Faster Buffer.toString("ascii")

This commit is contained in:
Jarred Sumner
2023-02-05 04:14:16 -08:00
parent df126b2f3b
commit e8fe6dd2f8

View File

@@ -796,15 +796,42 @@ pub const Encoder = struct {
switch (comptime encoding) {
.ascii => {
var to = allocator.alloc(u8, len) catch return ZigString.init("Out of memory").toErrorInstance(global);
var complete = to;
var remain = input;
@memcpy(to.ptr, input_ptr, to.len);
if (comptime bun.Environment.enableSIMD) {
const vector_size = 16;
// https://zig.godbolt.org/z/qezsY8T3W
var remain_in_u64 = remain[0 .. remain.len - (remain.len % vector_size)];
var to_in_u64 = to[0 .. to.len - (to.len % vector_size)];
var remain_as_u64 = std.mem.bytesAsSlice(u64, remain_in_u64);
var to_as_u64 = std.mem.bytesAsSlice(u64, to_in_u64);
const inner_vector_size = vector_size / 8;
const end_vector_len = @min(remain_as_u64.len, to_as_u64.len);
remain_as_u64 = remain_as_u64[0..end_vector_len];
to_as_u64 = to_as_u64[0..end_vector_len];
const end_ptr = remain_as_u64.ptr + remain_as_u64.len;
// using the pointer instead of the length is super important for the codegen
while (end_ptr != remain_as_u64.ptr) {
const buf = @as(@Vector(inner_vector_size, u64), remain_as_u64[0..inner_vector_size].*);
const mask = @splat(inner_vector_size, @as(u64, 0x7f7f7f7f7f7f7f7f));
to_as_u64[0..inner_vector_size].* = buf & mask;
// Hoping this gets auto vectorized
for (to[0..to.len]) |c, i| {
to[i] = @as(u8, @truncate(u7, c));
remain_as_u64 = remain_as_u64[inner_vector_size..];
to_as_u64 = to_as_u64[inner_vector_size..];
}
remain = remain[remain_in_u64.len..];
to = to[to_in_u64.len..];
}
return ZigString.init(to).toExternalValue(global);
const end_ptr = to.ptr + to.len;
while (to.ptr != end_ptr) {
to[0] = @as(u8, @truncate(u7, remain[0]));
to = to[1..];
remain = remain[1..];
}
return ZigString.init(complete).toExternalValue(global);
},
.latin1 => {
var to = allocator.alloc(u8, len) catch return ZigString.init("Out of memory").toErrorInstance(global);
@@ -919,7 +946,7 @@ pub const Encoder = struct {
if (slice.len == 0)
return 0;
if (slice.len > 1 and strings.eqlComptime(slice[slice.len - 2 ..][0..2], "==")) {
if (strings.endsWithComptime(slice, "==")) {
slice = slice[0 .. slice.len - 2];
} else if (slice[slice.len - 1] == '=') {
slice = slice[0 .. slice.len - 1];
@@ -1094,7 +1121,7 @@ pub const Encoder = struct {
if (slice.len == 0)
return &[_]u8{};
if (slice.len > 1 and strings.eqlComptime(slice[slice.len - 2 ..][0..2], "==")) {
if (strings.endsWithComptime(slice, "==")) {
slice = slice[0 .. slice.len - 2];
} else if (slice[slice.len - 1] == '=') {
slice = slice[0 .. slice.len - 1];