Skip to content
This repository has been archived by the owner on Feb 11, 2024. It is now read-only.

benchmark: cronet benchmarks and comparison with dart:io #8

Merged
merged 13 commits into from
Jul 13, 2021

Conversation

unsuitable001
Copy link
Contributor

@unsuitable001 unsuitable001 commented Jul 7, 2021

Benchmarks

Package Version: 0.0.1+1
Cronet Version: 86.0.4240.198
Cronet Build Type: Debug
Wrapper Version: 1
Dart SDK Version: 2.12.0

  • Latency
    • Writing Benchmarking Code
    • Gathering observations in different environments and writing reports
    • Comparing with dart:io
  • Throughput
    • Writing Benchmarking Code
    • Gathering observations in different environments and writing reports
    • Comparing with dart:io

May get affected by #11

Closes #3

@unsuitable001 unsuitable001 changed the title benchmark: cronet benchmars and comparison with dart:io benchmark: cronet benchmarks and comparison with dart:io Jul 7, 2021
}

static Future<double> measureFor(Function f, int minimumMillis) async {
var minimumMicros = minimumMillis * 1000;
Copy link
Member

Choose a reason for hiding this comment

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

To avoid writing millis and micros, you can use Duration.

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 :)

Though, future delayed gives us most "time accurate" and faster results,
it doesn't ensures if "late" requests are returned or not. As, we are
gradually incrementing the no. of spawned tasks in each loop, we must
ensure that everything is cleaned up from the previous test.
@dcharkes
Copy link
Member

dcharkes commented Jul 9, 2021

Some high level comments:

  • Documentation on how to set up local servers.
  • Make the benchmarks so that they don't require editing Dart files.
    • The throughput benchmark should run multiple times for parallelism 1, 2, 4, ..., 2^(N+2 above the peak)
    • The url tested could be a command line parameter.
  • We could add a benchmarks/run_all.dart script that automatically runs both JIT and AOT and outputs the markdown tables such that it is very easy to update the result if we change the performance. This would also make it easy for others to reproduce our results with invoking a single script.

@unsuitable001
Copy link
Contributor Author

@dcharkes Done 😄

2. Create a new `app.py` file that contains -

