And*_*rin 19 javascript maps object
我想要了解是否使用JS对象或地图,如果我需要在大型数据集(> 1000个对象)中按字符串键进行随机查找.
我写了一个简单的基准http://jsperf.com/javascript-objects-vs-map-performance,结果显示在Chrome(V8)中,对象的表现比你好大约2倍.但是,我检查了其他浏览器,结果则相反.为什么它们在各种浏览器/引擎中有所不同?
我还在Node.JS中编写了类似的测试,我看不到类似的结果(测试用例6比测试用例4要多得多):
var now = require("performance-now");
var mapKeyValue = new Map();
var mapStringKeyValue = new Map();
var objectKeyValue = {};
var n = 10000;
var testSamples = 100;
var firstRow = 0;
var firstRowString = firstRow + "";
var middleRow = Math.floor(n / 2);
var middleRowString = middleRow + "";
var lastRow = n - 1;
var lastRowString = lastRow + "";
var nonExist = n * 2;
var nonExistString = nonExist + "";
function makeid() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < 20; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
for (var i = 0; i < n; i++) {
var value = makeid();
mapKeyValue.set(i, value);
mapStringKeyValue.set(i + "", value);
objectKeyValue[i + ""] = value;
}
var t0, t1;
var averages = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (var j = 0; j < testSamples; j++) {
var k = 0;
t0 = now();
mapKeyValue.get(firstRow);
t1 = now();
averages[k++] += (t1 - t0);
t0 = now();
mapStringKeyValue.get(firstRowString);
t1 = now();
averages[k++] += (t1 - t0);
t0 = now();
objectKeyValue[firstRowString];
t1 = now();
averages[k++] += (t1 - t0);
t0 = now();
mapKeyValue.get(middleRow);
t1 = now();
averages[k++] += (t1 - t0);
t0 = now();
mapStringKeyValue.get(middleRowString);
t1 = now();
averages[k++] += (t1 - t0);
t0 = now();
objectKeyValue[middleRowString];
t1 = now();
averages[k++] += (t1 - t0);
t0 = now();
mapKeyValue.get(lastRow);
t1 = now();
averages[k++] += (t1 - t0);
t0 = now();
mapStringKeyValue.get(lastRowString);
t1 = now();
averages[k++] += (t1 - t0);
t0 = now();
objectKeyValue[lastRowString];
t1 = now();
averages[k++] += (t1 - t0);
t0 = now();
mapKeyValue.get(nonExist);
t1 = now();
averages[k++] += (t1 - t0);
t0 = now();
mapStringKeyValue.get(nonExistString);
t1 = now();
averages[k++] += (t1 - t0);
t0 = now();
objectKeyValue[nonExistString];
t1 = now();
averages[k++] += (t1 - t0);
}
console.log("Test samples number " + testSamples);
for (var i = 0; i < averages.length; i++) {
averages[i] /= testSamples;
console.log("Test case " + (i + 1) + " took in average " + (averages[i] * 1000000) + " ns");
}
Run Code Online (Sandbox Code Playgroud)
Test samples number 100
Test case 1 took in average 2050.269999999692 ns
Test case 2 took in average 751.2899999997202 ns
Test case 3 took in average 567.3000000004081 ns
Test case 4 took in average 727.2699999999688 ns
Test case 5 took in average 4760.029999999489 ns
Test case 6 took in average 1939.3400000004135 ns
Test case 7 took in average 673.549999999885 ns
Test case 8 took in average 689.3600000002564 ns
Test case 9 took in average 541.3700000001143 ns
Test case 10 took in average 1146.0599999999843 ns
Test case 11 took in average 3096.7699999998285 ns
Test case 12 took in average 644.7400000000058 ns
Run Code Online (Sandbox Code Playgroud)
如果您对如何改进基准测试并使其更准确,请告诉我.谢谢.
Two*_*The 22
我刚刚有一个类似的问题并写了一个测试用例,第一个答案与您的相似,但是我们都认为现代 JS 引擎非常有能力消除与函数结果无关的代码。
这意味着您的测试用例向您展示了误导性的结果,因为 JS 引擎能够完全删除您的测试用例,因此您测量了引擎运行空循环的速度。
我写了一个新的测试用例,确保浏览器没有机会消除代码,结果显示地图几乎是关联对象的两倍:https : //jsperf.com/map-vs-object- vs 冷冻
请注意,此测试不包括实际初始化 Map 对象的成本。实际上,因此对于小代码片段使用本地对象最有可能更快,而实际的 Maps 只有在您在全局上下文中存储大量数据的情况下才会更快。
有趣的是,浏览器意识到对象上没有写操作,因此忽略了它本来必须执行的所有更新检查。因此,冻结的性能实际上更慢,而人们期望它更快。
您最长的测试用例不到0.005毫秒.电脑正在吃早餐.您处于冷启动时间的微观波动将以相对百分比显着改变结果的区域.这使得这些数字意义不大.
我建议优化可读性和其他问题.让它工作,做对,然后快速.请记住,Map是新的,随着引擎的发展会越来越快.
以下是与微观基准,陷阱和改进方法相关的一些资源.