mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 12:44:43 +00:00
Change CData._data from []const to String (SSO)
After looking at a handful of websites, the # of Text and Commend nodes that are small (<= 12 bytes) is _really_ high. Ranging from 85% to 98%. I thought that was high, but a lot of it is indentation or a sentence that's broken down into multiple nodes, eg: <div><b>sale!</b> <span class=price>$1.99</span> buy now<div> So what looks like 1 sentence to us, is actually 3 text nodes. On a typical website, we should see thousands of fewer allocations in the page arena for the text in text nodes.
This commit is contained in:
147
src/string.zig
147
src/string.zig
@@ -111,6 +111,38 @@ pub const String = packed struct {
|
||||
return .init(allocator, self.str(), .{ .dupe = true });
|
||||
}
|
||||
|
||||
pub fn concat(allocator: Allocator, parts: []const []const u8) !String {
|
||||
var total_len: usize = 0;
|
||||
for (parts) |part| {
|
||||
total_len += part.len;
|
||||
}
|
||||
|
||||
if (total_len <= 12) {
|
||||
var content: [12]u8 = @splat(0);
|
||||
var pos: usize = 0;
|
||||
for (parts) |part| {
|
||||
@memcpy(content[pos..][0..part.len], part);
|
||||
pos += part.len;
|
||||
}
|
||||
return .{ .len = @intCast(total_len), .payload = .{ .content = content } };
|
||||
}
|
||||
|
||||
const result = try allocator.alloc(u8, total_len);
|
||||
var pos: usize = 0;
|
||||
for (parts) |part| {
|
||||
@memcpy(result[pos..][0..part.len], part);
|
||||
pos += part.len;
|
||||
}
|
||||
|
||||
return .{
|
||||
.len = @intCast(total_len),
|
||||
.payload = .{ .heap = .{
|
||||
.prefix = result[0..4].*,
|
||||
.ptr = (intern(result) orelse result).ptr,
|
||||
} },
|
||||
};
|
||||
}
|
||||
|
||||
pub fn str(self: *const String) []const u8 {
|
||||
const l = self.len;
|
||||
if (l < 0) {
|
||||
@@ -272,3 +304,118 @@ test "String" {
|
||||
try testing.expectEqual(false, str.eqlSlice("other_long" ** 100));
|
||||
}
|
||||
}
|
||||
|
||||
test "String.concat" {
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{});
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual(@as(usize, 0), result.str().len);
|
||||
try testing.expectEqual("", result.str());
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{"hello"});
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("hello", result.str());
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ "foo", "bar" });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("foobar", result.str());
|
||||
try testing.expectEqual(@as(i32, 6), result.len);
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ "test", "ing", "1234" });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("testing1234", result.str());
|
||||
try testing.expectEqual(@as(i32, 11), result.len);
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ "foo", "bar", "baz", "qux" });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("foobarbazqux", result.str());
|
||||
try testing.expectEqual(@as(i32, 12), result.len);
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ "hello", " world!" });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("hello world!", result.str());
|
||||
try testing.expectEqual(@as(i32, 12), result.len);
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ "a", "b", "c", "d", "e" });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("abcde", result.str());
|
||||
try testing.expectEqual(@as(i32, 5), result.len);
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ "one", " ", "two", " ", "three", " ", "four" });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("one two three four", result.str());
|
||||
try testing.expectEqual(@as(i32, 18), result.len);
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ "hello", "", "world" });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("helloworld", result.str());
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ "", "", "" });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("", result.str());
|
||||
try testing.expectEqual(@as(i32, 0), result.len);
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ "café", " ☕" });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("café ☕", result.str());
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ "Hello ", "世界", " and ", "مرحبا" });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("Hello 世界 and مرحبا", result.str());
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ " ", "test", " " });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual(" test ", result.str());
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ " ", " " });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual(" ", result.str());
|
||||
try testing.expectEqual(@as(i32, 4), result.len);
|
||||
}
|
||||
|
||||
{
|
||||
const result = try String.concat(testing.allocator, &.{ "Item ", "1", "2", "3" });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("Item 123", result.str());
|
||||
}
|
||||
|
||||
{
|
||||
const original = "Hello, world!";
|
||||
const result = try String.concat(testing.allocator, &.{ original[0..5], original[7..] });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("Helloworld!", result.str());
|
||||
}
|
||||
|
||||
{
|
||||
const original = "Hello!";
|
||||
const result = try String.concat(testing.allocator, &.{ original[0..5], " world", original[5..] });
|
||||
defer result.deinit(testing.allocator);
|
||||
try testing.expectEqual("Hello world!", result.str());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user