Knockout benchmark

by homer2

HTML

<script src="https://raw.github.com/SteveSanderson/knockout/master/build/output/knockout-latest.debug.js"></script>
<input id="data" type="text" value='{"LastActualMonth":"\/Date(1330581600000)\/","ResourceCategoryCosts":[{"Name":"Awards","MonthAmounts":[{"DateKey":"\/Date(1325397600000)\/","Amount":10000},{"DateKey":"\/Date(1328076000000)\/","Amount":10000},{"DateKey":"\/Date(1330581600000)\/","Amount":10000},{"DateKey":"\/Date(1333256400000)\/","Amount":10000},{"DateKey":"\/Date(1335848400000)\/","Amount":10000},{"DateKey":"\/Date(1338526800000)\/","Amount":10000},{"DateKey":"\/Date(1341118800000)\/","Amount":10000},{"DateKey":"\/Date(1343797200000)\/","Amount":10000},{"DateKey":"\/Date(1346475600000)\/","Amount":10000},{"DateKey":"\/Date(1349067600000)\/","Amount":10000},{"DateKey":"\/Date(1351746000000)\/","Amount":10000},{"DateKey":"\/Date(1354341600000)\/","Amount":10000}]},{"Name":"Catering","MonthAmounts":[{"DateKey":"\/Date(1325397600000)\/","Amount":10000},{"DateKey":"\/Date(1328076000000)\/","Amount":10000},{"DateKey":"\/Date(1330581600000)\/","Amount":10000},{"DateKey":"\/Date(1333256400000)\/","Amount":10000},{"DateKey":"\/Date(1335848400000)\/","Amount":10000},{"DateKey":"\/Date(1338526800000)\/","Amount":10000},{"DateKey":"\/Date(1341118800000)\/","Amount":10000},{"DateKey":"\/Date(1343797200000)\/","Amount":10000},{"DateKey":"\/Date(1346475600000)\/","Amount":10000},{"DateKey":"\/Date(1349067600000)\/","Amount":10000},{"DateKey":"\/Date(1351746000000)\/","Amount":10000},{"DateKey":"\/Date(1354341600000)\/","Amount":10000}]}]}' />
<div data-bind="text: ko.toJSON($root)"></div>

CSS

.header {
    font-size: 16px;
    font-family: sans-serif;
    font-weight: bold;
    margin-bottom: 20px;
}

JavaScript

function ConvertToDate(jsonDateString) {
    var re = /-?\d+/;
    var m = re.exec(jsonDateString);
    return new Date(parseInt(m[0]));
}
function MonthAmount(amount, dateKey) {
    var self = this;
    self.amount = ko.observable(amount);
    self.dateKey = ConvertToDate(dateKey);
    self.monthIndex = self.dateKey.getMonth();

    self.percentFormat = ko.computed({
        read: function () {
            return (self.amount() * 100).toFixed(2) + "%";
        },
        write: function (value) {
            self.amount(parseFloat(value.replace(/[^\d.-]/g, '')) / 100);
        },
        owner: this
    });
}

function ResourceCategory(name, monthAmounts) {
    var self = this;
    self.name = name;

    self.monthAmounts = ko.utils.arrayMap(monthAmounts, function (monthAmount) {
        return new MonthAmount(monthAmount.Amount, monthAmount.DateKey);
    });

    self.totalAmount = ko.computed(function () {
        var sum = 0;
        for (var i = 0; i < self.monthAmounts.length; i++) {
            sum += parseFloat(self.monthAmounts[i].amount());
        }
        return sum;
    });

    self.averageAmount = ko.computed(function () {
        return self.totalAmount() / self.monthAmounts.length;
    });

}

function OverheadViewModel(json) {
    var self = this;
    var today = new Date();
    self.currentMonth = new Date(today.getFullYear(), today.getMonth(), 1);
    self.currentMonthIndex = today.getMonth();
    self.lastActualDate = ConvertToDate(json.LastActualDate); 
    
    self.resourceCategories = ko.utils.arrayMap(json.ResourceCategoryCosts, function (resourceCategoryCost) {
        return new ResourceCategory(resourceCategoryCost.Name, resourceCategoryCost.MonthAmounts);
    });

    /*
    self.columnTotals = {};
    self.columnTotals.costCenterRateMonthTotals = new Array();
    self.columnTotals.resourceCategoriesMonthTotals = new Array();
    self.columnTotals.overheadBilledMonthTotals = new Array();
    self.columnTotals.varianceMonthTotals =...