blob: 2b26b72c8318bec244546bf81ce68e42a6ba20ec [file] [log] [blame]
// Copyright (c) 2013, 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 observe.test.benchmark.setup_observation_benchmark_base;
import 'dart:async';
import 'dart:html';
import 'package:observable/observable.dart';
import 'package:observe/observe.dart';
import 'package:benchmark_harness/benchmark_harness.dart';
abstract class SetupObservationBenchmarkBase<T extends Observable>
extends BenchmarkBase {
/// The number of objects to create and observe.
final int objectCount;
/// The current configuration.
final String config;
/// The objects we want to observe.
List<T> objects;
SetupObservationBenchmarkBase(String name, this.objectCount, this.config)
: super(name);
/// Subclasses should use this method to return an observable object to be
/// benchmarked.
T newObject();
/// Subclasses should override this to do anything other than a default change
/// listener. It must return either a StreamSubscription or a PathObserver.
newObserver(T obj) => obj.changes.listen((_) {});
/// Set up each benchmark by creating all the objects.
@override
void setup() {
objects = [];
while (objects.length < objectCount) {
objects.add(newObject());
}
}
/// Tear down each the benchmark and remove all listeners.
@override
void teardown() {
while (objects.isNotEmpty) {
var obj = objects.removeLast();
if (obj.hasObservers || (obj is ObservableList && obj.hasListObservers)) {
window.alert('Observers leaked!');
}
}
objects = null;
}
/// Run the benchmark by creating a listener on each object.
@override
void run() {
for (var object in objects) {
var observer = newObserver(object);
// **Note:** This is different than the JS implementation. Since run can
// be called an arbitrary number of times between [setup] and [teardown],
// we clean up all observers as we go. This means we are measuring both
// the setup and teardown of observers, versus the setup only in the
// JS benchmark. Not cleaning these up ends up giving `oh snap` errors.
if (observer is StreamSubscription) {
observer.cancel();
} else if (observer is PathObserver) {
observer.close();
} else {
throw 'Unknown observer type ${observer.runtimeType}. Only '
'[PathObserver] and [StreamSubscription] are supported.';
}
}
}
}