Skip to content

More benchmarker features #595

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

Merged
merged 24 commits into from
Aug 15, 2022
Merged

Conversation

rctcwyvrn
Copy link
Contributor

Adds

  • Loading results from a file
  • Measuring compile times (via a spi function in Regex)
  • Comparing compile times and against NSRegularExpression
  • Saving comparison results as csv
  • Charts (based on Add option to show benchmark charts #585)

Copy link
Contributor

@rxwei rxwei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📊

Comment on lines 55 to 61
BarMark(
x: .value("Name", name),
y: .value("Normalized runtime", new / old))
.foregroundStyle(LinearGradient(
colors: [.accentColor, new - old <= 0 ? .green : .yellow],
startPoint: .bottom,
endPoint: .top))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could inline this into the ForEach { ... }. I pulled this out to chartBody because of "expression too complex". That doesn't happen with just one bar mark.

@rctcwyvrn
Copy link
Contributor Author

@swift-ci test

@rctcwyvrn
Copy link
Contributor Author

Oh huh what version is the CI on?

/Users/ec2-user/jenkins/workspace/pr-swift-experimental-string-processing-macos/branch-main/swift-experimental-string-processing/Sources/RegexBenchmark/BenchmarkChart.swift:14:8: error: no such module 'Charts'
import Charts
       ^

@rxwei
Copy link
Contributor

rxwei commented Aug 4, 2022

I don't think the CI runs on macOS 13. Maybe #if canImport(Charts) around the import and around Chart usage.

return false
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of approach looks ok to me. I wonder if we can generalize the interface a little bit to give us some future flexibility without needing to add more SPI over time. For example, we could return a (resilient) result type which we can add metrics to in the future (number of instructions, complexity or star-height, etc). We could also have a (resilient) compilation options parameter, such as the proposed force-recompilation behavior which we could extend with more options like control over optimizations or even targeted engine version (e.g. back deployment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may also want to output per-stage metrics, like time spent parsing vs generating bytecode, etc.

@rctcwyvrn
Copy link
Contributor Author

rctcwyvrn commented Aug 5, 2022

  • Added setting compiler options to the SPI interface and made it extensible for the future by adding a _RegexInternalAction enum (not sure how to make sure this/the switch are abi stable)
  • Added some processor metrics code I wrote awhile back and forgot about
  • Added metrics and tracing enabled as options for the compiler
  • Using the new additions, added CLI options for turning on metrics/tracing for benchmarker regexes
  • Added parse time measurements to the benchmarker

@rctcwyvrn
Copy link
Contributor Author

@swift-ci test

@rctcwyvrn
Copy link
Contributor Author

@milseman Could you check that Regex._forceAction in Core.swift matches what you had in mind? Also that it's ABI stable the way it's written right now?

@@ -6,7 +6,7 @@ extension Benchmark {
case .whole:
let result = target.wholeMatch(of: regex)
if let match = result {
if match.0.count > 100 {
if match.0.count > 1000 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could / should we abstract this check out to a helper method somewhere?

static let disableOptimizations = CompileOptions(rawValue: 1)
static let `default`: CompileOptions = []
@_spi(RegexBenchmark)
public struct CompileOptions: OptionSet {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's underscore the name. Not a huge deal, but it makes it easier if we one day want API named CompileOptions

@@ -89,6 +89,8 @@ struct Processor {
// MARK: Metrics, debugging, etc.
var cycleCount = 0
var isTracingEnabled: Bool
let shouldMeasureMetrics: Bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While well-predicted, do we see any impact from checking this bool inside the processor? Worst case we could make it conditionally compile and the benchmark can enable it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Ah... the answer is quite a lot. Removing both the tracing and metric conditions speeds things up by 10-20% across the board. I'll see if I can figure out the conditional compilation

Copy link
Contributor Author

@rctcwyvrn rctcwyvrn Aug 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After looking around it doesn't seem like swiftPM supports the feature of "define this compilation variable only when being built as a dependency for target X". The only conditions it can enable/disable compilation variables on are platforms and debug/release. Trying to add multiple targets with flags enabled/disabled for _StringProcessing ends up with "overlapping source code"

https://forums.swift.org/t/swiftpm-and-conditional-compilation/36874
https://forums.swift.org/t/compilation-conditions-and-swift-packages/34627/4

So for now in order to use metrics/tracing you just have to rebuild with the flag directly swift build -c release -Xswiftc -DPROCESSOR_MEASUREMENTS_ENABLED

Copy link
Member

@milseman milseman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after making sure to underscore the SPI

- make charts prettier
- underscore compileroptions
- cleanup debug
@rctcwyvrn
Copy link
Contributor Author

image

Made the charts nice and pretty <:

Ideally this would be done in Package.swift instead of having to add a flag to swift build but alas it appears that it is not possible
- https://forums.swift.org/t/swiftpm-and-conditional-compilation/36874
- https://forums.swift.org/t/compilation-conditions-and-swift-packages/34627/4
@rctcwyvrn
Copy link
Contributor Author

@swift-ci test

@rctcwyvrn
Copy link
Contributor Author

@swift-ci test

@rctcwyvrn
Copy link
Contributor Author

@swift-ci test

@rctcwyvrn rctcwyvrn merged commit 68f8845 into swiftlang:main Aug 15, 2022
@rctcwyvrn
Copy link
Contributor Author

augh I forgot to switch it back to squash... oops

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants