// Copyright (c) 2016, 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. library kernel.treeshaker_bench; import 'dart:io'; import 'package:args/args.dart'; import 'package:kernel/class_hierarchy.dart'; import 'package:kernel/core_types.dart'; import 'package:kernel/kernel.dart'; import 'package:kernel/transformations/treeshaker.dart'; import 'class_hierarchy_basic.dart'; ArgParser argParser = new ArgParser(allowTrailingOptions: true) ..addFlag('basic', help: 'Use the basic class hierarchy implementation', negatable: false) ..addFlag('from-scratch', help: 'Rebuild class hierarchy for each tree shaking', negatable: false) ..addFlag('diagnose', abbr: 'd', help: 'Print internal diagnostics', negatable: false) ..addFlag('strong', help: 'Run the tree shaker in strong mode', negatable: false); String usage = ''' Usage: treeshaker_bench [options] FILE.dill Benchmark the tree shaker and the class hierarchy it depends on. Options: ${argParser.usage} '''; void main(List args) { if (args.length == 0) { print(usage); exit(1); } ArgResults options = argParser.parse(args); if (options.rest.length != 1) { print('Exactly one file must be given'); exit(1); } String filename = options.rest.single; bool strongMode = options['strong']; Component component = loadComponentFromBinary(filename); ClassHierarchy buildClassHierarchy() { return options['basic'] ? new BasicClassHierarchy(component) : new ClassHierarchy(component); } CoreTypes coreTypes = new CoreTypes(component); var watch = new Stopwatch()..start(); ClassHierarchy sharedClassHierarchy = buildClassHierarchy(); int coldHierarchyTime = watch.elapsedMicroseconds; var shaker = new TreeShaker(coreTypes, sharedClassHierarchy, component, strongMode: strongMode); if (options['diagnose']) { print(shaker.getDiagnosticString()); } shaker = null; int coldTreeShakingTime = watch.elapsedMicroseconds; ClassHierarchy getClassHierarchy() { return options['from-scratch'] ? buildClassHierarchy() : sharedClassHierarchy; } const int numberOfTrials = 50; int hotHierarchyTime = 0; int hotTreeShakingTime = 0; watch.reset(); for (int i = 0; i < numberOfTrials; i++) { watch.reset(); var hierarchy = getClassHierarchy(); hotHierarchyTime += watch.elapsedMicroseconds; new TreeShaker(coreTypes, hierarchy, component, strongMode: strongMode); hotTreeShakingTime += watch.elapsedMicroseconds; } hotHierarchyTime ~/= numberOfTrials; hotTreeShakingTime ~/= numberOfTrials; var coldShakingMs = coldTreeShakingTime ~/ 1000; var coldHierarchyMs = coldHierarchyTime ~/ 1000; var hotShakingMs = hotTreeShakingTime ~/ 1000; var hotHierarchyMs = hotHierarchyTime ~/ 1000; print(''' build.cold $coldShakingMs ms ($coldHierarchyMs ms from hierarchy) build.hot $hotShakingMs ms ($hotHierarchyMs ms from hierarchy)'''); }