mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-14 15:28:57 +00:00
Merge pull request #1195 from lightpanda-io/nikneym/blob-simd
Some checks failed
e2e-test / zig build release (push) Has been cancelled
zig-test / zig build dev (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
zig-test / browser fetch (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
nightly build / build-linux-x86_64 (push) Has been cancelled
nightly build / build-linux-aarch64 (push) Has been cancelled
nightly build / build-macos-aarch64 (push) Has been cancelled
nightly build / build-macos-x86_64 (push) Has been cancelled
wpt / web platform tests json output (push) Has been cancelled
wpt / perf-fmt (push) Has been cancelled
Some checks failed
e2e-test / zig build release (push) Has been cancelled
zig-test / zig build dev (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
zig-test / browser fetch (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
nightly build / build-linux-x86_64 (push) Has been cancelled
nightly build / build-linux-aarch64 (push) Has been cancelled
nightly build / build-macos-aarch64 (push) Has been cancelled
nightly build / build-macos-x86_64 (push) Has been cancelled
wpt / web platform tests json output (push) Has been cancelled
wpt / perf-fmt (push) Has been cancelled
This commit is contained in:
@@ -72,6 +72,26 @@ pub fn constructor(
|
||||
return .{ .slice = "", .mime = mime };
|
||||
}
|
||||
|
||||
const largest_vector = @max(std.simd.suggestVectorLength(u8) orelse 1, 8);
|
||||
/// Array of possible vector sizes for the current arch in decrementing order.
|
||||
/// We may move this to some file for SIMD helpers in the future.
|
||||
const vector_sizes = blk: {
|
||||
// Required for length calculation.
|
||||
var n: usize = largest_vector;
|
||||
var total: usize = 0;
|
||||
while (n != 2) : (n /= 2) total += 1;
|
||||
// Populate an array with vector sizes.
|
||||
n = largest_vector;
|
||||
var i: usize = 0;
|
||||
var items: [total]usize = undefined;
|
||||
while (n != 2) : (n /= 2) {
|
||||
defer i += 1;
|
||||
items[i] = n;
|
||||
}
|
||||
|
||||
break :blk items;
|
||||
};
|
||||
|
||||
/// Writes blob parts to given `Writer` with desired endings.
|
||||
fn writeBlobParts(
|
||||
writer: *Writer,
|
||||
@@ -88,7 +108,6 @@ fn writeBlobParts(
|
||||
}
|
||||
|
||||
// TODO: Windows support.
|
||||
// TODO: Vector search.
|
||||
|
||||
// Linux & Unix.
|
||||
// Both Firefox and Chrome implement it as such:
|
||||
@@ -108,10 +127,44 @@ fn writeBlobParts(
|
||||
// ```
|
||||
scan_parts: for (blob_parts) |part| {
|
||||
var end: usize = 0;
|
||||
var start = end;
|
||||
|
||||
inline for (vector_sizes) |vector_len| {
|
||||
const Vec = @Vector(vector_len, u8);
|
||||
|
||||
while (end + vector_len <= part.len) : (end += vector_len) {
|
||||
const cr: Vec = @splat('\r');
|
||||
// Load chunk as vectors.
|
||||
const slice = part[end..][0..vector_len];
|
||||
const chunk: Vec = slice.*;
|
||||
// Look for CR.
|
||||
const match = chunk == cr;
|
||||
|
||||
// Create a bitset out of match vector.
|
||||
const bitset = std.bit_set.IntegerBitSet(vector_len){
|
||||
.mask = @bitCast(@intFromBool(match)),
|
||||
};
|
||||
|
||||
var iter = bitset.iterator(.{});
|
||||
var relative_start: usize = 0;
|
||||
while (iter.next()) |index| {
|
||||
_ = try writer.writeVec(&.{ slice[relative_start..index], "\n" });
|
||||
|
||||
if (index + 1 != slice.len and slice[index + 1] == '\n') {
|
||||
relative_start = index + 2;
|
||||
} else {
|
||||
relative_start = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
_ = try writer.writeVec(&.{slice[relative_start..]});
|
||||
}
|
||||
}
|
||||
|
||||
// Scalar scan fallback.
|
||||
var relative_start: usize = end;
|
||||
while (end < part.len) {
|
||||
if (part[end] == '\r') {
|
||||
_ = try writer.writeVec(&.{ part[start..end], "\n" });
|
||||
_ = try writer.writeVec(&.{ part[relative_start..end], "\n" });
|
||||
|
||||
// Part ends with CR. We can continue to next part.
|
||||
if (end + 1 == part.len) {
|
||||
@@ -120,9 +173,9 @@ fn writeBlobParts(
|
||||
|
||||
// If next char is LF, skip it too.
|
||||
if (part[end + 1] == '\n') {
|
||||
start = end + 2;
|
||||
relative_start = end + 2;
|
||||
} else {
|
||||
start = end + 1;
|
||||
relative_start = end + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +185,7 @@ fn writeBlobParts(
|
||||
// Write the remaining. We get this in such situations:
|
||||
// `the quick brown\rfox`
|
||||
// `the quick brown\r\nfox`
|
||||
try writer.writeAll(part[start..end]);
|
||||
try writer.writeAll(part[relative_start..end]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,4 +86,40 @@
|
||||
testing.expectEqual(expected, result);
|
||||
});
|
||||
}
|
||||
|
||||
// Test for SIMD.
|
||||
{
|
||||
const parts = [
|
||||
"\rThe opened package\r\nof potato\nchi\rps",
|
||||
"held the\r\nanswer to the\r mystery. Both det\rectives looke\r\rd\r",
|
||||
"\rat it but failed to realize\nit was\r\nthe\rkey\r\n",
|
||||
"\r\nto solve the \rcrime.\r"
|
||||
];
|
||||
|
||||
const blob = new Blob(parts, { type: "text/html", endings: "native" });
|
||||
testing.expectEqual(161, blob.size);
|
||||
testing.expectEqual("text/html", blob.type);
|
||||
testing.async(blob.bytes(), result => {
|
||||
const expected = new Uint8Array([10, 84, 104, 101, 32, 111, 112, 101, 110,
|
||||
101, 100, 32, 112, 97, 99, 107, 97, 103,
|
||||
101, 10, 111, 102, 32, 112, 111, 116, 97,
|
||||
116, 111, 10, 99, 104, 105, 10, 112, 115,
|
||||
104, 101, 108, 100, 32, 116, 104, 101, 10,
|
||||
97, 110, 115, 119, 101, 114, 32, 116, 111,
|
||||
32, 116, 104, 101, 10, 32, 109, 121, 115,
|
||||
116, 101, 114, 121, 46, 32, 66, 111, 116,
|
||||
104, 32, 100, 101, 116, 10, 101, 99, 116,
|
||||
105, 118, 101, 115, 32, 108, 111, 111, 107,
|
||||
101, 10, 10, 100, 10, 10, 97, 116, 32, 105,
|
||||
116, 32, 98, 117, 116, 32, 102, 97, 105, 108,
|
||||
101, 100, 32, 116, 111, 32, 114, 101, 97,
|
||||
108, 105, 122, 101, 10, 105, 116, 32, 119, 97,
|
||||
115, 10, 116, 104, 101, 10, 107, 101, 121,
|
||||
10, 10, 116, 111, 32, 115, 111, 108, 118, 101,
|
||||
32, 116, 104, 101, 32, 10, 99, 114, 105, 109,
|
||||
101, 46, 10]);
|
||||
testing.expectEqual(true, result instanceof Uint8Array);
|
||||
testing.expectEqual(expected, result);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user