1const std = @import("std");
2const Io = std.Io;
3const time = std.time;
4const unicode = std.unicode;
5
6const N = 1_000_000;
7
8const KiB = 1024;
9const MiB = 1024 * KiB;
10const GiB = 1024 * MiB;
11
12const ResultCount = struct {
13 count: usize,
14 throughput: u64,
15};
16
17fn benchTime(io: Io) i96 {
18 return Io.Clock.awake.now(io).nanoseconds;
19}
20
21fn benchmarkCodepointCount(buf: []const u8, io: Io) !ResultCount {
22 const bytes = N * buf.len;
23
24 const start = benchTime(io);
25 var i: usize = 0;
26 var r: usize = undefined;
27 while (i < N) : (i += 1) {
28 r = try @call(
29 .never_inline,
30 std.unicode.utf8CountCodepoints,
31 .{buf},
32 );
33 }
34 const end = benchTime(io);
35
36 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
37 const throughput = @as(u64, @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s));
38
39 return ResultCount{ .count = r, .throughput = throughput };
40}
41
42pub fn main(init: std.process.Init) !void {
43 // Size of buffer is about size of printed message.
44 const io = init.io;
45 var stdout_buffer: [0x100]u8 = undefined;
46 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
47 const stdout = &stdout_writer.interface;
48
49 try stdout.print("short ASCII strings\n", .{});
50 try stdout.flush();
51 {
52 const result = try benchmarkCodepointCount("abc", io);
53 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
54 }
55
56 try stdout.print("short Unicode strings\n", .{});
57 try stdout.flush();
58 {
59 const result = try benchmarkCodepointCount("ŌŌŌ", io);
60 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
61 }
62
63 try stdout.print("pure ASCII strings\n", .{});
64 try stdout.flush();
65 {
66 const part = "hello";
67 const buf: [16][part.len]u8 = @splat(part.*);
68 const result = try benchmarkCodepointCount(@ptrCast(&buf), io);
69 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
70 }
71
72 try stdout.print("pure Unicode strings\n", .{});
73 try stdout.flush();
74 {
75 const part = "こんにちは";
76 const buf: [16][part.len]u8 = @splat(part.*);
77 const result = try benchmarkCodepointCount(@ptrCast(&buf), io);
78 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
79 }
80
81 try stdout.print("mixed ASCII/Unicode strings\n", .{});
82 try stdout.flush();
83 {
84 const part = "Hyvää huomenta";
85 const buf: [16][part.len]u8 = @splat(part.*);
86 const result = try benchmarkCodepointCount(@ptrCast(&buf), io);
87 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
88 }
89 try stdout.flush();
90}