Skip to content
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 AsyncBenchmarkBase class #44

Merged
merged 1 commit into from
Apr 29, 2022
Merged

Add AsyncBenchmarkBase class #44

merged 1 commit into from
Apr 29, 2022

Conversation

aam
Copy link
Contributor

@aam aam commented Aug 30, 2019

This is to accommodate tests that require async setup/teardown/run.

@aam aam requested a review from kevmoo August 30, 2019 18:23
@sortie sortie requested review from sortie and removed request for kevmoo September 5, 2019 11:34
@sortie
Copy link
Contributor

sortie commented Sep 5, 2019

Hi Kevin, I'd like to take over ownership of this package as we're now using it to benchmark the Dart SDK. Can you add me as an uploader for the https://pub.dev/packages/benchmark_harness package?

run() async {}

// Runs a short version of the benchmark. By default invokes [run] once.
void warmup() async {
Copy link
Contributor

Choose a reason for hiding this comment

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

Future, and likewise above and the other places

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

for (int i = 0; i < 10; i++) {
await run();
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Okay story time. The class in package:benchmark_harness is bug compatible with Golem and I need to keep them that way until I've migrated the benchmarks. Golem has an existing AsyncBenchmarkBase, and I need to keep this version compatible with it.

BenchmarkBase (including the one here) has a bug where it does ten iterations per exercise, but it doesn't multiply the final result by 10, meaning that it reports the time to run 10 iterations instead of 1. The documentation for this package mentions that.

The existing AsyncBenchmarkBase doesn't have that problem. It does one run per exercise. I need this version to be compatible with that. That's still not great because doing 10 iterations per exercise means less overhead checking the system time, but at least the results aren't misleading.

My intention is to take over this package and ensure there's a pair of sync/async base benchmark classes that report the time per iteration, and perhaps does 10 iterations per exercise.

So where does that leave you? I do need a class named AsyncBenchmarkBase that does one run per exercise and reports the time per iteration. This is results compatible with how we want things to be in the future. You can use that base class in your Isolates benchmark. When I make changes to this package in the future, I can update your benchmark while being results compatible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -62,3 +62,64 @@ class BenchmarkBase {
emitter.emit(name, measure());
}
}

class AsyncBenchmarkBase {
Copy link
Contributor

Choose a reason for hiding this comment

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

Put this in its own async_benchmark_base.dart file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

// Measures the score for this benchmark by executing it repeately until
// time minimum has been reached.
static Future<double> measureFor(Function f, int minimumMillis) async {
int minimumMicros = minimumMillis * 1000;
Copy link
Contributor

Choose a reason for hiding this comment

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

Use final for variables that are assigned once.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

await measureFor(warmup, 100);
// Run the benchmark for at least 2000ms.
double result = await measureFor(exercise, 2000);
await teardown();
Copy link
Contributor

Choose a reason for hiding this comment

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

Put this in a finally block. That's another difference between BenchmarkBase and AsyncBenchmarkBase.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@Fox32
Copy link

Fox32 commented Feb 28, 2020

Just wanted to submit a PR like this, but it's already here. Can this be merged?

@davidmartos96
Copy link

@sortie Any update on this? I think the only thing missing from the code review would be to replace the exercise function with the following so that it behaves the same as the sync version.

Future<void> exercise() async {
  for (int i = 0; i < 10; i++) {
    await run();
  }
}

I think the async version of the benchmarks can be very helpful for comparing things like database performance. It would be great if this could be merged at some point.

@sortie
Copy link
Contributor

sortie commented Jul 28, 2020

Yes, the plan is to do this work soon. package:benchmark_harness is currently central to the ongoing null safety benchmark migration and has been marked as null safe in master, but not published on pub of course. That means things are a bit in flux right now. In the meanwhile, I want to add some features such as this async harness to the package in order to finish the migration, and I also want to make some breaking changes. So overall, this work needs to be done in a thought out manner and this change will have to wait just a bit longer.

@mkustermann
Copy link
Member

If the only thing blocking this is the discussion about whether the number of iterations from the exercise function is taken into account for the reporting, then here's a suggestion: The harness class could take in it's constructor a boolean parameter signaling which behavior we want (or an integer parameter specifying the iteration count).

Apart from that, is there anything else to be decided before we can move forward here?

final String name;
final ScoreEmitter emitter;

// Empty constructor.
Copy link
Contributor

Choose a reason for hiding this comment

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

Switch the comments to triple slash dartdoc for documentation

const AsyncBenchmarkBase(this.name, {this.emitter = const PrintEmitter()});

// The benchmark code.
// This function is not used, if both [warmup] and [exercise] are overwritten.
Copy link
Contributor

Choose a reason for hiding this comment

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

Blank dartdoc line between the first paragraph and the second per style.

@sortie
Copy link
Contributor

sortie commented Apr 26, 2022

Hi Martin,

First up, I need to stabilize this package as it hasn't rolled into the Dart SDK in a long time. There's a slight risk that any of the changes in the meanwhile may have broken something. That roll is being done in https://dart-review.googlesource.com/c/sdk/+/212747

The PR has already been updated to be compatible with the historic AsyncBenchmarkBase behavior (which happens to be the intended behavior). I see a couple minor nits. I'll take a careful look once the benchmark_harness roll goes through and probably just take over this CL and get it fully done.

Jonas

@mkustermann
Copy link
Member

Thanks for getting the ball moving here again, @sortie (and thanks to @aam for doing the change in the first place :))!

The async benchmark harness accommodates tests that require async
setup/teardown/run implementations.
Copy link
Contributor

@sortie sortie left a comment

Choose a reason for hiding this comment

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

OK I took over this PR and got it over the finish line :)

@sortie sortie merged commit 0530da6 into master Apr 29, 2022
@sortie sortie deleted the async branch April 29, 2022 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants