Skip to content

Performance Domain

The Performance domain provides methods for collecting performance metrics.

Import

zig
const cdp = @import("cdp");
const Performance = cdp.Performance;

Initialization

zig
var session = try browser.newPage();
var performance = Performance.init(session);
try performance.enable();

Methods

enable

Enable performance metrics collection.

zig
pub fn enable(self: *Performance) !void

disable

Disable performance metrics collection.

zig
pub fn disable(self: *Performance) !void

getMetrics

Get current performance metrics.

zig
pub fn getMetrics(self: *Performance, allocator: Allocator) ![]Metric

Returns: Slice of metrics (caller must free)

Example:

zig
const metrics = try performance.getMetrics(allocator);
defer {
    for (metrics) |*m| m.deinit(allocator);
    allocator.free(metrics);
}

for (metrics) |m| {
    std.debug.print("{s}: {d}\n", .{m.name, m.value});
}

Types

Metric

zig
pub const Metric = struct {
    name: []const u8,
    value: f64,

    pub fn deinit(self: *Metric, allocator: Allocator) void;
};

Available Metrics

MetricDescription
TimestampCurrent timestamp
DocumentsNumber of documents
FramesNumber of frames
JSEventListenersJS event listener count
NodesDOM node count
LayoutCountLayout operations
RecalcStyleCountStyle recalculations
LayoutDurationLayout time (seconds)
RecalcStyleDurationStyle recalc time
ScriptDurationScript execution time
TaskDurationTask execution time
JSHeapUsedSizeJS heap used (bytes)
JSHeapTotalSizeJS heap total (bytes)

Complete Example

zig
const std = @import("std");
const cdp = @import("cdp");

pub fn main(init: std.process.Init) !void {
    const allocator = init.gpa;

    var browser = try cdp.Browser.launch(.{
        .headless = .new,
        .allocator = allocator,
        .io = init.io,
    });
    defer browser.close();

    var session = try browser.newPage();
    defer session.detach() catch {};

    var page = cdp.Page.init(session);
    var performance = cdp.Performance.init(session);
    
    try page.enable();
    try performance.enable();

    _ = try page.navigate(allocator, "https://example.com");

    // Wait for load
    var i: u32 = 0;
    while (i < 500000) : (i += 1) {
        std.atomic.spinLoopHint();
    }

    // Get metrics
    const metrics = try performance.getMetrics(allocator);
    defer {
        for (metrics) |*m| m.deinit(allocator);
        allocator.free(metrics);
    }

    std.debug.print("Performance Metrics:\n", .{});
    for (metrics) |m| {
        // Format based on metric type
        if (std.mem.endsWith(u8, m.name, "Duration")) {
            std.debug.print("  {s}: {d:.3}s\n", .{m.name, m.value});
        } else if (std.mem.endsWith(u8, m.name, "Size")) {
            std.debug.print("  {s}: {d:.0} bytes\n", .{m.name, m.value});
        } else {
            std.debug.print("  {s}: {d:.0}\n", .{m.name, m.value});
        }
    }
}

Performance Analysis

Memory Usage

zig
const metrics = try performance.getMetrics(allocator);
defer { /* cleanup */ };

for (metrics) |m| {
    if (std.mem.eql(u8, m.name, "JSHeapUsedSize")) {
        const mb = m.value / 1024 / 1024;
        std.debug.print("JS Heap: {d:.2} MB\n", .{mb});
    }
}

Rendering Performance

zig
for (metrics) |m| {
    if (std.mem.eql(u8, m.name, "LayoutDuration")) {
        std.debug.print("Layout: {d:.3}s\n", .{m.value});
    }
    if (std.mem.eql(u8, m.name, "RecalcStyleDuration")) {
        std.debug.print("Style: {d:.3}s\n", .{m.value});
    }
}

Script Performance

zig
for (metrics) |m| {
    if (std.mem.eql(u8, m.name, "ScriptDuration")) {
        std.debug.print("Script execution: {d:.3}s\n", .{m.value});
    }
    if (std.mem.eql(u8, m.name, "TaskDuration")) {
        std.debug.print("Task execution: {d:.3}s\n", .{m.value});
    }
}

Released under the MIT License.