Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(667)

Unified Diff: tests/standalone/priority_queue_stress_test.dart

Issue 689713003: Context objects don't have a compile-type. Return dynamic-type in this case. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/flow_graph_type_propagator.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tests/standalone/priority_queue_stress_test.dart
===================================================================
--- tests/standalone/priority_queue_stress_test.dart (revision 0)
+++ tests/standalone/priority_queue_stress_test.dart (revision 0)
@@ -0,0 +1,323 @@
+// Copyright (c) 2014, 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 priority_queue;
+
+import 'dart:collection';
+import 'dart:math';
+
+/**
+ * A priority used for the priority queue. Subclasses only need to implement
+ * the compareTo function.
+ */
+abstract class Priority implements Comparable {
+ /**
+ * Return < 0 if other is bigger, >0 if other is smaller, 0 if they are equal.
+ */
+ int compareTo(Priority other);
+ bool operator<(Priority other) => compareTo(other) < 0;
+ bool operator>(Priority other) => compareTo(other) > 0;
+ bool operator==(Priority other) => compareTo(other) == 0;
+}
+
+/**
+ * Priority based on integers.
+ */
+class IntPriority extends Priority {
+ int priority;
+ IntPriority(int this.priority);
+
+ int compareTo(IntPriority other) {
+ return priority - other.priority;
+ }
+ String toString() => "$priority";
+}
+
+/**
+ * An element of a priority queue. The type is used restriction based
+ * querying of the queues.
+ */
+abstract class TypedElement<V> {
+ bool typeEquals(var other);
+}
+
+class StringTypedElement<V> extends TypedElement{
+ String type;
+ V value;
+ StringTypedElement(String this.type, V this.value);
+ bool typeEquals(String otherType) => otherType == type;
+ String toString() => "<Type: $type, Value: $value>";
+}
+
+
+/**
+ * A priority node in a priority queue. A priority node contains all of the
+ * values for a given priority in a given queue. It is part of a linked
+ * list of nodes, with prev and next pointers.
+ */
+class PriorityNode<N extends TypedElement, T extends Priority> {
+ T priority;
+ Queue<N> values;
+ PriorityNode prev;
+ PriorityNode next;
+ PriorityNode(N initialNode, T this.priority)
+ : values = new Queue<N>() {
+ add(initialNode);
+ }
+
+ void add(N n) => values.add(n);
+
+ bool remove(N n) => values.remove(n);
+
+ N removeFirst() => values.removeFirst();
+
+ bool get isEmpty => values.isEmpty;
+
+ N get first => values.first;
+
+ String toString() => "Priority: $priority $values";
+}
+
+/**
+ * A priority queue with a FIFO property for nodes with same priority.
+ * The queue guarantees that nodes are returned in the same order they
+ * are added for a given priority.
+ * For type safety this queue is guarded by the elements being subclasses of
+ * TypedElement - this is not strictly neccesary since we never actually
+ * use the value or type of the nodes.
+ */
+class PriorityQueue<N extends TypedElement, P extends Priority> {
+ PriorityNode<N, P> head;
+ int length = 0;
+
+ void add(N value, P priority) {
+ length++;
+ if (head == null) {
+ head = new PriorityNode<N, P>(value, priority);
+ return;
+ }
+ assert(head.next == null);
+ var node = head;
+ while (node.prev != null && node.priority > priority) {
+ node = node.prev;
+ }
+ if (node.priority == priority) {
+ node.add(value);
+ } else if (node.priority < priority) {
+ var newNode = new PriorityNode<N, P>(value, priority);
+ newNode.next = node.next;
+ if (node.next != null) node.next.prev = newNode;
+ newNode.prev = node;
+ node.next = newNode;
+ if (node == head) head = newNode;
+ } else {
+ var newNode = new PriorityNode<N, P>(value, priority);
+ node.prev = newNode;
+ newNode.next = node;
+ }
+ }
+
+ N get first => head.first;
+
+ Priority get firstPriority => head.priority;
+
+ bool get isEmpty => head == null;
+
+ N removeFirst() {
+ if (isEmpty) throw "Can't get element from empty queue";
+ var value = head.removeFirst();
+ if (head.isEmpty) {
+ if (head.prev != null) {
+ head.prev.next = null;
+ }
+ head = head.prev;
+ }
+ length--;
+ assert(head == null || head.next == null);
+ return value;
+ }
+
+ String toString() {
+ if (head == null) return "Empty priority queue";
+ var node = head;
+ var buffer = new StringBuffer();
+ while (node.prev != null) {
+ buffer.writeln(node);
+ node = node.prev;
+ }
+ buffer.writeln(node);
+ return buffer.toString();
+ }
+}
+
+/**
+ * Implements a specialized priority queue that efficiently allows getting
+ * the highest priorized node that adheres to a set of restrictions.
+ * Most notably it allows to get the highest priority node where the node's
+ * type is not in an exclude list.
+ * In addition, the queue has a number of properties:
+ * The queue has fifo semantics for nodes with the same priority and type,
+ * i.e., if nodes a and b are added to the queue with priority x and type z
+ * then a is returned first iff a was added before b
+ * For different types with the same priority no guarantees are given, but
+ * the returned values try to be fair by returning from the biggest list of
+ * tasks in case of priority clash. (This could be fixed by adding timestamps
+ * to every node, that is _only_ used when collisions occur, not for
+ * insertions)
+ */
+class RestrictViewPriorityQueue<N extends TypedElement, P extends Priority> {
+ // We can't use the basic dart priority queue since it does not guarantee
+ // FIFO for items with the same order. This is currently not uptimized for
+ // different N, if many different N is expected here we should have a
+ // priority queue instead of a list.
+ List<PriorityQueue<N, P>> restrictedQueues = new List<PriorityQueue<N, P>>();
+ PriorityQueue<N, P> mainQueue = new PriorityQueue<N, P>();
+
+ void add(N value, P priority) {
+ for (var queue in restrictedQueues) {
+ if (queue.first.value == value) {
+ queue.add(value, priority);
+ }
+ }
+ mainQueue.add(value, priority);
+ }
+
+ bool get isEmpty => restrictedQueues.length + mainQueue.length == 0;
+
+ int get length => restrictedQueues.fold(0, (v, e) => v + element.length) +
+ mainQueue.length;
+
+ PriorityQueue getRestricted(List<N> restrictions) {
+ var current = null;
+ // Find highest restricted priority.
+ for (var queue in restrictedQueues) {
+ if (!restrictions.any((e) => queue.head.first.typeEquals(e))) {
+ if (current == null || queue.firstPriority > current.firstPriority) {
+ current = queue;
+ } else if (current.firstPriority == queue.firstPriority) {
+ current = queue.length > current.length ? queue : current;
+ }
+ }
+ }
+ return current;
+ }
+
+ N get first {
+ if (isEmpty) throw "Trying to remove node from empty queue";
+ var candidate = getRestricted([]);
+ if (candidate != null &&
+ (mainQueue.isEmpty ||
+ mainQueue.first.priority < candidate.first.priority)) {
+ return candidate.first;
+ }
+ return mainQueue.isEmpty ? null : mainQueue.first;
+ }
+
+ /**
+ * Returns the node that under the given set of restrictions.
+ * If the queue is empty this function throws.
+ * If the queue is not empty, but no node exists that adheres to the
+ * restrictions we return null.
+ */
+ N removeFirst({List restrictions: const []}) {
+ if (isEmpty) throw "Trying to remove node from empty queue";
+ var candidate = getRestricted(restrictions);
+
+ if (candidate != null &&
+ (mainQueue.isEmpty ||
+ mainQueue.firstPriority < candidate.firstPriority)) {
+ var value = candidate.removeFirst();
+ if (candidate.isEmpty) restrictedQueues.remove(candidate);
+ return value;
+ }
+ while (!mainQueue.isEmpty) {
+ var currentPriority = mainQueue.firstPriority;
+ var current = mainQueue.removeFirst();
+ if (!restrictions.any((e) => current.typeEquals(e))) {
+ return current;
+ } else {
+ var restrictedQueue = restrictedQueues
+ .firstWhere((e) => current.typeEquals(e.first.type),
+ orElse: () => null);
+ if (restrictedQueue == null) {
+ restrictedQueue = new PriorityQueue<N, P>();
+ restrictedQueues.add(restrictedQueue);
+ }
+ restrictedQueue.add(current, currentPriority);
+ }
+ }
+ }
+
+ String toString() {
+ if (isEmpty) return "Empty queue";
+ var buffer = new StringBuffer();
+ if (!restrictedQueues.isEmpty) {
+ buffer.writeln("Restricted queues");
+ for (var queue in restrictedQueues) {
+ buffer.writeln("$queue");
+ }
+ }
+ buffer.writeln("Main queue:");
+ buffer.writeln("$mainQueue");
+ return buffer.toString();
+ }
+}
+
+/// TEMPORARY TESTING AND PERFORMANCE
+void main([args]) {
+ stress(new RestrictViewPriorityQueue<StringTypedElement, IntPriority>());
+}
+
+void stress(queue) {
+ final int SIZE = 50000;
+ Random random = new Random(29);
+
+ var priorities = [1, 2, 3, 16, 32, 42, 56, 57, 59, 90];
+ var values = [new StringTypedElement('safari', 'foo'),
+ new StringTypedElement('ie', 'bar'),
+ new StringTypedElement('ff', 'foobar'),
+ new StringTypedElement('dartium', 'barfoo'),
+ new StringTypedElement('chrome', 'hest'),
+ new StringTypedElement('drt', 'fisk')];
+
+ var restricted = ['safari', 'chrome'];
+
+
+ void addRandom() {
+ queue.add(values[random.nextInt(values.length)],
+ new IntPriority(priorities[random.nextInt(priorities.length)]));
+ }
+
+ var stopwatch = new Stopwatch()..start();
+ while(queue.length < SIZE) {
+ addRandom();
+ }
+
+ stopwatch.stop();
+ print("Adding took: ${stopwatch.elapsedMilliseconds}");
+ print("Queue length: ${queue.length}");
+
+ stopwatch = new Stopwatch()..start();
+ while(queue.length > 0) {
+ queue.removeFirst();
+ }
+ stopwatch.stop();
+ print("Remowing took: ${stopwatch.elapsedMilliseconds}");
+ print("Queue length: ${queue.length}");
+
+
+ print("Restricted add/remove");
+ while(queue.length < SIZE) {
+ addRandom();
+ }
+
+ for (int i = 0; i < SIZE; i++) {
+ if (random.nextDouble() < 0.5) {
+ queue.removeFirst(restrictions: restricted);
+ } else {
+ queue.removeFirst();
+ }
+ addRandom();
+ }
+}
« no previous file with comments | « runtime/vm/flow_graph_type_propagator.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698