```python
from waitress import serve
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we ideally put the code required for local servers in the repository?

cc @dcharkes.

Copy link
Contributor Author

@unsuitable001 unsuitable001 Jul 10, 2021

Choose a reason for hiding this comment

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

Umm.. I can put that if that's what best practice is. But, any server will do the job. I just chosen these 2 servers as they are easy to setup, well known and used in production.

Should I include all the codes in the repo? (And, the resources they served too?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added :)

void main(List<String> args) async {
var url = 'https://example.com';
var throughputPrallelLimit = 10;
switch (args.length) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We can also consider using package:args throughout the package for handling cmd line args. But that's probably good for later if we end up with more arguments.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah. Let's use package:args in other places too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In a separate PR maybe to keep the commit history more meaningful? As, I'll have to migrate other parts of the package too. (i.e. bin/setup.dart).

Copy link
Member

@dcharkes dcharkes left a comment

Choose a reason for hiding this comment

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

Looking good! ✌️


Future<double> report() async {
final runtime = await measure();
print('Cronet(RunTime): $runtime us');
Copy link
Member

Choose a reason for hiding this comment

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

I think microseconds is a bit hard to read. Let's do milliseconds.

final jitLatency = await CronetBenchmark.main(url);
print('AOT');
Process.runSync('dart', ['compile', 'exe', 'benchmarks/latency.dart']);
final aotLatency = double.parse(
Copy link
Member

Choose a reason for hiding this comment

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

Please also stream the stdout to stdout instead of just capturing it.

url, pow(2, throughputPrallelLimit).toInt());
print('AOT');
Process.runSync('dart', ['compile', 'exe', 'benchmarks/throughput.dart']);
final throughputStdout = Process.runSync(
Copy link
Member

Choose a reason for hiding this comment

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

Please also stream the stdout to stdout instead of just capturing it.


import 'package:cronet/cronet.dart';

class CronetBenchmark {
Copy link
Member

Choose a reason for hiding this comment

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

LatencyBenchmark with subclasses CronetLatencyBenchmark and DartIOLatencyBenchmark.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The only difference between two will be swapping the import statement. But, how can I achieve this without 2 near duplicate file? How can I make this subclass structure?

(Maybe it's a really basic question to ask 😅 )


import 'package:cronet/cronet.dart';

class CronetThroughputBenchmark {
Copy link
Member

Choose a reason for hiding this comment

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

ThroughputBenchmark with subclasses CronetThroughputBenchmark and DartIOThroughputBenchmark.

});

print('Latency Test Results');
print('| Mode | package:cronet |');
Copy link
Member

Choose a reason for hiding this comment

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

Add column dart:io

@unsuitable001
Copy link
Contributor Author

@dcharkes Done! Also added #11 in TODO and run_all.dart test output.

@dcharkes
Copy link
Member

Latency Test Results

Mode package:cronet dart:io
JIT 90.435 ms 106.105 ms
AOT 89.000 ms 103.000 ms

On my machine, Cronet is faster. 😄

Throughput Test Results

Mode package:cronet dart:io
JIT 830 out of 1024 512 out of 512
AOT 850 out of 1024 512 out of 512

Can we make the time configurable for this benchmark? My internet seems too fast for Dart IO to hit it's limit. 🙈

@unsuitable001
Copy link
Contributor Author

unsuitable001 commented Jul 13, 2021

Can we make the time configurable for this benchmark?

@dcharkes You can pass the value of N where 2^N is the max spawn limit as n CLI argument. But, then you have to mention the target server url also as n CLI argument.
It will look like dart run run_all.dart http://example.com 10.
And, the default is 1024 spawns for both. Seems like dart:io is maxing out on 512 and then dipping. Can you confirm this from the console outputs?

@unsuitable001
Copy link
Contributor Author

I'll give these cli args some name on the next pr as we'll move to package:args. Then, it will be more documented and friendly to use :)

}
// TODO: https://github.com/google/cronet.dart/issues/11
await CronetLatencyBenchmark.main(url);
if (benchmarkDartIO) {
Copy link
Member

Choose a reason for hiding this comment

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

I'd just always run both instead of adding command line argument.

}

class DartIOLatencyBenchmark extends LatencyBenchmark {
final String url;
Copy link
Member

Choose a reason for hiding this comment

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

Can this be in LatencyBenchmark?

break;
case 2:
url = args[0];
throughputPrallelLimit = int.parse(args[1]).toInt();
Copy link
Member

Choose a reason for hiding this comment

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

It's more common to use flags for arg parsing so that you can provide them in any order and in any combination.

e.g. If I want to just provide a different throughputPrallelLimit I don't want to type http://example.com

}

class DartIOThroughputBenchmark extends ThroughputBenchmark {
final String url;
Copy link
Member

Choose a reason for hiding this comment

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

Can this be in ThroughputBenchmark?

@dcharkes
Copy link
Member

And, the default is 1024 spawns for both. Seems like dart:io is maxing out on 512 and then dipping. Can you confirm this from the console outputs?

500 ms results:

Throughput Test Results

Mode package:cronet dart:io
JIT 291 out of 1024 112 out of 128
AOT 300 out of 1024 128 out of 128

Prints for 1 second:

DartIOThroughputBenchmark: Total Spawned: 1, Returned in time: 1.
DartIOThroughputBenchmark: Total Spawned: 2, Returned in time: 2.
DartIOThroughputBenchmark: Total Spawned: 4, Returned in time: 4.
DartIOThroughputBenchmark: Total Spawned: 8, Returned in time: 8.
DartIOThroughputBenchmark: Total Spawned: 16, Returned in time: 16.
DartIOThroughputBenchmark: Total Spawned: 32, Returned in time: 32.
DartIOThroughputBenchmark: Total Spawned: 64, Returned in time: 64.
DartIOThroughputBenchmark: Total Spawned: 128, Returned in time: 128.
DartIOThroughputBenchmark: Total Spawned: 256, Returned in time: 256.
DartIOThroughputBenchmark: Total Spawned: 512, Returned in time: 512.
DartIOThroughputBenchmark: Total Spawned: 1024, Returned in time: 0.

@dcharkes
Copy link
Member

Okay, moving to package:args in a next PR is okay. Just disregard my comments on the CLI for now then.

@dcharkes dcharkes mentioned this pull request Jul 13, 2021
@unsuitable001
Copy link
Contributor Author

unsuitable001 commented Jul 13, 2021

Can we make the time configurable for this benchmark?

@dcharkes Opps! Seems like I misunderstood your comment. Anyways, Duration is now configurable as a 3rd argument from CLI.

Other changes are done except the CLI ones :). Added MacOS as supported platform in README. Seems like we missed that in the other PR.

@mannprerak2 mannprerak2 mentioned this pull request Jul 13, 2021
@dcharkes dcharkes merged commit a6eac31 into google:main Jul 13, 2021
@dcharkes
Copy link
Member

🚀 🚀 🚀

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

Successfully merging this pull request may close these issues.

Benchmarks
3 participants