Open peter-ahe-google opened 10 years ago
It was pointed out to me that perhaps I was starving my machine for CPUs. So I wrote a more sequential version:
import 'dart:io';
import 'dart:async';
main(List<String> arguments) { Stopwatch sw = new Stopwatch()..start(); Map<String, String> sources = <String, String>{}; Future<String> futures = new List<Future<String>>(); Uri testScheme = new Uri(scheme: 'org-dartlang-test'); Future.forEach(arguments, (String argument) { Uri uri = testScheme.resolve(argument); Future<String> future = new File.fromUri(Uri.base.resolve(argument)).readAsString(); return future.then((String source) { sources['$uri'] = future; }); }).then((_) { sw.stop(); print(sw.elapsedMilliseconds); }); }
On average this runs in 100.2 ms (average deviation 1.92) which is 184% of 54.6.
Just re-ran the code from above and it looks like we've regressed further (or things are just as bad as before and the differing numbers is due to HW configuration).
Sync Avg: 67.6 ms Async Ave: 149.3 ms
Difference: ~221%
This is a real problem in some situations and there is no workaround afaik. Since dart has no multithreading, it is almost impossible to use the sync io for example in Flutter.
I hope this issue will be worked on some time soon :+1:
@peter-ahe-google @bkonyi Any news on this issue?
I'm getting similar issues and I'm wondering if it's still preferred to use sync methods?
cc @aam
Yeah, I think async infrastructure still carries rather noticeable amount of overhead, so equivalent sync operations are faster. Async allows for better concurrent workload management, but in absence of that no real reason to use that.
To elaborate on what @aam said, there is significant overhead in async File
operations:
File
operations involve sending the request and response though a portFile
operations What if we modified the documentation like:
From:
Unless you have a specific reason for using the synchronous version of a method, prefer the asynchronous version to avoid blocking your program.
To:
The synchronous version of a method will always be more performant than the asynchronous version, sometimes significantly so. However, using the synchronous version of a method will block your program.
The async.dart program below is 40% slower than sync.dart:
==> sync.dart <== import 'dart:io';
main(List<String> arguments) { Stopwatch sw = new Stopwatch()..start(); Map<String, String> sources = <String, String>{}; Uri testScheme = new Uri(scheme: 'org-dartlang-test'); for (String argument in arguments) { Uri uri = testScheme.resolve(argument); String source = new File.fromUri(Uri.base.resolve(argument)).readAsStringSync(); sources['$uri'] = source; } sw.stop(); print(sw.elapsedMilliseconds); }
==> async.dart <== import 'dart:io';
import 'dart:async';
main(List<String> arguments) { Stopwatch sw = new Stopwatch()..start(); Map<String, String> sources = <String, String>{}; Future<String> futures = new List<Future<String>>(); Uri testScheme = new Uri(scheme: 'org-dartlang-test'); for (String argument in arguments) { Uri uri = testScheme.resolve(argument); Future<String> future = new File.fromUri(Uri.base.resolve(argument)).readAsString(); futures.add(future.then((String source) { sources['$uri'] = future; })); } Future.wait(futures).then((_) { sw.stop(); print(sw.elapsedMilliseconds); }); }
I've measured this at r36733. On my Mac which is a dual 3.06 GHz 6-Core Intel Xeon running OS X version 10.9.3 (mavericks).
I've run the test 10 times (after initial runs to ensure all files are cached) using:
for i in {1..10} ; do ./sdk/bin/dart -pp/ sync.dart tests/compiler/dart2js_extra/*.dart; done
for i in {1..10} ; do ./sdk/bin/dart -pp/ async.dart tests/compiler/dart2js_extra/*.dart; done
On average sync runs in 54.6 milliseconds (average deviation 0.48), and async runs in 75.1 milliseconds (average deviation 0.96). 75.1/54.6 is 138%.