159 lines
3.9 KiB
Dart
159 lines
3.9 KiB
Dart
|
|
// 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;
|
||
|
|
|
||
|
|
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 = PathSet(root);
|
||
|
|
|
||
|
|
/// Use a fixed [math.Random] with a constant seed to ensure the tests are
|
||
|
|
/// deterministic.
|
||
|
|
final math.Random random = 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, void Function(String) callback) {
|
||
|
|
void recurse(String path, int 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 = [];
|
||
|
|
|
||
|
|
@override
|
||
|
|
void setup() {
|
||
|
|
// Make a bunch of paths in about the same order we expect to get them from
|
||
|
|
// Directory.list().
|
||
|
|
walkTree(3, paths.add);
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
void run() {
|
||
|
|
for (var path in paths) {
|
||
|
|
pathSet.add(path);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class ContainsBenchmark extends PathSetBenchmark {
|
||
|
|
ContainsBenchmark() : super('contains()');
|
||
|
|
|
||
|
|
final List<String> paths = [];
|
||
|
|
|
||
|
|
@override
|
||
|
|
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',
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
void run() {
|
||
|
|
var contained = 0;
|
||
|
|
for (var path in paths) {
|
||
|
|
if (pathSet.contains(path)) contained++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (contained != 10000) throw StateError('Wrong result: $contained');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class PathsBenchmark extends PathSetBenchmark {
|
||
|
|
PathsBenchmark() : super('toSet()');
|
||
|
|
|
||
|
|
@override
|
||
|
|
void setup() {
|
||
|
|
walkTree(3, pathSet.add);
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
void run() {
|
||
|
|
var count = 0;
|
||
|
|
for (var _ in pathSet.paths) {
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (count != 10000) throw StateError('Wrong result: $count');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class RemoveBenchmark extends PathSetBenchmark {
|
||
|
|
RemoveBenchmark() : super('remove()');
|
||
|
|
|
||
|
|
final List<String> paths = [];
|
||
|
|
|
||
|
|
@override
|
||
|
|
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);
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
void run() {
|
||
|
|
for (var path in paths) {
|
||
|
|
pathSet.remove(path);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
AddBenchmark().report();
|
||
|
|
ContainsBenchmark().report();
|
||
|
|
PathsBenchmark().report();
|
||
|
|
RemoveBenchmark().report();
|
||
|
|
}
|