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
Performance comparison between the knockout mapping plugins ko.viewmodel and ko.mapping.
With custom mapper
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.0/knockout-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.3.3/knockout.mapping.js"></script>
<script src="http://coderenaissance.github.com/knockout.viewmodel/knockout.viewmodel.min.js"></script>
<SCRIPT LANGUAGE="JavaScript">
var order = {
items:[
{
string:"item3",
number:3,
anotherObject:{
items:[{id:4, name:"item4"},{id:5, name:"Item5"}]
}
},
{
string:"Item0",
number:0,
anotherObject: {
items:[{id:1, name:"Item1"},{id:2, name:"Item2"}]
}
}
]
};
var mapper = {
".items":{t:"items",map:[{f:"*",t:"*"}]},
".items.anotherObject":{t:"items.anotherObject",map:[{f:"*",t:"*"}]},
".items.anotherObject.items":{t:"items.anotherObject.items",map:[{f:"*",t:"*"}]},
};
var t = 0;
var parentPathKey = "*";
print = function(parentPath,t,obj,toObj,indexArr){
if( obj ){
for(var i in obj){
//var tabs = ""; for(var j=t;--j;){ tabs+="\t";}s+=tabs;s+=i;
if( obj[i] && i !== parentPathKey ){
// console.log(parentPath+"."+i);
var currObject = obj[i];
// check for mapping
var mapping = mapper[parentPath+"."+i];
if( currObject instanceof Array ){
var constructedObject = toObj;
if( mapping ){
// if t then create or get t, else i becomes t should be an array
if( mapping.t ){
constructedObject = createOrGetObjectArr( mapping.t, toObj, indexArr);
}else{
constructedObject = createOrGetObjectArr( i, toObj , indexArr);
}
}
var currObjectArrLen = currObject.length
for(var k = 0; k < currObjectArrLen; k++){
var currObjectInArr = currObject[k];
if( !currObjectInArr[parentPathKey] && k !== parentPathKey){
currObjectInArr[parentPathKey] = obj;
}
//s+="\n"+tabs+"[";
if( mapping ){
var constructedObjectItem = constructedObject[constructedObject.length] = {};
if(mapping.map){
var mappingMapLen = mapping.map.length;
// iterate through mappings
for(var itr = 0; itr < mappingMapLen;itr++ ){
var nestedMapping = mapping.map[itr];
// the array could of objects or direct values
// m.f = * then copy all the obj to m.t object
if( nestedMapping.f === "*" ){
// clone
copyAllproperties(constructedObjectItem, currObjectInArr);//TODO: check if nested paths
}else{
// m.f = index then and set it to map.t//TODO: handle index
// m.f = has parent, then iterate and set to m.t object
if( nestedMapping.f ){
// get value
if( nestedMapping.t ){
createAndSet(nestedMapping.t,constructedObjectItem
,nestedMapping.f,currObjectInArr);
}
}
}
}
}
}
indexArr.push(constructedObject.length - 1);
if( i !== parentPathKey ){
print(parentPath+"."+i, t+1, currObjectInArr, toObj, indexArr);
}
indexArr.pop();
delete currObjectInArr[parentPathKey];
//s+=tabs+"]";
}
}else if( currObject instanceof Object ){
if( currObject[parentPathKey] && i !== parentPathKey){
currObject[parentPathKey] = obj;
}
//s+="\n"+tabs+"{";
var constructedObject = toObj;
if( mapping ){
// if t then create or get t, else i becomes t
if( mapping.t ){
contructedObject = createOrGetObject( mapping.t, toObj,false, indexArr );
}else{
contructedObject = createOrGetObject( i, toObj, false, indexArr );
}
var mappingMapLen = mapping.map.length;
// iterate through mappings
for(var itr = 0; itr < mappingMapLen;itr++ ){
var nestedMapping = mapping.map[itr];
// the array could of objects or direct values
// m.f = * then copy all the obj to m.t object
if( nestedMapping.f === "*" ){
// clone
copyAllproperties( contructedObject, currObject );//TODO: check if nested paths
}else{
// m.f = index then and set it to map.t//TODO: handle index
// m.f = has parent, then iterate and set to m.t object
if( nestedMapping.f ){
if( nestedMapping.t ){
createAndSet(nestedMapping.t, contructedObject
,nestedMapping.f, currObject);
}
}
}
}
}
if( i !== parentPathKey ){
print( parentPath+"."+i, t+1, currObject, toObj , indexArr);
}
delete currObject[parentPathKey];
//s+=tabs+"}";
}else{
if( mapping ){
if( mapping === "*"){
toObj[i] = currObject;
}else{
if( mapping ){
// m.f or i, set it to m.t
if( mapping.f ){
if( mapping.t ){//TODO: the constructedObject is just a primitive type
createAndSet(mapping.t,toObj,i,toObj);
}else{
createAndSet(i,toObj,i,toObj);
}
}
}
}
}
}
}
//s+="\n";
}
}
}
function createAndSet(toPath, to, fromPath, from){
var splits = toPath.split(".");
var constructed = to;
var len = splits.length;
for( var i = 0; i < len - 1; i++){
var currSplit = splits[ i ];
constructed = constructed[ currSplit ] = constructed[ currSplit ] || {};
}
constructed[ splits[ len - 1 ] ] = getFromValue( fromPath, from );
}
function createOrGetObjectArr( path, o, indexArr){
return createOrGetObject(path, o, true, indexArr);
}
function createOrGetObject( path, o, isArray, indexArr){
// TODO: incorporate, arrays
var splits = path.split(".");
var constructed = o;
var len = splits.length;
for( var i = 0; i < len; i++){
var currSplit = splits[ i ];
var tmp = constructed[ currSplit ] = constructed[ currSplit ] || ( isArray ? []:{});
if( tmp instanceof Array && i+1 < len ){
constructed = tmp[ tmp.length - 1 ];
}else{
constructed = tmp;
}
}
return constructed;
}
function copyAllproperties(to, from){
for(var k in from) {
if(k !== parentPathKey){
var currObject = from[k];
if( !( currObject instanceof Array
||currObject instanceof Object ) ){//TODO: re-iterate on this functionality
to[k] = from[k]
}
}
};
}
function getFromValue(path, obj){
// check if parent exists, parent should invoke a parent call.
// TODO: throw an error if the property does not exist
var splits = path.split(".");
var len = splits.length;
if( len > 1 ){
for( var i = 0; i < len; i++){
var curSplit = splits[i];
if(curSplit === "parent"){
obj = obj[parentPathKey];
}else{
if(obj[curSplit]){
obj = obj[curSplit];
}
}
}
}
return obj;
}
</script>
var numberOfArrayRecords = 100,
viewmodel = null,
model = {
items:[]
};
for(var x = 0; x < numberOfArrayRecords; x++){
model.items.push({
string:"Test",
number:4,
anotherObject:{
items:[{id:4, name:"Test"},{id:7, name:"Test2"}]
}
});
}
Ready to run.
Test | Ops/sec | |
---|---|---|
ko.mapping |
| ready |
ko.viewmodel |
| ready |
custom |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.