ko.viewmodel vs ko.mapping vs knockout.wrap vs knockout.mapper (v30)

Revision 30 of this benchmark created on


Description

Performance comparison between the knockout mapping plugins ko.viewmodel and ko.mapping and knockout.wrap and knockout.mapper

Adds my custom mapper.

Preparation HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<script src="http://coderenaissance.github.com/knockout.viewmodel/knockout.viewmodel.min.js"></script>
<script src="https://rawgit.com/arj03/knockout.wrap/master/knockout.wrap.js"></script>
<script src="https://rawgit.com/lucaslorentz/knockout.mapper/master/knockout.mapper.js"></script>
<script>
ko.mapper2 = {
        isFunction: function(functionToCheck) {
             var getType = {};
            return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
        },
        fromJS: function (raw, mappingOptions, target) {
            var self = this;
            mappingOptions = mappingOptions || {};
            target = target || {};
            for (var property in raw) {
    
                if (raw[property] instanceof Array) {
                    var createItem = function(options) { return self.mapProperty(options); };
    
                    if (mappingOptions[property]) {
                        createItem = mappingOptions[property].create;
                    }
    
                    var arrayToSet = raw[property].map(function(item) {
                        return createItem({ data: item, property: property, mapping: mappingOptions });
                    });
                    
                    if (this.isFunction(target[property])) {
                        target[property](arrayToSet);
                    } else {
                        target[property] = ko.observableArray(arrayToSet);
                    }
    
                } else {
                    this.setProperty(target, property, {data: raw[property], property: property, mapping: mappingOptions });
                }
            }
            return target;
        },
        setProperty: function (target, property, options) {
            if (options.mapping[options.property]) {
                target[property] = options.mapping[options.property].create({ data: options.data });
                return;
            }
    
            if (options.data != null && typeof options.data === 'object') {
                var obj = target[property] || {};
                target[property] = this.fromJS(options.data, options.mapping, obj);
            } else {
                if (this.isFunction(target[property])) {
                    target[property](options.data);
                } else {
                    target[property] = ko.observable(options.data);
                }
            }
        },
        mapProperty: function (options) {
            if (options.mapping[options.property]) {
                return options.mapping[options.property].create({data: options.data});
            }
    
            if (options.data != null && typeof options.data === 'object') {
                return this.fromJS(options.data, options.mapping, {});
            } else {
                return ko.observable(options.data);
            }
    
        }
    };
</script>

Setup

var numberOfArrayRecords = 1000,
      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"
          }]
        }
      });
    
    }

Test runner

Ready to run.

Testing in
TestOps/sec
ko.mapping
viewmodel = ko.mapping.fromJS(model);
ready
ko.viewmodel
viewmodel = ko.viewmodel.fromModel(model);
ready
knockout.wrap
viewmodel = ko.wrap.fromJS(model);
ready
knockout.mapper
viewmodel = ko.mapper.fromJS(model);
ready
custom mapper
viewmodel = ko.mapper2.fromJS(model);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.