| // Copyright (c) 2015, 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. |
| |
| /// Benchmarks for the PathSet class. |
| library watcher.benchmark.path_set; |
| |
| import 'dart:io'; |
| import 'dart:math' as math; |
| |
| import 'package:benchmark_harness/benchmark_harness.dart'; |
| import 'package:path/path.dart' as p; |
| |
| import 'package:watcher/src/path_set.dart'; |
| |
| final String root = Platform.isWindows ? r"C:\root" : "/root"; |
| |
| /// Base class for benchmarks on [PathSet]. |
| abstract class PathSetBenchmark extends BenchmarkBase { |
| PathSetBenchmark(String method) : super("PathSet.$method"); |
| |
| final PathSet pathSet = new PathSet(root); |
| |
| /// Use a fixed [Random] with a constant seed to ensure the tests are |
| /// deterministic. |
| final math.Random random = new math.Random(1234); |
| |
| /// Walks over a virtual directory [depth] levels deep invoking [callback] |
| /// for each "file". |
| /// |
| /// Each virtual directory contains ten entries: either subdirectories or |
| /// files. |
| void walkTree(int depth, callback(String path)) { |
| recurse(path, remainingDepth) { |
| for (var i = 0; i < 10; i++) { |
| var padded = i.toString().padLeft(2, '0'); |
| if (remainingDepth == 0) { |
| callback(p.join(path, "file_$padded.txt")); |
| } else { |
| var subdir = p.join(path, "subdirectory_$padded"); |
| recurse(subdir, remainingDepth - 1); |
| } |
| } |
| } |
| |
| recurse(root, depth); |
| } |
| } |
| |
| class AddBenchmark extends PathSetBenchmark { |
| AddBenchmark() : super("add()"); |
| |
| final List<String> paths = []; |
| |
| void setup() { |
| // Make a bunch of paths in about the same order we expect to get them from |
| // Directory.list(). |
| walkTree(3, paths.add); |
| } |
| |
| void run() { |
| for (var path in paths) pathSet.add(path); |
| } |
| } |
| |
| class ContainsBenchmark extends PathSetBenchmark { |
| ContainsBenchmark() : super("contains()"); |
| |
| final List<String> paths = []; |
| |
| void setup() { |
| // Add a bunch of paths to the set. |
| walkTree(3, (path) { |
| pathSet.add(path); |
| paths.add(path); |
| }); |
| |
| // Add some non-existent paths to test the false case. |
| for (var i = 0; i < 100; i++) { |
| paths.addAll([ |
| "/nope", |
| "/root/nope", |
| "/root/subdirectory_04/nope", |
| "/root/subdirectory_04/subdirectory_04/nope", |
| "/root/subdirectory_04/subdirectory_04/subdirectory_04/nope", |
| "/root/subdirectory_04/subdirectory_04/subdirectory_04/nope/file_04.txt", |
| ]); |
| } |
| } |
| |
| void run() { |
| var contained = 0; |
| for (var path in paths) { |
| if (pathSet.contains(path)) contained++; |
| } |
| |
| if (contained != 10000) throw "Wrong result: $contained"; |
| } |
| } |
| |
| class PathsBenchmark extends PathSetBenchmark { |
| PathsBenchmark() : super("toSet()"); |
| |
| void setup() { |
| walkTree(3, pathSet.add); |
| } |
| |
| void run() { |
| var count = 0; |
| for (var _ in pathSet.paths) { |
| count++; |
| } |
| |
| if (count != 10000) throw "Wrong result: $count"; |
| } |
| } |
| |
| class RemoveBenchmark extends PathSetBenchmark { |
| RemoveBenchmark() : super("remove()"); |
| |
| final List<String> paths = []; |
| |
| void setup() { |
| // Make a bunch of paths. Do this here so that we don't spend benchmarked |
| // time synthesizing paths. |
| walkTree(3, (path) { |
| pathSet.add(path); |
| paths.add(path); |
| }); |
| |
| // Shuffle the paths so that we delete them in a random order that |
| // hopefully mimics real-world file system usage. Do the shuffling here so |
| // that we don't spend benchmarked time shuffling. |
| paths.shuffle(random); |
| } |
| |
| void run() { |
| for (var path in paths) pathSet.remove(path); |
| } |
| } |
| |
| main() { |
| new AddBenchmark().report(); |
| new ContainsBenchmark().report(); |
| new PathsBenchmark().report(); |
| new RemoveBenchmark().report(); |
| } |