mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-30 07:31:47 +00:00
performance now
This commit is contained in:
@@ -251,7 +251,7 @@ pub const Page = struct {
|
|||||||
fn init(self: *Page, arena: Allocator, session: *Session) !void {
|
fn init(self: *Page, arena: Allocator, session: *Session) !void {
|
||||||
const browser = session.browser;
|
const browser = session.browser;
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.window = .{},
|
.window = try Window.create(null, null), // TODO why do we not call Window.create()?
|
||||||
.arena = arena,
|
.arena = arena,
|
||||||
.doc = null,
|
.doc = null,
|
||||||
.raw_data = null,
|
.raw_data = null,
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ const Navigator = @import("navigator.zig").Navigator;
|
|||||||
const History = @import("history.zig").History;
|
const History = @import("history.zig").History;
|
||||||
const Location = @import("location.zig").Location;
|
const Location = @import("location.zig").Location;
|
||||||
const MediaQueryList = @import("media_query_list.zig").MediaQueryList;
|
const MediaQueryList = @import("media_query_list.zig").MediaQueryList;
|
||||||
|
const Performance = @import("performance.zig").Performance;
|
||||||
|
|
||||||
pub const Interfaces = .{
|
pub const Interfaces = .{
|
||||||
HTMLDocument,
|
HTMLDocument,
|
||||||
@@ -36,4 +37,5 @@ pub const Interfaces = .{
|
|||||||
History,
|
History,
|
||||||
Location,
|
Location,
|
||||||
MediaQueryList,
|
MediaQueryList,
|
||||||
|
Performance,
|
||||||
};
|
};
|
||||||
|
|||||||
87
src/browser/html/performance.zig
Normal file
87
src/browser/html/performance.zig
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// Copyright (C) 2023-2025 Lightpanda (Selecy SAS)
|
||||||
|
//
|
||||||
|
// Francis Bouvier <francis@lightpanda.io>
|
||||||
|
// Pierre Tachoire <pierre@lightpanda.io>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const parser = @import("../netsurf.zig");
|
||||||
|
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
||||||
|
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Performance
|
||||||
|
pub const Performance = struct {
|
||||||
|
pub const prototype = *EventTarget;
|
||||||
|
|
||||||
|
// Extend libdom event target for pure zig struct.
|
||||||
|
base: parser.EventTargetTBase = parser.EventTargetTBase{},
|
||||||
|
|
||||||
|
time_origin: std.time.Timer,
|
||||||
|
// if (Window.crossOriginIsolated) -> Resolution in isolated contexts: 5 microseconds
|
||||||
|
// else -> Resolution in non-isolated contexts: 100 microseconds
|
||||||
|
const ms_resolution = 100;
|
||||||
|
|
||||||
|
fn limited_resolution_ms(nanoseconds: u64) f64 {
|
||||||
|
const elapsed_at_resolution = ((nanoseconds / std.time.ns_per_ms) + ms_resolution / 2) / ms_resolution * ms_resolution;
|
||||||
|
const elapsed = @as(f64, @floatFromInt(elapsed_at_resolution));
|
||||||
|
return elapsed / @as(f64, std.time.us_per_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_timeOrigin(self: *const Performance) f64 {
|
||||||
|
const is_posix = switch (@import("builtin").os.tag) { // From std.time.zig L125
|
||||||
|
.windows, .uefi, .wasi => false,
|
||||||
|
else => true,
|
||||||
|
};
|
||||||
|
const zero = std.time.Instant{ .timestamp = if (!is_posix) 0 else .{ .sec = 0, .nsec = 0 } };
|
||||||
|
const started = self.time_origin.started.since(zero);
|
||||||
|
return limited_resolution_ms(started);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _now(self: *Performance) f64 {
|
||||||
|
return limited_resolution_ms(self.time_origin.read());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const testing = @import("./../../testing.zig");
|
||||||
|
|
||||||
|
test "Performance: get_timeOrigin" {
|
||||||
|
var perf = Performance{ .time_origin = try std.time.Timer.start() };
|
||||||
|
const time_origin = perf.get_timeOrigin();
|
||||||
|
try testing.expect(time_origin >= 0);
|
||||||
|
|
||||||
|
// Check resolution
|
||||||
|
try testing.expectDelta(@rem(time_origin * std.time.us_per_ms, 100.0), 0.0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "Performance: now" {
|
||||||
|
var perf = Performance{ .time_origin = try std.time.Timer.start() };
|
||||||
|
|
||||||
|
// Monotonically increasing
|
||||||
|
var now = perf._now();
|
||||||
|
while (now <= 0) { // Loop for now to not be 0
|
||||||
|
try testing.expect(now == 0);
|
||||||
|
now = perf._now();
|
||||||
|
}
|
||||||
|
// Check resolution
|
||||||
|
try testing.expectDelta(@rem(now * std.time.us_per_ms, 100.0), 0.0, 0.1);
|
||||||
|
|
||||||
|
var after = perf._now();
|
||||||
|
while (after <= now) { // Loop untill after > now
|
||||||
|
try testing.expect(after == now);
|
||||||
|
after = perf._now();
|
||||||
|
}
|
||||||
|
// Check resolution
|
||||||
|
try testing.expectDelta(@rem(after * std.time.us_per_ms, 100.0), 0.0, 0.1);
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ const Crypto = @import("../crypto/crypto.zig").Crypto;
|
|||||||
const Console = @import("../console/console.zig").Console;
|
const Console = @import("../console/console.zig").Console;
|
||||||
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
||||||
const MediaQueryList = @import("media_query_list.zig").MediaQueryList;
|
const MediaQueryList = @import("media_query_list.zig").MediaQueryList;
|
||||||
|
const Performance = @import("performance.zig").Performance;
|
||||||
|
|
||||||
const storage = @import("../storage/storage.zig");
|
const storage = @import("../storage/storage.zig");
|
||||||
|
|
||||||
@@ -56,11 +57,13 @@ pub const Window = struct {
|
|||||||
crypto: Crypto = .{},
|
crypto: Crypto = .{},
|
||||||
console: Console = .{},
|
console: Console = .{},
|
||||||
navigator: Navigator = .{},
|
navigator: Navigator = .{},
|
||||||
|
performance: Performance,
|
||||||
|
|
||||||
pub fn create(target: ?[]const u8, navigator: ?Navigator) Window {
|
pub fn create(target: ?[]const u8, navigator: ?Navigator) !Window {
|
||||||
return .{
|
return .{
|
||||||
.target = target orelse "",
|
.target = target orelse "",
|
||||||
.navigator = navigator orelse .{},
|
.navigator = navigator orelse .{},
|
||||||
|
.performance = .{ .time_origin = try std.time.Timer.start() },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +75,7 @@ pub const Window = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn replaceDocument(self: *Window, doc: *parser.DocumentHTML) !void {
|
pub fn replaceDocument(self: *Window, doc: *parser.DocumentHTML) !void {
|
||||||
|
self.performance.time_origin.reset(); // When to reset see: https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin
|
||||||
self.document = doc;
|
self.document = doc;
|
||||||
try parser.documentHTMLSetLocation(Location, doc, &self.location);
|
try parser.documentHTMLSetLocation(Location, doc, &self.location);
|
||||||
}
|
}
|
||||||
@@ -130,6 +134,10 @@ pub const Window = struct {
|
|||||||
return &self.storage_shelf.?.bucket.session;
|
return &self.storage_shelf.?.bucket.session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_performance(self: *Window) *Performance {
|
||||||
|
return &self.performance;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO handle callback arguments.
|
// TODO handle callback arguments.
|
||||||
pub fn _setTimeout(self: *Window, cbk: Callback, delay: ?u32, state: *SessionState) !u32 {
|
pub fn _setTimeout(self: *Window, cbk: Callback, delay: ?u32, state: *SessionState) !u32 {
|
||||||
return self.createTimeout(cbk, delay, state, false);
|
return self.createTimeout(cbk, delay, state, false);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const parser = @import("../browser/netsurf.zig");
|
|||||||
const base = @import("../testing.zig");
|
const base = @import("../testing.zig");
|
||||||
pub const allocator = base.allocator;
|
pub const allocator = base.allocator;
|
||||||
pub const expectJson = base.expectJson;
|
pub const expectJson = base.expectJson;
|
||||||
|
pub const expect = std.testing.expect;
|
||||||
pub const expectEqual = base.expectEqual;
|
pub const expectEqual = base.expectEqual;
|
||||||
pub const expectError = base.expectError;
|
pub const expectError = base.expectError;
|
||||||
pub const expectEqualSlices = base.expectEqualSlices;
|
pub const expectEqualSlices = base.expectEqualSlices;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ const Allocator = std.mem.Allocator;
|
|||||||
|
|
||||||
pub const allocator = std.testing.allocator;
|
pub const allocator = std.testing.allocator;
|
||||||
pub const expectError = std.testing.expectError;
|
pub const expectError = std.testing.expectError;
|
||||||
|
pub const expect = std.testing.expect;
|
||||||
pub const expectString = std.testing.expectEqualStrings;
|
pub const expectString = std.testing.expectEqualStrings;
|
||||||
pub const expectEqualSlices = std.testing.expectEqualSlices;
|
pub const expectEqualSlices = std.testing.expectEqualSlices;
|
||||||
|
|
||||||
@@ -421,7 +422,7 @@ pub const JsRunner = struct {
|
|||||||
.http_client = &self.http_client,
|
.http_client = &self.http_client,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.window = .{};
|
self.window = try Window.create(null, null);
|
||||||
try self.window.replaceDocument(document);
|
try self.window.replaceDocument(document);
|
||||||
try self.window.replaceLocation(.{
|
try self.window.replaceLocation(.{
|
||||||
.url = try self.url.toWebApi(arena),
|
.url = try self.url.toWebApi(arena),
|
||||||
|
|||||||
Reference in New Issue
Block a user