-
Notifications
You must be signed in to change notification settings - Fork 195
Fix running benchmarks (Issue 1386) #1393
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import Benchmark | ||
|
||
let benchmarks = { | ||
calendarBenchmarks() | ||
localeBenchmarks() | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,7 +54,7 @@ print("swift-foundation benchmarks: \(usePackage.description)") | |
var packageDependency : [Package.Dependency] = [.package(url: "https://github.com/ordo-one/package-benchmark.git", from: "1.11.1")] | ||
var targetDependency : [Target.Dependency] = [.product(name: "Benchmark", package: "package-benchmark")] | ||
var i18nTargetDependencies : [Target.Dependency] = [] | ||
var swiftSettings : [SwiftSetting] = [] | ||
var swiftSettings : [SwiftSetting] = [.unsafeFlags(["-Rmodule-loading"]), .enableUpcomingFeature("MemberImportVisibility")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems fine to me, since this patch is trying to keep that from happening again. |
||
|
||
switch usePackage { | ||
case .useLocalPackage(let root): | ||
|
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.
@itingliu FWIW… it's possible this might lead to some unexpected behaviors. Our
calendarBenchmarks
function sets some global state:And our
localeBenchmarks
also sets some global state:At this point… I'm not sure we know exactly which function "wins".
I believe our expectation is that the benchmarks defined in
localeBenchmarks
run withpeakMemoryResident
andpeakMemoryResidentDelta
as default metrics. Is that correct? And our expectation is that the benchmarks defined incalendarBenchmarks
do not run withpeakMemoryResident
andpeakMemoryResidentDelta
as default metrics. Is that correct?Uh oh!
There was an error while loading. Please reload this page.
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.
They're executed sequentially, so I think mutating global state is fine. The configurations will just be updated right before the tests run, or am I missing anything?
Uh oh!
There was an error while loading. Please reload this page.
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.
This is where my question was going… to what extent is registering a set of benchmarks decoupled from running a subset of those benchmarks?
Suppose we run our international benchmarks package target… but we focus specifically on a benchmark defined from
calendarBenchmarks
:When we launch our benchmarks… I assume we have to execute both
calendarBenchmarks
andlocaleBenchmarks
. The next step then is to respect thefilter
that was specified and only runnextThousandThursdaysInTheFourthWeekOfNovember
. At that point… I believe we can see how our benchmark tests are potentiallyrunningout of sync from the global state we set when those tests were defined.In general I believe the pattern I typically see is splitting benchmark targets apart and this question about the global
Benchmark.defaultConfiguration
state is not very important. It is global state… but we tear it down and rebuild it for every target so it is fresh and clean.I do not believe this is a major issue… and this is currently a very impactful diff that unblocks engineers from running benchmarks and that is good! But I do believe there might be some unexpected issues currently from running the benchmarks and what specific metrics might be reported. I could maybe think of three possible ideas to work around that:
BenchmarkCalendar
andBenchmarkLocale
to separate and independent benchmark targets.BenchmarkCalendar
andBenchmarkLocale
as one benchmark target but update the way that configurations are passed to benchmarks so we do not depend on global state. Similar to what we do in other places.1BenchmarkCalendar
andBenchmarkLocale
as one benchmark target and update some header documentation comments where the benchmarks are defined to notify engineers that we might see unexpected behavior when configurations might not be respected.But I don't think this discussion would have to block this specific diff from landing. I think you can use your best judgement and make the best decision if you want to ship more code on this right now or ship a future diff with a potential workaround in the future.
Footnotes
https://github.com/swiftlang/swift-foundation/blob/swift-6.1.2-RELEASE/Benchmarks/Benchmarks/Internationalization/BenchmarkCalendar.swift#L135-L148 ↩
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.
Since
nextThousandThursdaysInTheFourthWeekOfNovember
is defined insidelocaleBenchmarks
,localeBenchmarks
will need to be run first, so I would expect the configuration set in that benchmark to be used.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.
Ahh… I think you are correct! It looks like the default Benchmark constructor does use shared global state:
https://github.com/ordo-one/package-benchmark/blob/1.29.3/Sources/Benchmark/Benchmark.swift#L229
But the configuration itself is a value type:
https://github.com/ordo-one/package-benchmark/blob/1.29.3/Sources/Benchmark/Benchmark.swift#L432
Which is then copied by value in the new benchmark:
https://github.com/ordo-one/package-benchmark/blob/1.29.3/Sources/Benchmark/Benchmark.swift#L238
So it looks like defining benchmarks does capture shared mutable state… but it captures that shared mutable state by value and mutating that shared state in the future does not affect the benchmark after it was defined. My mistake! Sorry for any confusion about that.