Add performance tests for Map/Set with String and Object keys
authoradamk@chromium.org <adamk@chromium.org>
Wed, 29 Oct 2014 10:18:16 +0000 (10:18 +0000)
committeradamk@chromium.org <adamk@chromium.org>
Wed, 29 Oct 2014 10:18:38 +0000 (10:18 +0000)
The big change here is to split out each key type into its own
benchmark suite, since optimizations for different key types
are likely to be disjoint. ForEach tests have also been split
into separate "Iteration" suites, again with the thought that
iteration performance is likely separable from key type.

As part of adding the new tests, rejiggered the existing tests:
  - Map.set and Set.add (along with their Weak variants) no longer
    include construction costs in their scores
  - Moved key logic into the shared common.js

R=arv@chromium.org, machenbach@chromium.org

Review URL: https://codereview.chromium.org/685753004

Cr-Commit-Position: refs/heads/master@{#24969}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24969 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

test/js-perf-test/Collections/Collections.json
test/js-perf-test/Collections/common.js [new file with mode: 0644]
test/js-perf-test/Collections/map.js
test/js-perf-test/Collections/run.js
test/js-perf-test/Collections/set.js
test/js-perf-test/Collections/weakmap.js
test/js-perf-test/Collections/weakset.js

index 63c3aa5..fd29f46 100644 (file)
@@ -2,14 +2,19 @@
   "name": "JSTests/Collections",
   "path": ["."],
   "main": "run.js",
-  "flags": ["--harmony-collections"],
   "run_count": 5,
   "units": "score",
   "results_regexp": "^%s\\-Collections\\(Score\\): (.+)$",
   "total": true,
   "tests": [
-    {"name": "Map"},
-    {"name": "Set"},
+    {"name": "Map-Smi"},
+    {"name": "Map-String"},
+    {"name": "Map-Object"},
+    {"name": "Map-Iteration"},
+    {"name": "Set-Smi"},
+    {"name": "Set-String"},
+    {"name": "Set-Object"},
+    {"name": "Set-Iteration"},
     {"name": "WeakMap"},
     {"name": "WeakSet"}
   ]
diff --git a/test/js-perf-test/Collections/common.js b/test/js-perf-test/Collections/common.js
new file mode 100644 (file)
index 0000000..3ea3933
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var N = 10;
+var keys;
+
+
+function SetupSmiKeys() {
+  keys = new Array(N * 2);
+  for (var i = 0; i < N * 2; i++) {
+    keys[i] = i;
+  }
+}
+
+
+function SetupStringKeys() {
+  keys = new Array(N * 2);
+  for (var i = 0; i < N * 2; i++) {
+    keys[i] = 's' + i;
+  }
+}
+
+
+function SetupObjectKeys() {
+  keys = new Array(N * 2);
+  for (var i = 0; i < N * 2; i++) {
+    keys[i] = {};
+  }
+}
index b310a71..4f55798 100644 (file)
@@ -3,24 +3,71 @@
 // found in the LICENSE file.
 
 
-var MapBenchmark = new BenchmarkSuite('Map', [1000], [
-  new Benchmark('Set', false, false, 0, MapSet),
-  new Benchmark('Has', false, false, 0, MapHas, MapSetup, MapTearDown),
-  new Benchmark('Get', false, false, 0, MapGet, MapSetup, MapTearDown),
-  new Benchmark('Delete', false, false, 0, MapDelete, MapSetup, MapTearDown),
-  new Benchmark('ForEach', false, false, 0, MapForEach, MapSetup, MapTearDown),
+var MapSmiBenchmark = new BenchmarkSuite('Map-Smi', [1000], [
+  new Benchmark('Set', false, false, 0, MapSetSmi, MapSetupSmiBase, MapTearDown),
+  new Benchmark('Has', false, false, 0, MapHasSmi, MapSetupSmi, MapTearDown),
+  new Benchmark('Get', false, false, 0, MapGetSmi, MapSetupSmi, MapTearDown),
+  new Benchmark('Delete', false, false, 0, MapDeleteSmi, MapSetupSmi, MapTearDown),
+]);
+
+
+var MapStringBenchmark = new BenchmarkSuite('Map-String', [1000], [
+  new Benchmark('Set', false, false, 0, MapSetString, MapSetupStringBase, MapTearDown),
+  new Benchmark('Has', false, false, 0, MapHasString, MapSetupString, MapTearDown),
+  new Benchmark('Get', false, false, 0, MapGetString, MapSetupString, MapTearDown),
+  new Benchmark('Delete', false, false, 0, MapDeleteString, MapSetupString, MapTearDown),
+]);
+
+
+var MapObjectBenchmark = new BenchmarkSuite('Map-Object', [1000], [
+  new Benchmark('Set', false, false, 0, MapSetObject, MapSetupObjectBase, MapTearDown),
+  new Benchmark('Has', false, false, 0, MapHasObject, MapSetupObject, MapTearDown),
+  new Benchmark('Get', false, false, 0, MapGetObject, MapSetupObject, MapTearDown),
+  new Benchmark('Delete', false, false, 0, MapDeleteObject, MapSetupObject, MapTearDown),
+]);
+
+
+var MapIterationBenchmark = new BenchmarkSuite('Map-Iteration', [1000], [
+  new Benchmark('ForEach', false, false, 0, MapForEach, MapSetupSmi, MapTearDown),
 ]);
 
 
 var map;
-var N = 10;
 
 
-function MapSetup() {
+function MapSetupSmiBase() {
+  SetupSmiKeys();
+  map = new Map;
+}
+
+
+function MapSetupSmi() {
+  MapSetupSmiBase();
+  MapSetSmi();
+}
+
+
+function MapSetupStringBase() {
+  SetupStringKeys();
+  map = new Map;
+}
+
+
+function MapSetupString() {
+  MapSetupStringBase();
+  MapSetString();
+}
+
+
+function MapSetupObjectBase() {
+  SetupObjectKeys();
   map = new Map;
-  for (var i = 0; i < N; i++) {
-    map.set(i, i);
-  }
+}
+
+
+function MapSetupObject() {
+  MapSetupObjectBase();
+  MapSetObject();
 }
 
 
@@ -29,45 +76,134 @@ function MapTearDown() {
 }
 
 
-function MapSet() {
-  MapSetup();
-  MapTearDown();
+function MapSetSmi() {
+  for (var i = 0; i < N; i++) {
+    map.set(keys[i], i);
+  }
+}
+
+
+function MapHasSmi() {
+  for (var i = 0; i < N; i++) {
+    if (!map.has(keys[i])) {
+      throw new Error();
+    }
+  }
+  for (var i = N; i < 2 * N; i++) {
+    if (map.has(keys[i])) {
+      throw new Error();
+    }
+  }
+}
+
+
+function MapGetSmi() {
+  for (var i = 0; i < N; i++) {
+    if (map.get(keys[i]) !== i) {
+      throw new Error();
+    }
+  }
+  for (var i = N; i < 2 * N; i++) {
+    if (map.get(keys[i]) !== undefined) {
+      throw new Error();
+    }
+  }
+}
+
+
+function MapDeleteSmi() {
+  // This is run more than once per setup so we will end up deleting items
+  // more than once. Therefore, we do not the return value of delete.
+  for (var i = 0; i < N; i++) {
+    map.delete(keys[i]);
+  }
+}
+
+
+function MapSetString() {
+  for (var i = 0; i < N; i++) {
+    map.set(keys[i], i);
+  }
+}
+
+
+function MapHasString() {
+  for (var i = 0; i < N; i++) {
+    if (!map.has(keys[i])) {
+      throw new Error();
+    }
+  }
+  for (var i = N; i < 2 * N; i++) {
+    if (map.has(keys[i])) {
+      throw new Error();
+    }
+  }
+}
+
+
+function MapGetString() {
+  for (var i = 0; i < N; i++) {
+    if (map.get(keys[i]) !== i) {
+      throw new Error();
+    }
+  }
+  for (var i = N; i < 2 * N; i++) {
+    if (map.get(keys[i]) !== undefined) {
+      throw new Error();
+    }
+  }
+}
+
+
+function MapDeleteString() {
+  // This is run more than once per setup so we will end up deleting items
+  // more than once. Therefore, we do not the return value of delete.
+  for (var i = 0; i < N; i++) {
+    map.delete(keys[i]);
+  }
+}
+
+
+function MapSetObject() {
+  for (var i = 0; i < N; i++) {
+    map.set(keys[i], i);
+  }
 }
 
 
-function MapHas() {
+function MapHasObject() {
   for (var i = 0; i < N; i++) {
-    if (!map.has(i)) {
+    if (!map.has(keys[i])) {
       throw new Error();
     }
   }
   for (var i = N; i < 2 * N; i++) {
-    if (map.has(i)) {
+    if (map.has(keys[i])) {
       throw new Error();
     }
   }
 }
 
 
-function MapGet() {
+function MapGetObject() {
   for (var i = 0; i < N; i++) {
-    if (map.get(i) !== i) {
+    if (map.get(keys[i]) !== i) {
       throw new Error();
     }
   }
   for (var i = N; i < 2 * N; i++) {
-    if (map.get(i) !== undefined) {
+    if (map.get(keys[i]) !== undefined) {
       throw new Error();
     }
   }
 }
 
 
-function MapDelete() {
+function MapDeleteObject() {
   // This is run more than once per setup so we will end up deleting items
   // more than once. Therefore, we do not the return value of delete.
   for (var i = 0; i < N; i++) {
-    map.delete(i);
+    map.delete(keys[i]);
   }
 }
 
index ac80872..50f1ee1 100644 (file)
@@ -4,6 +4,7 @@
 
 
 load('../base.js');
+load('common.js');
 load('map.js');
 load('set.js');
 load('weakmap.js');
index e6455e1..3be27f5 100644 (file)
 // found in the LICENSE file.
 
 
-var SetBenchmark = new BenchmarkSuite('Set', [1000], [
-  new Benchmark('Add', false, false, 0, SetAdd),
-  new Benchmark('Has', false, false, 0, SetHas, SetSetup, SetTearDown),
-  new Benchmark('Delete', false, false, 0, SetDelete, SetSetup, SetTearDown),
-  new Benchmark('ForEach', false, false, 0, SetForEach, SetSetup, SetTearDown),
+var SetSmiBenchmark = new BenchmarkSuite('Set-Smi', [1000], [
+  new Benchmark('Set', false, false, 0, SetAddSmi, SetSetupSmiBase, SetTearDown),
+  new Benchmark('Has', false, false, 0, SetHasSmi, SetSetupSmi, SetTearDown),
+  new Benchmark('Delete', false, false, 0, SetDeleteSmi, SetSetupSmi, SetTearDown),
+]);
+
+
+var SetStringBenchmark = new BenchmarkSuite('Set-String', [1000], [
+  new Benchmark('Set', false, false, 0, SetAddString, SetSetupStringBase, SetTearDown),
+  new Benchmark('Has', false, false, 0, SetHasString, SetSetupString, SetTearDown),
+  new Benchmark('Delete', false, false, 0, SetDeleteString, SetSetupString, SetTearDown),
+]);
+
+
+var SetObjectBenchmark = new BenchmarkSuite('Set-Object', [1000], [
+  new Benchmark('Set', false, false, 0, SetAddObject, SetSetupObjectBase, SetTearDown),
+  new Benchmark('Has', false, false, 0, SetHasObject, SetSetupObject, SetTearDown),
+  new Benchmark('Delete', false, false, 0, SetDeleteObject, SetSetupObject, SetTearDown),
+]);
+
+
+var SetIterationBenchmark = new BenchmarkSuite('Set-Iteration', [1000], [
+  new Benchmark('ForEach', false, false, 0, SetForEach, SetSetupSmi, SetTearDown),
 ]);
 
 
 var set;
-var N = 10;
 
 
-function SetSetup() {
+function SetSetupSmiBase() {
+  SetupSmiKeys();
   set = new Set;
+}
+
+
+function SetSetupSmi() {
+  SetSetupSmiBase();
+  SetAddSmi();
+}
+
+
+function SetSetupStringBase() {
+  SetupStringKeys();
+  set = new Set;
+}
+
+
+function SetSetupString() {
+  SetSetupStringBase();
+  SetAddString();
+}
+
+
+function SetSetupObjectBase() {
+  SetupObjectKeys();
+  set = new Set;
+}
+
+
+function SetSetupObject() {
+  SetSetupObjectBase();
+  SetAddObject();
+}
+
+
+function SetTearDown() {
+  set = null;
+}
+
+
+function SetAddSmi() {
   for (var i = 0; i < N; i++) {
-    set.add(i);
+    set.add(keys[i], i);
   }
 }
 
 
-function SetTearDown() {
-  map = null;
+function SetHasSmi() {
+  for (var i = 0; i < N; i++) {
+    if (!set.has(keys[i])) {
+      throw new Error();
+    }
+  }
+  for (var i = N; i < 2 * N; i++) {
+    if (set.has(keys[i])) {
+      throw new Error();
+    }
+  }
 }
 
 
-function SetAdd() {
-  SetSetup();
-  SetTearDown();
+function SetDeleteSmi() {
+  // This is run more than once per setup so we will end up deleting items
+  // more than once. Therefore, we do not the return value of delete.
+  for (var i = 0; i < N; i++) {
+    set.delete(keys[i]);
+  }
+}
+
+
+function SetAddString() {
+  for (var i = 0; i < N; i++) {
+    set.add(keys[i], i);
+  }
+}
+
+
+function SetHasString() {
+  for (var i = 0; i < N; i++) {
+    if (!set.has(keys[i])) {
+      throw new Error();
+    }
+  }
+  for (var i = N; i < 2 * N; i++) {
+    if (set.has(keys[i])) {
+      throw new Error();
+    }
+  }
+}
+
+
+function SetDeleteString() {
+  // This is run more than once per setup so we will end up deleting items
+  // more than once. Therefore, we do not the return value of delete.
+  for (var i = 0; i < N; i++) {
+    set.delete(keys[i]);
+  }
+}
+
+
+function SetAddObject() {
+  for (var i = 0; i < N; i++) {
+    set.add(keys[i], i);
+  }
 }
 
 
-function SetHas() {
+function SetHasObject() {
   for (var i = 0; i < N; i++) {
-    if (!set.has(i)) {
+    if (!set.has(keys[i])) {
       throw new Error();
     }
   }
   for (var i = N; i < 2 * N; i++) {
-    if (set.has(i)) {
+    if (set.has(keys[i])) {
       throw new Error();
     }
   }
 }
 
 
-function SetDelete() {
+function SetDeleteObject() {
   // This is run more than once per setup so we will end up deleting items
   // more than once. Therefore, we do not the return value of delete.
   for (var i = 0; i < N; i++) {
-    set.delete(i);
+    set.delete(keys[i]);
   }
 }
 
index 8736dfd..9aa265f 100644 (file)
@@ -4,7 +4,8 @@
 
 
 var MapBenchmark = new BenchmarkSuite('WeakMap', [1000], [
-  new Benchmark('Set', false, false, 0, WeakMapSet),
+  new Benchmark('Set', false, false, 0, WeakMapSet, WeakMapSetupBase,
+      WeakMapTearDown),
   new Benchmark('Has', false, false, 0, WeakMapHas, WeakMapSetup,
       WeakMapTearDown),
   new Benchmark('Get', false, false, 0, WeakMapGet, WeakMapSetup,
@@ -15,20 +16,17 @@ var MapBenchmark = new BenchmarkSuite('WeakMap', [1000], [
 
 
 var wm;
-var N = 10;
-var keys = [];
 
 
-for (var i = 0; i < N * 2; i++) {
-  keys[i] = {};
+function WeakMapSetupBase() {
+  SetupObjectKeys();
+  wm = new WeakMap;
 }
 
 
 function WeakMapSetup() {
-  wm = new WeakMap;
-  for (var i = 0; i < N; i++) {
-    wm.set(keys[i], i);
-  }
+  WeakMapSetupBase();
+  WeakMapSet();
 }
 
 
@@ -38,8 +36,9 @@ function WeakMapTearDown() {
 
 
 function WeakMapSet() {
-  WeakMapSetup();
-  WeakMapTearDown();
+  for (var i = 0; i < N; i++) {
+    wm.set(keys[i], i);
+  }
 }
 
 
index a7d0f3d..2936477 100644 (file)
@@ -4,7 +4,8 @@
 
 
 var SetBenchmark = new BenchmarkSuite('WeakSet', [1000], [
-  new Benchmark('Add', false, false, 0, WeakSetAdd),
+  new Benchmark('Add', false, false, 0, WeakSetAdd, WeakSetSetupBase,
+      WeakSetTearDown),
   new Benchmark('Has', false, false, 0, WeakSetHas, WeakSetSetup,
       WeakSetTearDown),
   new Benchmark('Delete', false, false, 0, WeakSetDelete, WeakSetSetup,
@@ -13,20 +14,17 @@ var SetBenchmark = new BenchmarkSuite('WeakSet', [1000], [
 
 
 var ws;
-var N = 10;
-var keys = [];
 
 
-for (var i = 0; i < N * 2; i++) {
-  keys[i] = {};
+function WeakSetSetupBase() {
+  SetupObjectKeys();
+  ws = new WeakSet;
 }
 
 
 function WeakSetSetup() {
-  ws = new WeakSet;
-  for (var i = 0; i < N; i++) {
-    ws.add(keys[i]);
-  }
+  WeakSetSetupBase();
+  WeakSetAdd();
 }
 
 
@@ -36,8 +34,9 @@ function WeakSetTearDown() {
 
 
 function WeakSetAdd() {
-  WeakSetSetup();
-  WeakSetTearDown();
+  for (var i = 0; i < N; i++) {
+    ws.add(keys[i]);
+  }
 }