| Index: pkg/analysis_server/benchmark/perf/benchmarks_impl.dart | 
| diff --git a/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart b/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..8b2c0695abc9836a29f9b113c34afd4010bfb921 | 
| --- /dev/null | 
| +++ b/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart | 
| @@ -0,0 +1,183 @@ | 
| +// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file | 
| +// for details. All rights reserved. Use of this source code is governed by a | 
| +// BSD-style license that can be found in the LICENSE file. | 
| + | 
| +import 'dart:async'; | 
| +import 'dart:io'; | 
| + | 
| +import 'package:analysis_server/src/protocol_server.dart'; | 
| +import 'package:path/path.dart' as path; | 
| + | 
| +import '../../test/integration/support/integration_tests.dart'; | 
| +import '../benchmarks.dart'; | 
| +import 'memory_tests.dart'; | 
| + | 
| +/// benchmarks: | 
| +///   - analysis-server-cold-analysis | 
| +///   - analysis-server-cold-memory | 
| +class ColdAnalysisBenchmark extends Benchmark { | 
| +  ColdAnalysisBenchmark() | 
| +      : super( | 
| +          'analysis-server-cold', | 
| +          'Analysis server benchmarks of a large project on start-up, no ' | 
| +              'existing driver cache.', | 
| +        ); | 
| + | 
| +  int get maxIterations => 3; | 
| + | 
| +  @override | 
| +  Future<BenchMarkResult> run({bool quick: false}) async { | 
| +    deleteServerCache(); | 
| + | 
| +    Stopwatch stopwatch = new Stopwatch()..start(); | 
| + | 
| +    AnalysisServerMemoryUsageTest test = new AnalysisServerMemoryUsageTest(); | 
| +    await test.setUp(); | 
| +    await test.subscribeToStatusNotifications(); | 
| +    await test.sendAnalysisSetAnalysisRoots(getProjectRoots(quick: quick), []); | 
| +    await test.analysisFinished; | 
| + | 
| +    stopwatch.stop(); | 
| +    int usedBytes = test.getMemoryUsage(); | 
| + | 
| +    CompoundBenchMarkResult result = new CompoundBenchMarkResult(id); | 
| +    result.add('analysis', | 
| +        new BenchMarkResult('micros', stopwatch.elapsedMicroseconds)); | 
| +    result.add('memory', new BenchMarkResult('bytes', usedBytes)); | 
| + | 
| +    await test.shutdown(); | 
| + | 
| +    return result; | 
| +  } | 
| +} | 
| + | 
| +/// benchmarks: | 
| +///   - analysis-server-warm-analysis | 
| +///   - analysis-server-warm-memory | 
| +///   - analysis-server-edit | 
| +///   - analysis-server-completion | 
| +class AnalysisBenchmark extends Benchmark { | 
| +  AnalysisBenchmark() | 
| +      : super( | 
| +          'analysis-server', | 
| +          'Analysis server benchmarks of a large project, with an existing ' | 
| +              'driver cache.', | 
| +        ); | 
| + | 
| +  @override | 
| +  Future<BenchMarkResult> run({bool quick: false}) async { | 
| +    Stopwatch stopwatch = new Stopwatch()..start(); | 
| + | 
| +    AnalysisServerMemoryUsageTest test = new AnalysisServerMemoryUsageTest(); | 
| +    await test.setUp(); | 
| +    await test.subscribeToStatusNotifications(); | 
| +    await test.sendAnalysisSetAnalysisRoots(getProjectRoots(quick: quick), []); | 
| +    await test.analysisFinished; | 
| + | 
| +    stopwatch.stop(); | 
| +    int usedBytes = test.getMemoryUsage(); | 
| + | 
| +    CompoundBenchMarkResult result = new CompoundBenchMarkResult(id); | 
| +    result.add('warm-analysis', | 
| +        new BenchMarkResult('micros', stopwatch.elapsedMicroseconds)); | 
| +    result.add('warm-memory', new BenchMarkResult('bytes', usedBytes)); | 
| + | 
| +    if (!quick) { | 
| +      // change timing | 
| +      final int editMicros = await _calcEditTiming(test); | 
| +      result.add('edit', new BenchMarkResult('micros', editMicros)); | 
| + | 
| +      // code completion | 
| +      final int completionMicros = await _calcCompletionTiming(test); | 
| +      result.add('completion', new BenchMarkResult('micros', completionMicros)); | 
| +    } | 
| + | 
| +    await test.shutdown(); | 
| + | 
| +    return result; | 
| +  } | 
| + | 
| +  Future<int> _calcEditTiming( | 
| +      AbstractAnalysisServerIntegrationTest test) async { | 
| +    const int kGroupCount = 5; | 
| + | 
| +    final String filePath = | 
| +        path.join(analysisServerSrcPath, 'lib/src/analysis_server.dart'); | 
| +    String contents = new File(filePath).readAsStringSync(); | 
| + | 
| +    await test | 
| +        .sendAnalysisUpdateContent({filePath: new AddContentOverlay(contents)}); | 
| + | 
| +    final Stopwatch stopwatch = new Stopwatch()..start(); | 
| + | 
| +    for (int i = 0; i < kGroupCount; i++) { | 
| +      int startIndex = i * (contents.length ~/ (kGroupCount + 2)); | 
| +      int index = contents.indexOf(';', startIndex); | 
| +      contents = contents.substring(0, index + 1) + | 
| +          ' ' + | 
| +          contents.substring(index + 1); | 
| +      test.sendAnalysisUpdateContent( | 
| +          {filePath: new AddContentOverlay(contents)}); | 
| +      await test.analysisFinished; | 
| +    } | 
| + | 
| +    stopwatch.stop(); | 
| + | 
| +    return stopwatch.elapsedMicroseconds ~/ kGroupCount; | 
| +  } | 
| + | 
| +  Future<int> _calcCompletionTiming( | 
| +      AbstractAnalysisServerIntegrationTest test) async { | 
| +    const int kGroupCount = 10; | 
| + | 
| +    final String filePath = | 
| +        path.join(analysisServerSrcPath, 'lib/src/analysis_server.dart'); | 
| +    String contents = new File(filePath).readAsStringSync(); | 
| + | 
| +    await test | 
| +        .sendAnalysisUpdateContent({filePath: new AddContentOverlay(contents)}); | 
| + | 
| +    int completionCount = 0; | 
| +    final Stopwatch stopwatch = new Stopwatch()..start(); | 
| + | 
| +    Future _complete(int offset) async { | 
| +      CompletionGetSuggestionsResult result = | 
| +          await test.sendCompletionGetSuggestions(filePath, offset); | 
| + | 
| +      Future<CompletionResultsParams> future = test.onCompletionResults | 
| +          .where((CompletionResultsParams params) => | 
| +              params.id == result.id && params.isLast) | 
| +          .first; | 
| +      await future; | 
| + | 
| +      completionCount++; | 
| +    } | 
| + | 
| +    for (int i = 0; i < kGroupCount; i++) { | 
| +      int startIndex = i * (contents.length ~/ (kGroupCount + 2)); | 
| +      // Look for a line with a period in it that ends with a semi-colon. | 
| +      int index = | 
| +          contents.indexOf(new RegExp(r'\..*;$', multiLine: true), startIndex); | 
| + | 
| +      await _complete(index - 10); | 
| +      await _complete(index - 1); | 
| +      await _complete(index); | 
| +      await _complete(index + 1); | 
| +      await _complete(index + 10); | 
| + | 
| +      if (i + 1 < kGroupCount) { | 
| +        // mutate | 
| +        index = contents.indexOf(';', index); | 
| +        contents = contents.substring(0, index + 1) + | 
| +            ' ' + | 
| +            contents.substring(index + 1); | 
| +        await test.sendAnalysisUpdateContent( | 
| +            {filePath: new AddContentOverlay(contents)}); | 
| +      } | 
| +    } | 
| + | 
| +    stopwatch.stop(); | 
| + | 
| +    return stopwatch.elapsedMicroseconds ~/ completionCount; | 
| +  } | 
| +} | 
|  |