aboutsummaryrefslogtreecommitdiff
path: root/misctools
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-08-28 21:28:05 -0700
committerGravatar GitHub <noreply@github.com> 2022-08-28 21:28:05 -0700
commitc1734c6ec5ef709ee4126b3474c7bee0a377a1fa (patch)
tree097710a13a1d85228efadf6d57823bb3a4f1c011 /misctools
parentb2141a204fbc351a40467037138168aea23a6930 (diff)
downloadbun-c1734c6ec5ef709ee4126b3474c7bee0a377a1fa.tar.gz
bun-c1734c6ec5ef709ee4126b3474c7bee0a377a1fa.tar.zst
bun-c1734c6ec5ef709ee4126b3474c7bee0a377a1fa.zip
More reliable macOS event loop (#1166)
* More reliable macOS event loop * Reduce CPU usage of idling * Add another implementation * Add benchmark Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'misctools')
-rw-r--r--misctools/machbench.zig137
1 files changed, 137 insertions, 0 deletions
diff --git a/misctools/machbench.zig b/misctools/machbench.zig
new file mode 100644
index 000000000..9c486f48a
--- /dev/null
+++ b/misctools/machbench.zig
@@ -0,0 +1,137 @@
+// most of this file is copy pasted from other files in misctools
+const std = @import("std");
+const bun = @import("../src/global.zig");
+const string = bun.string;
+const Output = bun.Output;
+const Global = bun.Global;
+const Environment = bun.Environment;
+const strings = bun.strings;
+const MutableString = bun.MutableString;
+const stringZ = bun.stringZ;
+const default_allocator = bun.default_allocator;
+const C = bun.C;
+const clap = @import("../src/deps/zig-clap/clap.zig");
+const AsyncIO = @import("io");
+
+const URL = @import("../src/url.zig").URL;
+const Headers = @import("http").Headers;
+const Method = @import("../src/http/method.zig").Method;
+const ColonListType = @import("../src/cli/colon_list_type.zig").ColonListType;
+const HeadersTuple = ColonListType(string, noop_resolver);
+const path_handler = @import("../src/resolver/resolve_path.zig");
+const NetworkThread = @import("http").NetworkThread;
+const HTTP = @import("http");
+fn noop_resolver(in: string) !string {
+ return in;
+}
+
+var waker: AsyncIO.Waker = undefined;
+
+fn spamMe(count: usize) void {
+ Output.Source.configureNamedThread("1");
+ defer Output.flush();
+ var timer = std.time.Timer.start() catch unreachable;
+
+ var i: usize = 0;
+ while (i < count) : (i += 1) {
+ waker.wake() catch unreachable;
+ }
+ Output.prettyErrorln("[EVFILT_MACHPORT] Sent {any}", .{bun.fmt.fmtDuration(timer.read())});
+}
+const thread_count = 1;
+pub fn machMain(runs: usize) anyerror!void {
+ defer Output.flush();
+ waker = try AsyncIO.Waker.init(bun.default_allocator);
+
+ var args = try std.process.argsAlloc(bun.default_allocator);
+ const count = std.fmt.parseInt(usize, args[args.len - 1], 10) catch 1024;
+ var elapsed: u64 = 0;
+
+ var remaining_runs: usize = runs;
+ while (remaining_runs > 0) : (remaining_runs -= 1) {
+ var threads: [thread_count]std.Thread = undefined;
+ var j: usize = 0;
+ while (j < thread_count) : (j += 1) {
+ threads[j] = try std.Thread.spawn(.{}, spamMe, .{count});
+ }
+
+ var timer = try std.time.Timer.start();
+ var i: usize = 0;
+ while (i < count * thread_count) : (i += 1) {
+ i += try waker.wait();
+ }
+
+ j = 0;
+ while (j < thread_count) : (j += 1) {
+ threads[j].join();
+ }
+ elapsed += timer.read();
+ }
+
+ Output.prettyErrorln("[EVFILT_MACHPORT] Recv {any}", .{bun.fmt.fmtDuration(elapsed)});
+}
+var user_waker: AsyncIO.UserFilterWaker = undefined;
+
+fn spamMeUserFilter(count: usize) void {
+ Output.Source.configureNamedThread("2");
+ defer Output.flush();
+ var timer = std.time.Timer.start() catch unreachable;
+ var i: usize = 0;
+ while (i < count * thread_count) : (i += 1) {
+ user_waker.wake() catch unreachable;
+ }
+
+ Output.prettyErrorln("[EVFILT_USER] Sent {any}", .{bun.fmt.fmtDuration(timer.read())});
+}
+pub fn userMain(runs: usize) anyerror!void {
+ defer Output.flush();
+ user_waker = try AsyncIO.UserFilterWaker.init(bun.default_allocator);
+
+ var args = try std.process.argsAlloc(bun.default_allocator);
+ const count = std.fmt.parseInt(usize, args[args.len - 1], 10) catch 1024;
+ var remaining_runs = runs;
+ var elapsed: u64 = 0;
+
+ while (remaining_runs > 0) : (remaining_runs -= 1) {
+ var threads: [thread_count]std.Thread = undefined;
+ var j: usize = 0;
+ while (j < thread_count) : (j += 1) {
+ threads[j] = try std.Thread.spawn(.{}, spamMeUserFilter, .{count});
+ }
+
+ var timer = try std.time.Timer.start();
+ var i: usize = 0;
+ while (i < count) {
+ i += try user_waker.wait();
+ }
+
+ j = 0;
+ while (j < thread_count) : (j += 1) {
+ threads[j].join();
+ }
+ elapsed += timer.read();
+ }
+
+ Output.prettyErrorln("[EVFILT_USER] Recv {any}", .{bun.fmt.fmtDuration(elapsed)});
+ Output.flush();
+}
+
+pub fn main() anyerror!void {
+ var stdout_ = std.io.getStdOut();
+ var stderr_ = std.io.getStdErr();
+ var output_source = Output.Source.init(stdout_, stderr_);
+ Output.Source.set(&output_source);
+
+ var args = try std.process.argsAlloc(bun.default_allocator);
+ const count = std.fmt.parseInt(usize, args[args.len - 1], 10) catch 1024;
+ Output.prettyErrorln("For {d} messages and {d} threads:", .{ count, thread_count });
+ Output.flush();
+ defer Output.flush();
+ const runs = if (std.os.getenv("RUNS")) |run_count| try std.fmt.parseInt(usize, run_count, 10) else 1;
+
+ if (std.os.getenv("NO_MACH") == null)
+ try machMain(runs);
+
+ if (std.os.getenv("NO_USER") == null)
+ try userMain(runs);
+}