mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 16:00:45 +00:00
Track more Cider operation performance.
R=brianwilkerson@google.com, keertip@google.com Change-Id: I95f2a36434556256dd5d55395cfc1bfca056763b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153068 Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
cffeac78f9
commit
4301899ed5
|
@ -124,7 +124,8 @@ class CiderCompletionComputer {
|
|||
_logger.run('Add imported suggestions', () {
|
||||
suggestions.addAll(
|
||||
_importedLibrariesSuggestions(
|
||||
resolvedUnit.libraryElement,
|
||||
target: resolvedUnit.libraryElement,
|
||||
performance: performance,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
@ -182,12 +183,16 @@ class CiderCompletionComputer {
|
|||
///
|
||||
/// TODO(scheglov) Implement show / hide combinators.
|
||||
/// TODO(scheglov) Implement prefixes.
|
||||
List<CompletionSuggestion> _importedLibrariesSuggestions(
|
||||
LibraryElement target,
|
||||
) {
|
||||
List<CompletionSuggestion> _importedLibrariesSuggestions({
|
||||
@required LibraryElement target,
|
||||
@required OperationPerformanceImpl performance,
|
||||
}) {
|
||||
var suggestions = <CompletionSuggestion>[];
|
||||
for (var importedLibrary in target.importedLibraries) {
|
||||
var importedSuggestions = _importedLibrarySuggestions(importedLibrary);
|
||||
var importedSuggestions = _importedLibrarySuggestions(
|
||||
element: importedLibrary,
|
||||
performance: performance,
|
||||
);
|
||||
suggestions.addAll(importedSuggestions);
|
||||
}
|
||||
return suggestions;
|
||||
|
@ -195,11 +200,15 @@ class CiderCompletionComputer {
|
|||
|
||||
/// Return cached, or compute unprefixed suggestions for all elements
|
||||
/// exported from the library.
|
||||
List<CompletionSuggestion> _importedLibrarySuggestions(
|
||||
LibraryElement element,
|
||||
) {
|
||||
List<CompletionSuggestion> _importedLibrarySuggestions({
|
||||
@required LibraryElement element,
|
||||
@required OperationPerformanceImpl performance,
|
||||
}) {
|
||||
var path = element.source.fullName;
|
||||
var signature = _fileResolver.getLibraryLinkedSignature(path);
|
||||
var signature = _fileResolver.getLibraryLinkedSignature(
|
||||
path: path,
|
||||
performance: performance,
|
||||
);
|
||||
|
||||
var cacheEntry = _cache._importedLibraries[path];
|
||||
if (cacheEntry == null || cacheEntry.signature != signature) {
|
||||
|
|
|
@ -14,7 +14,6 @@ import 'package:analyzer/error/listener.dart';
|
|||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/src/dart/analysis/experiments.dart';
|
||||
import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
|
||||
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
|
||||
import 'package:analyzer/src/dart/analysis/unlinked_api_signature.dart';
|
||||
import 'package:analyzer/src/dart/ast/ast.dart';
|
||||
import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
|
||||
|
@ -30,7 +29,9 @@ import 'package:analyzer/src/summary/idl.dart';
|
|||
import 'package:analyzer/src/summary/link.dart' as graph
|
||||
show DependencyWalker, Node;
|
||||
import 'package:analyzer/src/summary2/informative_data.dart';
|
||||
import 'package:analyzer/src/util/performance/operation_performance.dart';
|
||||
import 'package:convert/convert.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Ensure that the [FileState.libraryCycle] for the [file] and anything it
|
||||
/// depends on is computed.
|
||||
|
@ -161,10 +162,12 @@ class FileState {
|
|||
return unit;
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
void refresh({
|
||||
@required OperationPerformanceImpl performance,
|
||||
}) {
|
||||
_fsState.testView.refreshedFiles.add(path);
|
||||
|
||||
_fsState.timers.digest.run(() {
|
||||
performance.run('digest', (_) {
|
||||
_digest = utf8.encode(_fsState.getFileDigest(path));
|
||||
_exists = _digest.isNotEmpty;
|
||||
});
|
||||
|
@ -177,19 +180,21 @@ class FileState {
|
|||
bytes = _fsState._byteStore.get(unlinkedKey, _digest);
|
||||
|
||||
if (bytes == null || bytes.isEmpty) {
|
||||
var content = _fsState.timers.read.run(() {
|
||||
var content = performance.run('content', (_) {
|
||||
return getContent();
|
||||
});
|
||||
var unit = _fsState.timers.parse.run(() {
|
||||
|
||||
var unit = performance.run('parse', (_) {
|
||||
return parse(AnalysisErrorListener.NULL_LISTENER, content);
|
||||
});
|
||||
_fsState.timers.unlinked.run(() {
|
||||
|
||||
performance.run('unlinked', (_) {
|
||||
var unlinkedBuilder = serializeAstCiderUnlinked(_digest, unit);
|
||||
bytes = unlinkedBuilder.toBuffer();
|
||||
_fsState._byteStore.put(unlinkedKey, _digest, bytes);
|
||||
});
|
||||
|
||||
_fsState.timers.prefetch.run(() {
|
||||
performance.run('prefetch', (_) {
|
||||
unlinked2 = CiderUnlinkedUnit.fromBuffer(bytes).unlinkedUnit;
|
||||
_prefetchDirectReferences(unlinked2);
|
||||
});
|
||||
|
@ -202,19 +207,28 @@ class FileState {
|
|||
|
||||
// Build the graph.
|
||||
for (var directive in unlinked2.imports) {
|
||||
var file = _fileForRelativeUri(directive.uri);
|
||||
var file = _fileForRelativeUri(
|
||||
relativeUri: directive.uri,
|
||||
performance: performance,
|
||||
);
|
||||
if (file != null) {
|
||||
importedFiles.add(file);
|
||||
}
|
||||
}
|
||||
for (var directive in unlinked2.exports) {
|
||||
var file = _fileForRelativeUri(directive.uri);
|
||||
var file = _fileForRelativeUri(
|
||||
relativeUri: directive.uri,
|
||||
performance: performance,
|
||||
);
|
||||
if (file != null) {
|
||||
exportedFiles.add(file);
|
||||
}
|
||||
}
|
||||
for (var uri in unlinked2.parts) {
|
||||
var file = _fileForRelativeUri(uri);
|
||||
var file = _fileForRelativeUri(
|
||||
relativeUri: uri,
|
||||
performance: performance,
|
||||
);
|
||||
if (file != null) {
|
||||
partedFiles.add(file);
|
||||
}
|
||||
|
@ -222,7 +236,10 @@ class FileState {
|
|||
if (unlinked2.hasPartOfDirective) {
|
||||
var uri = unlinked2.partOfUri;
|
||||
if (uri.isNotEmpty) {
|
||||
partOfLibrary = _fileForRelativeUri(uri);
|
||||
partOfLibrary = _fileForRelativeUri(
|
||||
relativeUri: uri,
|
||||
performance: performance,
|
||||
);
|
||||
if (partOfLibrary != null) {
|
||||
directReferencedFiles.add(partOfLibrary);
|
||||
}
|
||||
|
@ -244,7 +261,10 @@ class FileState {
|
|||
return path;
|
||||
}
|
||||
|
||||
FileState _fileForRelativeUri(String relativeUri) {
|
||||
FileState _fileForRelativeUri({
|
||||
@required String relativeUri,
|
||||
@required OperationPerformanceImpl performance,
|
||||
}) {
|
||||
if (relativeUri.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
@ -256,7 +276,10 @@ class FileState {
|
|||
return null;
|
||||
}
|
||||
|
||||
var file = _fsState.getFileForUri(absoluteUri);
|
||||
var file = _fsState.getFileForUri(
|
||||
uri: absoluteUri,
|
||||
performance: performance,
|
||||
);
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -372,7 +395,6 @@ class FileState {
|
|||
}
|
||||
|
||||
class FileSystemState {
|
||||
final PerformanceLog _logger;
|
||||
final ResourceProvider _resourceProvider;
|
||||
final CiderByteStore _byteStore;
|
||||
final SourceFactory _sourceFactory;
|
||||
|
@ -393,12 +415,11 @@ class FileSystemState {
|
|||
/// to batch file reads in systems where file fetches are expensive.
|
||||
final void Function(List<String> paths) prefetchFiles;
|
||||
|
||||
final FileSystemStateTimers timers = FileSystemStateTimers();
|
||||
final FileSystemStateTimers timers2 = FileSystemStateTimers();
|
||||
|
||||
final FileSystemStateTestView testView = FileSystemStateTestView();
|
||||
|
||||
FileSystemState(
|
||||
this._logger,
|
||||
this._resourceProvider,
|
||||
this._byteStore,
|
||||
this._sourceFactory,
|
||||
|
@ -432,7 +453,10 @@ class FileSystemState {
|
|||
}
|
||||
}
|
||||
|
||||
FileState getFileForPath(String path) {
|
||||
FileState getFileForPath({
|
||||
@required String path,
|
||||
@required OperationPerformanceImpl performance,
|
||||
}) {
|
||||
var file = _pathToFile[path];
|
||||
if (file == null) {
|
||||
var fileUri = _resourceProvider.pathContext.toUri(path);
|
||||
|
@ -446,12 +470,19 @@ class FileSystemState {
|
|||
_pathToFile[path] = file;
|
||||
_uriToFile[uri] = file;
|
||||
|
||||
file.refresh();
|
||||
performance.run('refresh', (performance) {
|
||||
file.refresh(
|
||||
performance: performance,
|
||||
);
|
||||
});
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
FileState getFileForUri(Uri uri) {
|
||||
FileState getFileForUri({
|
||||
@required Uri uri,
|
||||
@required OperationPerformanceImpl performance,
|
||||
}) {
|
||||
FileState file = _uriToFile[uri];
|
||||
if (file == null) {
|
||||
var source = _sourceFactory.forUri2(uri);
|
||||
|
@ -464,7 +495,9 @@ class FileSystemState {
|
|||
_pathToFile[path] = file;
|
||||
_uriToFile[uri] = file;
|
||||
|
||||
file.refresh();
|
||||
file.refresh(
|
||||
performance: performance,
|
||||
);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
@ -476,18 +509,6 @@ class FileSystemState {
|
|||
}
|
||||
return source.fullName;
|
||||
}
|
||||
|
||||
void logStatistics() {
|
||||
_logger.writeln(
|
||||
'[files: ${_pathToFile.length}]'
|
||||
'[digest: ${timers.digest.timer.elapsedMilliseconds} ms]'
|
||||
'[read: ${timers.read.timer.elapsedMilliseconds} ms]'
|
||||
'[parse: ${timers.parse.timer.elapsedMilliseconds} ms]'
|
||||
'[unlinked: ${timers.unlinked.timer.elapsedMilliseconds} ms]'
|
||||
'[prefetch: ${timers.prefetch.timer.elapsedMilliseconds} ms]',
|
||||
);
|
||||
timers.reset();
|
||||
}
|
||||
}
|
||||
|
||||
class FileSystemStateTestView {
|
||||
|
|
|
@ -218,18 +218,36 @@ class FileResolver {
|
|||
@required OperationPerformanceImpl performance,
|
||||
}) {
|
||||
return performance.run('fileContext', (performance) {
|
||||
var analysisOptions = _getAnalysisOptions(path);
|
||||
_createContext(path, analysisOptions);
|
||||
var analysisOptions = performance.run('analysisOptions', (_) {
|
||||
return _getAnalysisOptions(path);
|
||||
});
|
||||
|
||||
performance.run('createContext', (_) {
|
||||
_createContext(path, analysisOptions);
|
||||
});
|
||||
|
||||
var file = performance.run('fileForPath', (performance) {
|
||||
return fsState.getFileForPath(
|
||||
path: path,
|
||||
performance: performance,
|
||||
);
|
||||
});
|
||||
|
||||
var file = fsState.getFileForPath(path);
|
||||
return FileContext(analysisOptions, file);
|
||||
});
|
||||
}
|
||||
|
||||
String getLibraryLinkedSignature(String path) {
|
||||
String getLibraryLinkedSignature({
|
||||
@required String path,
|
||||
@required OperationPerformanceImpl performance,
|
||||
}) {
|
||||
_throwIfNotAbsoluteNormalizedPath(path);
|
||||
|
||||
var file = fsState.getFileForPath(path);
|
||||
var file = fsState.getFileForPath(
|
||||
path: path,
|
||||
performance: performance,
|
||||
);
|
||||
|
||||
return file.libraryCycle.signatureStr;
|
||||
}
|
||||
|
||||
|
@ -346,7 +364,6 @@ class FileResolver {
|
|||
);
|
||||
|
||||
fsState = FileSystemState(
|
||||
logger,
|
||||
resourceProvider,
|
||||
byteStore,
|
||||
sourceFactory,
|
||||
|
|
|
@ -66,13 +66,17 @@ class OperationPerformanceImpl implements OperationPerformance {
|
|||
);
|
||||
}
|
||||
|
||||
/// Run the [operation] as a new child.
|
||||
/// Run the [operation] as a child with the given [name].
|
||||
///
|
||||
/// If there is no such child, a new one is created, with a new timer.
|
||||
///
|
||||
/// If there is already a child with that name, its timer will resume and
|
||||
/// then stop. So, it will accumulate time across all runs.
|
||||
T run<T>(
|
||||
String name,
|
||||
T Function(OperationPerformanceImpl) operation,
|
||||
) {
|
||||
var child = OperationPerformanceImpl(name);
|
||||
_children.add(child);
|
||||
OperationPerformanceImpl child = _existingOrNewChild(name);
|
||||
child._timer.start();
|
||||
|
||||
try {
|
||||
|
@ -82,13 +86,17 @@ class OperationPerformanceImpl implements OperationPerformance {
|
|||
}
|
||||
}
|
||||
|
||||
/// Run the [operation] as a new child.
|
||||
/// Run the [operation] as a child with the given [name].
|
||||
///
|
||||
/// If there is no such child, a new one is created, with a new timer.
|
||||
///
|
||||
/// If there is already a child with that name, its timer will resume and
|
||||
/// then stop. So, it will accumulate time across all runs.
|
||||
Future<T> runAsync<T>(
|
||||
String name,
|
||||
Future<T> Function(OperationPerformanceImpl) operation,
|
||||
) async {
|
||||
var child = OperationPerformanceImpl(name);
|
||||
_children.add(child);
|
||||
var child = _existingOrNewChild(name);
|
||||
child._timer.start();
|
||||
|
||||
try {
|
||||
|
@ -112,4 +120,13 @@ class OperationPerformanceImpl implements OperationPerformance {
|
|||
child.write(buffer: buffer, indent: childIndent);
|
||||
}
|
||||
}
|
||||
|
||||
OperationPerformanceImpl _existingOrNewChild(String name) {
|
||||
var child = getChild(name);
|
||||
if (child == null) {
|
||||
child = OperationPerformanceImpl(name);
|
||||
_children.add(child);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue