Index: runtime/bin/vmservice/loader.dart |
diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart |
index 8af63b50e269099db170915a18cb154f5d2ec39e..a72e735df2cbe3f27bba5d090a49fad0c0dc42db 100644 |
--- a/runtime/bin/vmservice/loader.dart |
+++ b/runtime/bin/vmservice/loader.dart |
@@ -53,6 +53,15 @@ _enforceTrailingSlash(uri) { |
return uri; |
} |
+class FileRequest { |
+ final SendPort sp; |
+ final int tag; |
+ final Uri uri; |
+ final Uri resolvedUri; |
+ final String libraryUrl; |
+ FileRequest(this.sp, this.tag, this.uri, this.resolvedUri, this.libraryUrl); |
+} |
+ |
// State associated with the isolate that is used for loading. |
class IsolateLoaderState extends IsolateEmbedderData { |
IsolateLoaderState(this.isolateId); |
@@ -78,6 +87,7 @@ class IsolateLoaderState extends IsolateEmbedderData { |
if (packagesConfigFlag != null) { |
_setPackagesConfig(packagesConfigFlag); |
} |
+ _fileRequestQueue = new List<FileRequest>(); |
} |
void cleanup() { |
@@ -114,6 +124,24 @@ class IsolateLoaderState extends IsolateEmbedderData { |
Uri _packageConfig = null; |
Map<String, Uri> _packageMap = null; |
+ // We issue only 16 concurrent calls to File.readAsBytes() to stay within |
+ // platform-specific resource limits (e.g. max open files). The rest go on |
+ // _fileRequestQueue and are processed when we can safely issue them. |
+ static const int _maxFileRequests = 16; |
+ int currentFileRequests = 0; |
+ List<FileRequest> _fileRequestQueue; |
+ |
+ bool get shouldIssueFileRequest => currentFileRequests < _maxFileRequests; |
+ void enqueueFileRequest(FileRequest fr) { |
+ _fileRequestQueue.add(fr); |
+ } |
+ FileRequest dequeueFileRequest() { |
+ if (_fileRequestQueue.length == 0) { |
+ return null; |
+ } |
+ return _fileRequestQueue.removeAt(0); |
+ } |
+ |
_setPackageRoot(String packageRoot) { |
packageRoot = _sanitizeWindowsPath(packageRoot); |
if (packageRoot.startsWith('file:') || |
@@ -399,7 +427,8 @@ void _loadHttp(SendPort sp, |
Timer.run(() {}); |
} |
-void _loadFile(SendPort sp, |
+void _loadFile(IsolateLoaderState loaderState, |
+ SendPort sp, |
int tag, |
Uri uri, |
Uri resolvedUri, |
@@ -411,6 +440,17 @@ void _loadFile(SendPort sp, |
}, |
onError: (e) { |
_sendResourceResponse(sp, tag, uri, resolvedUri, libraryUrl, e.toString()); |
+ }).whenComplete(() { |
+ loaderState.currentFileRequests--; |
+ while (loaderState.shouldIssueFileRequest) { |
+ FileRequest fr = loaderState.dequeueFileRequest(); |
+ if (fr == null) { |
+ break; |
+ } |
+ _loadFile( |
+ loaderState, fr.sp, fr.tag, fr.uri, fr.resolvedUri, fr.libraryUrl); |
+ loaderState.currentFileRequests++; |
+ } |
}); |
} |
@@ -507,7 +547,13 @@ _handleResourceRequest(IsolateLoaderState loaderState, |
Uri resolvedUri, |
String libraryUrl) { |
if (resolvedUri.scheme == '' || resolvedUri.scheme == 'file') { |
- _loadFile(sp, tag, uri, resolvedUri, libraryUrl); |
+ if (loaderState.shouldIssueFileRequest) { |
+ _loadFile(loaderState, sp, tag, uri, resolvedUri, libraryUrl); |
+ loaderState.currentFileRequests++; |
+ } else { |
+ FileRequest fr = new FileRequest(sp, tag, uri, resolvedUri, libraryUrl); |
+ loaderState.enqueueFileRequest(fr); |
+ } |
} else if ((resolvedUri.scheme == 'http') || |
(resolvedUri.scheme == 'https')) { |
_loadHttp(sp, tag, uri, resolvedUri, libraryUrl); |