bench: add client benchmark for js-framework-benchmark (#38)

This commit is contained in:
Mohabbat 2026-01-13 12:11:21 +06:00 committed by GitHub
parent cc06392f74
commit d1680e70fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 363 additions and 0 deletions

10
benches/client/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# Zig
.zig-cache
# zig-out
# ZX
/dist
/bundle
# Node.js
node_modules

28
benches/client/README.md Normal file
View File

@ -0,0 +1,28 @@
# ZX
This website is built with [ZX](https://github.com/nurulhudaapon/zx).
**[Full Documentation →](https://ziex.dev)**
## Installation of ZX
##### Linux/macOS
```bash
curl -fsSL https://ziex.dev/install | bash
```
##### Windows
```powershell
powershell -c "irm ziex.dev/install.ps1 | iex"
```
##### Installing Zig
```bash
brew install zig # macOS
winget install -e --id zig.zig # Windows
```
[_See for other platforms →_](https://ziglang.org/learn/getting-started/)
## Running this Project
```bash
zx serve
```

Binary file not shown.

32
benches/client/build.zig Normal file
View File

@ -0,0 +1,32 @@
const std = @import("std");
const zx = @import("zx");
pub fn build(b: *std.Build) !void {
// --- Target and Optimize from `zig build` arguments ---
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// --- Root Module ---
const mod = b.addModule("root_mod", .{
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
});
// --- ZX Setup (sets up ZX, dependencies, executables and `serve` step) ---
const site_exe = b.addExecutable(.{
.name = "zx_site",
.root_module = b.createModule(.{
.root_source_file = b.path("site/main.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "root_mod", .module = mod },
},
}),
});
_ = try zx.init(b, site_exe, .{
.experimental = .{ .enabled_csr = true },
});
}

View File

@ -0,0 +1,17 @@
.{
.name = .zx_site,
.version = "0.0.0",
.fingerprint = 0xc04151551dc3c31d,
.minimum_zig_version = "0.15.2",
.dependencies = .{
.zx = .{
.url = "git+https://github.com/nurulhudaapon/zx#a94b0efab6d9d2c30ccaa22eb80bb8051e76ee34",
.hash = "zx-0.1.0-dev.562-8okzKu7fgQAQaD7ebNtUdcIzmcdxEjtCvO3-GKhrojWv",
},
},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
},
}

BIN
benches/client/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html lang="en-US"><head><title>ZX</title><link href="/css/currentStyle.css" rel="stylesheet"></head><body><main><!--$c305245--><div class="container"><div class="jumbotron"><div class="row"><div class="col-md-6"><h1>ZX Client-Side keyed</h1></div><div class="col-md-6"><div class="row"><div class="col-sm-6 smallpad"><button type="button" class="btn btn-primary btn-block" id="run">Create 1,000 rows</button></div><div class="col-sm-6 smallpad"><button type="button" class="btn btn-primary btn-block" id="runlots">Create 10,000 rows</button></div><div class="col-sm-6 smallpad"><button type="button" class="btn btn-primary btn-block" id="add">Append 1,000 rows</button></div><div class="col-sm-6 smallpad"><button type="button" class="btn btn-primary btn-block" id="update">Update every 10th row</button></div><div class="col-sm-6 smallpad"><button type="button" class="btn btn-primary btn-block" id="clear">Clear</button></div><div class="col-sm-6 smallpad"><button type="button" class="btn btn-primary btn-block" id="swaprows">Swap Rows</button></div></div></div></div></div><table class="table table-hover table-striped test-data"><tbody></tbody></table><span class="preloadicon glyphicon glyphicon-remove" aria-hidden="true"></span></div><!--/$c305245--></main>
<script type="module">
import {init } from "https://cdn.jsdelivr.net/npm/ziex@0.1.0-dev.562/wasm/index.min.js";
init({url: "/frameworks/keyed/zx/assets/main.wasm"});
</script>
</body></html>

13
benches/client/package-lock.json generated Normal file
View File

@ -0,0 +1,13 @@
{
"name": "js-framework-benchmark-zx",
"version": "1.1.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "js-framework-benchmark-zx",
"version": "1.1.1",
"license": "Apache-2.0"
}
}
}

View File

@ -0,0 +1,27 @@
{
"name": "js-framework-benchmark-zx",
"version": "1.1.1",
"description": "Vanilla.JS demo",
"main": "index.js",
"js-framework-benchmark": {
"frameworkVersion": "",
"issues": [
772
]
},
"scripts": {
"dev": "exit 0",
"build-prod": "exit 0"
},
"keywords": [
"react",
"webpack"
],
"author": "Stefan Krause",
"license": "Apache-2.0",
"homepage": "https://github.com/krausest/js-framework-benchmark",
"repository": {
"type": "git",
"url": "https://github.com/krausest/js-framework-benchmark.git"
}
}

View File

@ -0,0 +1,34 @@
const meta = @import("zx_meta").meta;
const std = @import("std");
const zx = @import("zx");
const builtin = @import("builtin");
const config = zx.App.Config{ .server = .{}, .meta = meta };
pub fn main() !void {
if (zx.platform == .browser) return;
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer _ = gpa.deinit();
const app = try zx.App.init(allocator, config);
defer app.deinit();
app.info();
try app.start();
}
var client = zx.Client.init(
zx.client_allocator,
.{ .components = &@import("zx_components").components },
);
export fn mainClient() void {
if (zx.platform != .browser) return;
client.info();
client.renderAll();
}
pub const std_options = zx.std_options;

View File

@ -0,0 +1,17 @@
pub fn Layout(ctx: zx.LayoutContext, children: zx.Component) zx.Component {
return (
<html @allocator={ctx.arena} lang="en-US">
<head>
<title>ZX</title>
<link href="/css/currentStyle.css" rel="stylesheet"/>
</head>
<body>
{children}
<script src=`https://cdn.jsdelivr.net/npm/ziex@{zx.info.version_string}/wasm/init.min.js` />
</body>
</html>
);
}
const zx = @import("zx");

View File

@ -0,0 +1,174 @@
pub fn Page(ctx: zx.PageContext) zx.Component {
return (
<main @allocator={ctx.arena}>
<SimpleApp @rendering={.client} @allocator={ctx.arena} />
</main>
);
}
const Item = struct { id: u32, text: []const u8 };
pub fn SimpleApp(allocator: zx.Allocator) zx.Component {
return (
<div @{allocator} class="container">
<div class="jumbotron">
<div class="row">
<div class="col-md-6">
<h1>{"ZX Client-Side keyed"}</h1>
</div>
<div class="col-md-6">
<div class="row">
<Button onclick={create_rows} id="run" title="Create 1,000 rows" />
<Button onclick={create_large_rows} id="runlots" title="Create 10,000 rows" />
<Button onclick={append_rows} id="add" title="Append 1,000 rows" />
<Button onclick={updateRows} id="update" title="Update every 10th row" />
<Button onclick={clearRows} id="clear" title="Clear" />
<Button onclick={swapRows} id="swaprows" title="Swap Rows" />
</div>
</div>
</div>
</div>
<table class="table table-hover table-striped test-data">
<tbody>
{for (items.items) |item| (
<tr key={item.id}>
<td class="col-md-1">{item.id}</td>
<td class="col-md-4">
<a>{item.text}</a>
</td>
<td class="col-md-1">
<a>
<span class="glyphicon glyphicon-remove" aria-hidden="true" />
</a>
</td>
<td class="col-md-6" />
</tr>
)}
</tbody>
</table>
<span class="preloadicon glyphicon glyphicon-remove" aria-hidden="true" />
</div>
);
}
const ButtonProps = struct { onclick: *const fn (zx.EventContext) void, title: []const u8, id: []const u8 };
fn Button(ctx: *zx.ComponentCtx(ButtonProps)) zx.Component {
return (
<div @allocator={ctx.allocator} class="col-sm-6 smallpad">
<button type="button" class="btn btn-primary btn-block" onclick={ctx.props.onclick} id={ctx.props.id}>
{ctx.props.title}
</button>
</div>
);
}
var next_id: u32 = 1;
var items = std.ArrayList(Item).empty;
fn clearRows(_: zx.EventContext) void {
items.clearRetainingCapacity();
next_id = 1;
zx.requestRender();
}
fn swapRows(_: zx.EventContext) void {
if (items.items.len > 998) {
const tmp = items.items[1];
items.items[1] = items.items[998];
items.items[998] = tmp;
zx.requestRender();
}
}
fn updateRows(_: zx.EventContext) void {
var i: usize = 0;
while (i < items.items.len) : (i += 10) {
const item = &items.items[i];
const new_text = std.fmt.allocPrint(zx.client_allocator, "{s} !!!", .{item.text}) catch @panic("OOM");
item.text = new_text;
}
zx.requestRender();
}
var seed: u32 = 12345;
fn RandomNumber(max: u32) u32 {
seed = seed *% 1103515245 +% 12345;
return seed % max;
}
const adjectives = [_][]const u8{
"pretty",
"large",
"big",
"small",
"tall",
"short",
"long",
"handsome",
"plain",
"quaint",
"clean",
"elegant",
"easy",
"angry",
"crazy",
"helpful",
"mushy",
"odd",
"unsightly",
"adorable",
"important",
"inexpensive",
"cheap",
"expensive",
"fancy",
};
const colours = [_][]const u8{ "red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange" };
const nouns = [_][]const u8{ "table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard" };
fn BuildRows(count_to_add: u32, clear_first: bool) void {
std.log.info("BuildRows called with count_to_add: {d}", .{count_to_add});
if (clear_first) {
items.clearRetainingCapacity();
next_id = 1;
}
for (0..count_to_add) |_| {
const text = std.fmt.allocPrint(zx.client_allocator, "{s} {s} {s}", .{ adjectives[RandomNumber(adjectives.len)], colours[RandomNumber(colours.len)], nouns[RandomNumber(nouns.len)] }) catch @panic("OOM");
const item = Item{
.id = next_id,
.text = text,
};
items.append(zx.client_allocator, item) catch @panic("OOM");
next_id += 1;
}
std.log.info("Total items after BuildRows: {d}", .{items.items.len});
zx.requestRender();
std.log.info("after: {d}", .{items.items.len});
// count.set(@intCast(items.items.len));
}
fn create_rows(_: zx.EventContext) void {
BuildRows(1000, true);
}
fn create_large_rows(_: zx.EventContext) void {
BuildRows(10000, true);
}
fn append_rows(_: zx.EventContext) void {
BuildRows(1000, false);
}
const zx = @import("zx");
const std = @import("std");

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,3 @@
pub fn get_about_zx() []const u8 {
return "ZX is a framework for building web applications with Zig.";
}