jsPerf.app is an online JavaScript performance benchmark test runner & jsperf.com mirror. It is a complete rewrite in homage to the once excellent jsperf.com now with hopefully a more modern & maintainable codebase.
jsperf.com URLs are mirrored at the same path, e.g:
https://jsperf.com/negative-modulo/2
Can be accessed at:
https://jsperf.app/negative-modulo/2
Compare 2 methods to get values in complex objects by key name, using different sources.
Method 1: Loop object recursive
Method 2: Search in JSON string with a lexer
Source 1: Object
Source 2: JSON string
JSON.parse and JSON.stringify are slow methods, so in some cases it's faster to search in the JSON string with a simple lexer. In this case the resulting string is probably smaller than the complete JSON string, so call of JSON.parse only for the result is faster.
(function (global) {
var rsimple = /^(?:(?:-?(?=[1-9]|0(?!\d))\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|(?:true|false|null)|(?:"(?:[^"\\\\]*|\\\\["\\\\bfnrt\/]|\\\\u[0-9a-f]{4})*"))\s*:?\s*/,
ropen = /^(?:\[|\{)\s*/,
rnext = /^,\s*/,
rclose = /^(?:\]|\})\s*/;
function escapeRegexp(string) {
return (string)
.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, "\\$1");
}
function lexer(json) {
var part = "";
repl = function (all) {
part += all;
return "";
},
i = 0;
while (json.length && i >= 0) {
if (rsimple.test(json)) {
json = json.replace(rsimple, repl);
}
else if (ropen.test(json)) {
json = json.replace(ropen, repl);
i++;
}
else if (rclose.test(json) && i > 0) {
json = json.replace(rclose, repl);
i--;
}
else if (rnext.test(json) && i > 0) {
json = json.replace(rnext, repl);
}
else {
i = -1;
}
}
return part;
}
global.findInJSON = function (keyname, json, g) {
var rfind = new RegExp("\"" + escapeRegexp(keyname) + "\"\\s*:\\s*([\\s\\S]+)$", ""),
results = [];
function handle(json) {
var found = rfind.exec(json);
if (found) {
results.push(lexer(found[1]));
// Search global
if (g) {
handle(found[1]);
}
}
}
// Convert to JSON and start search
handle(json);
// Get results array from JSON string
return "[" + results.join(",") + "]";
};
global.findInObject = function (keyname, object, g) {
var results = [];
function handle(object) {
for (var key in object) {
if (key === keyname) {
results.push(object[key]);
if (!g) {
return;
}
}
if (typeof object[key] === "object") {
handle(object[key]);
}
}
}
handle(object);
return results;
};
}(this));
var testDataObject = {
"module": [{
"exports": "Class",
"module": "class",
"author": "Evan Vosberg",
"copyright": "© 2012 by Evan Vosberg",
"info": "http://github.com/evanvosberg",
"license": "Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.",
"class": [{
"name": "Class",
"shortdesc": "Create a class object.",
"category": ["Utilities", "Example"],
"signature": [{
"since": "1.0",
"param": [{
"type": ["String"],
"name": "classname",
"shortdesc": "A scope name in dot natation to define the class global.",
"optional": true
}, {
"type": ["Array", "Class"],
"name": "superclass",
"shortdesc": "A class object or an array of class objects.",
"optional": true
}, {
"type": ["Object"],
"name": "properties",
"shortdesc": "An object of methods and properties for the speciefied class.",
"option": [{
"type": ["Function"],
"name": "constructor",
"shortdesc": "The class constructer which will be called on instantiate.",
"since": "1.0",
"optional": true
}]
}],
"return": ["Class"],
"title": "Class([classname] [, superclass], properties)"
}],
"description": {
"longdesc": "<p>Javascript doesn't have a Class system like Java, <code>Class()</code> simulates this.</p><h4>Setup a constuctor for the class</h4><p>If a method of the properties named <em>constructor</em>, it will be interpreted as the constructor method oncalling a new instance of the class. Also all constuctors of superclasses will be exectuted on calling anew instance of the class.</p><h4>Call overwritten inherited methods</h4><p>If a class overwrites a method of a superclass with an own method, you can call the original method insideof the new method in the following way <code>this._super(arg1, argN)</code> or <code>this._superApply(args)</code>.</p>"
},
"method": [{
"name": "_proxy",
"shortdesc": "This method is most useful for attaching event handlers to an element where the context is the current class instance.",
"signature": [{
"since": "1.0",
"param": [{
"type": ["String", "Function"],
"name": "function",
"shortdesc": "The function or the name of a function (from current instance) whose context will be changed to the current instance."
}],
"return": ["Function"],
"title": "_proxy(function)"
}],
"description": {
"longdesc-syntax": "md",
"longdesc": "<p>Additionally, <code>._proxy()</code> makes sure that even if you bind <code>jQuery.on()</code> the function with returned from <code>._proxy()</code> it will still unbind <code>jQuery.off()</code> the correct function, if passed the original.</p>"
}
}]
}],
"function": [{
"name": "Class.isClass",
"shortdesc": "Determine whether the given argument is an class object.",
"category": ["Utilities"],
"signature": [{
"since": "1.0",
"param": [{
"type": ["Function"],
"name": "function",
"shortdesc": "Object to test whether or not it is a function."
}, {
"type": ["Boolean"],
"name": "strict",
"shortdesc": "A boolean indication whether the class was created with Class().",
"optional": true
}],
"return": ["Boolean"],
"title": "Class.isClass(function [, strict])"
}],
"description": {
"longdesc-syntax": "md",
"longdesc": "<p>This method determines whether the argument is an class object.</p>"
}
}]
}]
};
var testDataJSON = JSON.stringify(testDataObject);
Ready to run.
Test | Ops/sec | |
---|---|---|
Loop source: Object |
| ready |
Loop source: JSON (needs to convert input) |
| ready |
Lexer source: Object (needs to convert input and output) |
| ready |
Lexer source: JSON (needs to convert output) |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.