Commit 5b85911e authored by adamk@chromium.org's avatar adamk@chromium.org

Add performance tests for Map/Set with String and Object keys

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
parent 48643341
...@@ -2,14 +2,19 @@ ...@@ -2,14 +2,19 @@
"name": "JSTests/Collections", "name": "JSTests/Collections",
"path": ["."], "path": ["."],
"main": "run.js", "main": "run.js",
"flags": ["--harmony-collections"],
"run_count": 5, "run_count": 5,
"units": "score", "units": "score",
"results_regexp": "^%s\\-Collections\\(Score\\): (.+)$", "results_regexp": "^%s\\-Collections\\(Score\\): (.+)$",
"total": true, "total": true,
"tests": [ "tests": [
{"name": "Map"}, {"name": "Map-Smi"},
{"name": "Set"}, {"name": "Map-String"},
{"name": "Map-Object"},
{"name": "Map-Iteration"},
{"name": "Set-Smi"},
{"name": "Set-String"},
{"name": "Set-Object"},
{"name": "Set-Iteration"},
{"name": "WeakMap"}, {"name": "WeakMap"},
{"name": "WeakSet"} {"name": "WeakSet"}
] ]
......
// 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] = {};
}
}
...@@ -3,24 +3,71 @@ ...@@ -3,24 +3,71 @@
// found in the LICENSE file. // found in the LICENSE file.
var MapBenchmark = new BenchmarkSuite('Map', [1000], [ var MapSmiBenchmark = new BenchmarkSuite('Map-Smi', [1000], [
new Benchmark('Set', false, false, 0, MapSet), new Benchmark('Set', false, false, 0, MapSetSmi, MapSetupSmiBase, MapTearDown),
new Benchmark('Has', false, false, 0, MapHas, MapSetup, MapTearDown), new Benchmark('Has', false, false, 0, MapHasSmi, MapSetupSmi, MapTearDown),
new Benchmark('Get', false, false, 0, MapGet, MapSetup, MapTearDown), new Benchmark('Get', false, false, 0, MapGetSmi, MapSetupSmi, MapTearDown),
new Benchmark('Delete', false, false, 0, MapDelete, MapSetup, MapTearDown), new Benchmark('Delete', false, false, 0, MapDeleteSmi, MapSetupSmi, MapTearDown),
new Benchmark('ForEach', false, false, 0, MapForEach, MapSetup, 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 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; map = new Map;
for (var i = 0; i < N; i++) { }
map.set(i, i);
}
function MapSetupObject() {
MapSetupObjectBase();
MapSetObject();
} }
...@@ -29,45 +76,134 @@ function MapTearDown() { ...@@ -29,45 +76,134 @@ function MapTearDown() {
} }
function MapSet() { function MapSetSmi() {
MapSetup(); for (var i = 0; i < N; i++) {
MapTearDown(); 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++) { for (var i = 0; i < N; i++) {
if (!map.has(i)) { if (!map.has(keys[i])) {
throw new Error(); throw new Error();
} }
} }
for (var i = N; i < 2 * N; i++) { for (var i = N; i < 2 * N; i++) {
if (map.has(i)) { if (map.has(keys[i])) {
throw new Error(); throw new Error();
} }
} }
} }
function MapGet() { function MapGetObject() {
for (var i = 0; i < N; i++) { for (var i = 0; i < N; i++) {
if (map.get(i) !== i) { if (map.get(keys[i]) !== i) {
throw new Error(); throw new Error();
} }
} }
for (var i = N; i < 2 * N; i++) { for (var i = N; i < 2 * N; i++) {
if (map.get(i) !== undefined) { if (map.get(keys[i]) !== undefined) {
throw new Error(); throw new Error();
} }
} }
} }
function MapDelete() { function MapDeleteObject() {
// This is run more than once per setup so we will end up deleting items // 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. // more than once. Therefore, we do not the return value of delete.
for (var i = 0; i < N; i++) { for (var i = 0; i < N; i++) {
map.delete(i); map.delete(keys[i]);
} }
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
load('../base.js'); load('../base.js');
load('common.js');
load('map.js'); load('map.js');
load('set.js'); load('set.js');
load('weakmap.js'); load('weakmap.js');
......
...@@ -3,56 +3,162 @@ ...@@ -3,56 +3,162 @@
// found in the LICENSE file. // found in the LICENSE file.
var SetBenchmark = new BenchmarkSuite('Set', [1000], [ var SetSmiBenchmark = new BenchmarkSuite('Set-Smi', [1000], [
new Benchmark('Add', false, false, 0, SetAdd), new Benchmark('Set', false, false, 0, SetAddSmi, SetSetupSmiBase, SetTearDown),
new Benchmark('Has', false, false, 0, SetHas, SetSetup, SetTearDown), new Benchmark('Has', false, false, 0, SetHasSmi, SetSetupSmi, SetTearDown),
new Benchmark('Delete', false, false, 0, SetDelete, SetSetup, SetTearDown), new Benchmark('Delete', false, false, 0, SetDeleteSmi, SetSetupSmi, SetTearDown),
new Benchmark('ForEach', false, false, 0, SetForEach, SetSetup, 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 set;
var N = 10;
function SetSetup() { function SetSetupSmiBase() {
SetupSmiKeys();
set = new Set; 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++) { for (var i = 0; i < N; i++) {
set.add(i); set.add(keys[i], i);
} }
} }
function SetTearDown() { function SetHasSmi() {
map = null; 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() { function SetDeleteSmi() {
SetSetup(); // This is run more than once per setup so we will end up deleting items
SetTearDown(); // 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++) { for (var i = 0; i < N; i++) {
if (!set.has(i)) { if (!set.has(keys[i])) {
throw new Error(); throw new Error();
} }
} }
for (var i = N; i < 2 * N; i++) { for (var i = N; i < 2 * N; i++) {
if (set.has(i)) { if (set.has(keys[i])) {
throw new Error(); throw new Error();
} }
} }
} }
function SetDelete() { function SetDeleteObject() {
// This is run more than once per setup so we will end up deleting items // 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. // more than once. Therefore, we do not the return value of delete.
for (var i = 0; i < N; i++) { for (var i = 0; i < N; i++) {
set.delete(i); set.delete(keys[i]);
} }
} }
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
var MapBenchmark = new BenchmarkSuite('WeakMap', [1000], [ 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, new Benchmark('Has', false, false, 0, WeakMapHas, WeakMapSetup,
WeakMapTearDown), WeakMapTearDown),
new Benchmark('Get', false, false, 0, WeakMapGet, WeakMapSetup, new Benchmark('Get', false, false, 0, WeakMapGet, WeakMapSetup,
...@@ -15,20 +16,17 @@ var MapBenchmark = new BenchmarkSuite('WeakMap', [1000], [ ...@@ -15,20 +16,17 @@ var MapBenchmark = new BenchmarkSuite('WeakMap', [1000], [
var wm; var wm;
var N = 10;
var keys = [];
for (var i = 0; i < N * 2; i++) { function WeakMapSetupBase() {
keys[i] = {}; SetupObjectKeys();
wm = new WeakMap;
} }
function WeakMapSetup() { function WeakMapSetup() {
wm = new WeakMap; WeakMapSetupBase();
for (var i = 0; i < N; i++) { WeakMapSet();
wm.set(keys[i], i);
}
} }
...@@ -38,8 +36,9 @@ function WeakMapTearDown() { ...@@ -38,8 +36,9 @@ function WeakMapTearDown() {
function WeakMapSet() { function WeakMapSet() {
WeakMapSetup(); for (var i = 0; i < N; i++) {
WeakMapTearDown(); wm.set(keys[i], i);
}
} }
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
var SetBenchmark = new BenchmarkSuite('WeakSet', [1000], [ 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, new Benchmark('Has', false, false, 0, WeakSetHas, WeakSetSetup,
WeakSetTearDown), WeakSetTearDown),
new Benchmark('Delete', false, false, 0, WeakSetDelete, WeakSetSetup, new Benchmark('Delete', false, false, 0, WeakSetDelete, WeakSetSetup,
...@@ -13,20 +14,17 @@ var SetBenchmark = new BenchmarkSuite('WeakSet', [1000], [ ...@@ -13,20 +14,17 @@ var SetBenchmark = new BenchmarkSuite('WeakSet', [1000], [
var ws; var ws;
var N = 10;
var keys = [];
for (var i = 0; i < N * 2; i++) { function WeakSetSetupBase() {
keys[i] = {}; SetupObjectKeys();
ws = new WeakSet;
} }
function WeakSetSetup() { function WeakSetSetup() {
ws = new WeakSet; WeakSetSetupBase();
for (var i = 0; i < N; i++) { WeakSetAdd();
ws.add(keys[i]);
}
} }
...@@ -36,8 +34,9 @@ function WeakSetTearDown() { ...@@ -36,8 +34,9 @@ function WeakSetTearDown() {
function WeakSetAdd() { function WeakSetAdd() {
WeakSetSetup(); for (var i = 0; i < N; i++) {
WeakSetTearDown(); ws.add(keys[i]);
}
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment