-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add more benchmarks #11
base: main
Are you sure you want to change the base?
Conversation
Before: name time std iterations --------------------------------------------------------------------------------------------------------------------- NonBlockingThreadPool: join, one level 690.0 ns ± 163522.04859994436 76147 NonBlockingThreadPool: join, two levels 2064.0 ns ± 316859.10411173315 15613 NonBlockingThreadPool: join, three levels 4941.0 ns ± 351192.3836080291 11462 NonBlockingThreadPool: join, four levels, three on thread pool thread 6369.0 ns ± 400867.0104087665 8426 NonBlockingThreadPool: parallel for, one level 2862068.0 ns ± 395500.70262353314 509 NonBlockingThreadPool: parallel for, two levels 2609616.5 ns ± 251679.60080760892 486 NonBlockingThreadPool: parallel for, one level, grain size 10 345706.0 ns ± 247728.9607701072 2859 NonBlockingThreadPool: parallel for, one level, grain size 100 142316.0 ns ± 292455.2283264145 4417 NonBlockingThreadPool: parallel for, one level, grain size 1000 78977.0 ns ± 214052.89967520352 6321 NonBlockingThreadPool: parallel for, one level, grain size 2000 50729.0 ns ± 164390.21843606833 7247 NonBlockingThreadPool: parallel for, one level, grain size 5000 39656.0 ns ± 190176.9821963313 8649 NonBlockingThreadPool: parallel for, two levels, grain size 10 & 100 1657159.5 ns ± 806196.7324534839 842 NonBlockingThreadPool: dispatch concurrent perform, one level 237865.0 ns ± 21098.405428758302 6223 NonBlockingThreadPool: dispatch concurrent perform, two levels 40180.0 ns ± 5290.912573146778 38178 NonBlockingThreadPool: sequential one level 370.0 ns ± 224.22220630175732 1000000 NonBlockingThreadPool: sequential two levels 485.0 ns ± 279.54687747682283 1000000 After: name time std iterations --------------------------------------------------------------------------------------------------------------------- NonBlockingThreadPool: join, one level 484.0 ns ± 161129.49945627034 78655 NonBlockingThreadPool: join, two levels 1446.0 ns ± 255823.17176138048 29165 NonBlockingThreadPool: join, three levels 3369.0 ns ± 244942.08954270577 21109 NonBlockingThreadPool: join, four levels, three on thread pool thread 3833.0 ns ± 270662.97199023387 15008 NonBlockingThreadPool: parallel for, one level 2661959.0 ns ± 360213.96138696355 543 NonBlockingThreadPool: parallel for, two levels 2469215.5 ns ± 334972.7168585615 538 NonBlockingThreadPool: parallel for, one level, grain size 10 327907.0 ns ± 473609.1412896736 2708 NonBlockingThreadPool: parallel for, one level, grain size 100 125174.5 ns ± 329418.62320991984 3934 NonBlockingThreadPool: parallel for, one level, grain size 1000 73999.0 ns ± 238626.6115465731 6940 NonBlockingThreadPool: parallel for, one level, grain size 2000 50771.0 ns ± 205223.8350497277 7089 NonBlockingThreadPool: parallel for, one level, grain size 5000 26571.5 ns ± 220587.47147580027 8398 NonBlockingThreadPool: parallel for, two levels, grain size 10 & 100 1162189.0 ns ± 940733.3616910677 991 NonBlockingThreadPool: dispatch concurrent perform, one level 247549.0 ns ± 23605.70739546625 5815 NonBlockingThreadPool: dispatch concurrent perform, two levels 41744.0 ns ± 6449.1291628621575 33719 NonBlockingThreadPool: sequential one level 402.0 ns ± 170.32164151542221 1000000 NonBlockingThreadPool: sequential two levels 466.0 ns ± 195.13074674728864 1000000
} else { | ||
wakeupWorkerIfRequired() | ||
} | ||
} else { | ||
// Called not from within the threadpool; pick a victim thread from the pool at random. | ||
// TODO: use a faster RNG! | ||
let victim = Int.random(in: 0..<queues.count) | ||
if let bounced = queues[victim].pushBack(fn) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought you were against victim
. It's not API, but still? Personally, I have no objections, but why waste an opportunity to give you a hard time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-D
} else { | ||
wakeupWorkerIfRequired() | ||
|
||
// Execute local half using recurion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Execute local half using recurion. | |
// Execute local half using recursion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice if you'd add some comments describing what you're trying to measure and why. That would make it possible for me to evaluate the code without guessing at intent, and would provide guideposts for future benchmarks
} | ||
|
||
fileprivate func executeJoinTask(_ task: UnsafeMutablePointer<JoinTask>) { | ||
assert(!task.pointee.isDoneAcquiring(), "Join task done before even starting execution?!?") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to use assert
in benchmarking code, given that it will be compiled away in release mode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, not quite sure I follow? I do intentionally want to use an assert
because I do want it compiled away in release mode. But having these asserts sprinkled throughout the code has been helpful in ensuring the implementation is correct during testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine! I was just asking.
It looks like a lot of what happens in this PR is not just adding benchmarking. Can it be broken into smaller units or at least more completely described? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to move this into draft form. I'm not ready for it to go in. Thanks for the comments! I appreciate them.
} else { | ||
wakeupWorkerIfRequired() | ||
} | ||
} else { | ||
// Called not from within the threadpool; pick a victim thread from the pool at random. | ||
// TODO: use a faster RNG! | ||
let victim = Int.random(in: 0..<queues.count) | ||
if let bounced = queues[victim].pushBack(fn) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-D
} | ||
|
||
fileprivate func executeJoinTask(_ task: UnsafeMutablePointer<JoinTask>) { | ||
assert(!task.pointee.isDoneAcquiring(), "Join task done before even starting execution?!?") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, not quite sure I follow? I do intentionally want to use an assert
because I do want it compiled away in release mode. But having these asserts sprinkled throughout the code has been helpful in ensuring the implementation is correct during testing.
No description provided.