//********* BenchPress-v3.js ********** // // A set of benchmarks to measure the efficiency of language implementations. // Based in part on the Stanford Integer Benchmarks originally written by // John Hennesey, modified by Peter Nye, and further modified by members of // the Self group under David Ungar and Randy Smith. // // To be consistent with other languages, some benchmarks use 1-based indexing. // To support this, arrays are created with an extra element and the contents // of their zeroth entries are ignored. // // // John Maloney, August 1995 // //*************************************** /********** AbstractBenchmark **********/ function randInit() { this.seed = 74755; } function rand() { this.seed = (( this.seed * 1309) + 13849) & 0xffff; return this.seed; } function testRand() { this.randInit(); if ((this.rand() != 22896) || (this.rand() != 34761) || (this.rand() != 34014) || (this.rand() != 39231) || (this.rand() != 52540) || (this.rand() != 41445) || (this.rand() != 1546) || (this.rand() != 5947) || (this.rand() != 65224)) { this.error("Random number generator"); } } function unimplemented() { print(""); } function AbstractBenchmark_error(s) { print("Error in " + s); } function AbstractBenchmark() { this.error = AbstractBenchmark_error; this.rand = rand; this.randInit = randInit; this.run = unimplemented; this.seed = 0; } AbstractBenchmark.Vect = new Array(10000); /********** AbstractSortBenchmark **********/ function checkArray(a) { var lastIndex, i; /* Note: sort benchmarks use 1-based indexing */ lastIndex = a.length - 1; if ((a[1] != this.littlest) || (a[lastIndex] != this.biggest)) { this.error("Sort Benchmark: Array is not sorted"); return; } for (i = 2; i <= lastIndex; i++) { if (a[i - 1] > a[i]) { this.error("Sort Benchmark: Array is not sorted"); return; } } } function randomArray(arraySize) { var a; var i, val; this.randInit(); a = new Array(arraySize + 1); /* extra for 1-based indexing */ this.biggest = -10000; this.littlest = 10000; for (i = 1; i <= arraySize; i++) { val = this.rand(); a[i] = val; if (val > this.biggest) this.biggest = val; if (val < this.littlest) this.littlest = val; } return a; } function AbstractSortBenchmark() { this.biggest = 0; this.littlest = 0; this.randomArray = randomArray; this.checkArray = checkArray; } AbstractSortBenchmark.prototype = new AbstractBenchmark; /********** SieveBenchmark **********/ function sieve(flags, flagsSize) { var primeCount = 0; for (var i = 0; i <= flagsSize; i++) { flags[i] = true; } for (var i = 2; i <= flagsSize; i++) { if (flags[i]) { primeCount++; for (var k = i + i; k <= flagsSize; k = k + i) { flags[k] = false; /* k is not prime */ } } } return primeCount; } function SieveBenchmark_run() { if (sieve(this.flags, 8190) != 1027) this.error("SieveBenchmark"); } function SieveBenchmark() { this.flags = new Array(8191); this.run = SieveBenchmark_run; } SieveBenchmark.prototype = new AbstractBenchmark; /********** BounceBenchmark **********/ function Ball() { this.x = 0; this.y = 0; this.xVel = 0; this.yVel = 0; this.initializeFor = initializeFor; this.bounce = bounce; } function initializeFor(bm) { this.x = bm.rand() % 500; this.y = bm.rand() % 500; this.xVel = (bm.rand() % 300) - 150; this.yVel = (bm.rand() % 300) - 150; return this; } function bounce() { var xLimit = 500; var yLimit = 500; var bounced = false; this.x = this.x + this.xVel; this.y = this.y + this.yVel; if (this.x > xLimit) { this.x = xLimit; this.xVel = 0 - Math.abs(this.xVel); bounced = true; } if (this.x < 0) { this.x = 0; this.xVel = Math.abs(this.xVel); bounced = true; } if (this.y > yLimit) { this.y = yLimit; this.yVel = 0 - Math.abs(this.yVel); bounced = true; } if (this.y < 0) { this.y = 0; this.yVel = Math.abs(this.yVel); bounced = true; } return bounced; } function BounceBenchmark() { this.run = BounceBenchmark_run; } BounceBenchmark.prototype = new AbstractBenchmark; function BounceBenchmark_run() { var ballCount = 100; var balls; var bounces = 0; var i, j; this.randInit(); balls = new Array(ballCount); for (i = 0; i < ballCount; i++) { balls[i] = (new Ball()).initializeFor(this); } for (i = 0; i < 10; i++) { for (j = 0; j < ballCount; j++) { if (balls[j].bounce()) bounces++; } } if (bounces != 268) this.error("BounceBenchmark " + bounces); } /********** NestedForLoopBenchmark **********/ function NestedForLoopBenchmark_run() { var sum, i, j; sum = 0; for (i = 1000; i > 0; i--) { for (j = 100; j > 0; j--) { sum = sum + 1; } } if (sum != 100000) { this.error("NestedForLoopBenchmark"); } } function NestedForLoopBenchmark() { this.run = NestedForLoopBenchmark_run; } NestedForLoopBenchmark.prototype = new AbstractBenchmark; /********** NestedWhileLoopBenchmark **********/ function NestedWhileLoopBenchmark_run() { var sum, i, j; sum = 0; i = 1000; while (i > 0) { j = 100; while (j > 0) { sum = sum + 1; j--; } i--; } if (sum != 100000) { this.error("NestedWhileLoopBenchmark"); } } function NestedWhileLoopBenchmark() { this.run = NestedWhileLoopBenchmark_run; } NestedWhileLoopBenchmark.prototype = new AbstractBenchmark; /********** PermBenchmark **********/ function PermBenchmark() { this.count = 0; this.v = 0; this.run = PermBenchmark_run; this.permute = permute; this.swap = swap; } PermBenchmark.prototype = new AbstractBenchmark; function swap(i, j) { var tmp = this.v[i]; this.v[i] = this.v[j]; this.v[j] = tmp; } function permute(n) { var i; this.count++; if (n != 1) { this.permute(n - 1); for (i = n - 1; i > 0; i--) { this.swap(n, i); this.permute(n - 1); this.swap(n, i); } } } function PermBenchmark_run() { this.count = 0; this.v = new Array(8); /* extra for 1-based indexing */ this.permute(7); if (this.count != 8660) { this.error("PermBenchmark"); } } /********** QueensBenchmark **********/ function QueensBenchmark() { this.freeRows = null; this.freeMajs = null; this.freeMins = null; this.qrows = null; this.run = QueensBenchmark_run; this.placeQueen = placeQueen; this.doQueens = doQueens; } QueensBenchmark.prototype = new AbstractBenchmark; function placeQueen(col) { for (var row = 1; row <= 8; row++) { if (this.freeRows[row] && this.freeMajs[(col + row) - 1] && this.freeMins[(col - row) + 7]) { this.qrows[col] = row; this.freeRows[row] = false; this.freeMajs[(col + row) - 1] = false; this.freeMins[(col - row) + 7] = false; if (col == 8) return true; if (this.placeQueen(col + 1)) return true; this.freeRows[row] = true; this.freeMajs[(col + row) - 1] = true; this.freeMins[(col - row) + 7] = true; } } return false; } function doQueens() { var i; /* allocate extra element in each array for 1-based indexing */ this.freeRows = new Array(9); for (i = 8; i > 0; i--) { this.freeRows[i] = true; } this.freeMajs = new Array(16); for (i = 15; i > 0; i--) { this.freeMajs[i] = true; } this.freeMins = new Array(16); for (i = 15; i > 0; i--) { this.freeMins[i] = true; } this.qrows = new Array(9); for (i = 8; i > 0; i--) { this.qrows[i] = -1; } if (!this.placeQueen(1)) this.error("QueensBenchmark"); } function QueensBenchmark_run() { for (var i = 10; i > 0; i--) this.doQueens(); } /********** QuicksortBenchmark **********/ function QuicksortBenchmark() { this.run = QuicksortBenchmark_run; this.sort = sort; } QuicksortBenchmark.prototype = new AbstractSortBenchmark; function sort(a, l, r) { var i, j, pivot, temp; i = l; j = r; pivot = a[Math.floor((l + r) / 2)]; while (i <= j) { while (a[i] < pivot) i++; while (pivot < a[j]) j--; if (i <= j) { temp = a[i]; a[i] = a[j]; a[j] = temp; i++; j--; } } if (l < j) this.sort(a, l, j); if (i < r) this.sort(a, i, r); } function QuicksortBenchmark_run() { var v; v = this.randomArray(1000); this.sort(v, 1, 1000); this.checkArray(v); } /********** RecurseBenchmark **********/ function RecurseBenchmark() { this.run = RecurseBenchmark_run; this.recurse = recurse; } RecurseBenchmark.prototype = new AbstractBenchmark; function recurse(n) { if (n > 0) { this.recurse(n - 1); this.recurse(n - 1); } } function RecurseBenchmark_run() { this.recurse(14); } /********** BubbleSortBenchmark **********/ function bubbleSort(a) { var top, i, curr, next; top = a.length - 1; while (top > 1) { i = 1; while (i < top) { curr = a[i]; next = a[i + 1]; if (curr > next) { a[i] = next; a[i + 1] = curr; } i++; } top--; } } function BubbleSortBenchmark() { this.run = BubbleSortBenchmark_run; this.bubbleSort = bubbleSort; } BubbleSortBenchmark.prototype = new AbstractSortBenchmark; function BubbleSortBenchmark_run() { var a; a = this.randomArray(250); this.bubbleSort(a); this.checkArray(a); } /********** IncrementAllBenchmark **********/ function IncrementAllBenchmark() { this.run = IncrementAllBenchmark_run; } IncrementAllBenchmark.prototype = new AbstractBenchmark; function IncrementAllBenchmark_run() { var oldVal, i; oldVal = AbstractBenchmark.Vect[1]; for (i = AbstractBenchmark.Vect.length - 1; i >= 0; i--) { AbstractBenchmark.Vect[i] = AbstractBenchmark.Vect[i] + 1; } if (AbstractBenchmark.Vect[1] != (oldVal + 1)) { this.error("IncrementAllBenchmark"); } } /********** MMIntBenchmark **********/ function IntegerMatrix(rowCount, columnCount) { this.rows = rowCount; this.columns = columnCount; this.data = new Array(rowCount); for (var i = rowCount - 1; i >= 0; i--) { this.data[i] = new Array(columnCount); } this.fillFor = IntegerMatrix_fillFor; this.dotProduct = IntegerMatrix_dotProduct; this.multiplyBy = IntegerMatrix_multiplyBy; } function IntegerMatrix_fillFor(bm) { for (var i = this.rows - 1; i >= 0; i--) { for (var j = this.columns - 1; j >= 0; j--) { this.data[i][j] = (bm.rand() % 120) - 60; } } } function IntegerMatrix_dotProduct(row, rowSize, otherM, columnIndex) { var sum = 0; for (var i = 0; i < rowSize; i++) { sum = sum + (row[i] * otherM.data[i][columnIndex]); } return sum; } function IntegerMatrix_multiplyBy(m) { var rowCount = this.rows; var columnCount = m.columns; result = new IntegerMatrix(rowCount, columnCount); for (var i = 0; i < rowCount; i++) { for (var j = 0; j < columnCount; j++) { result.data[i][j] = this.dotProduct(this.data[i], this.columns, m, j); } } return result; } function MMIntBenchmark() { this.run = MMIntBenchmark_run; } MMIntBenchmark.prototype = new AbstractBenchmark; function MMIntBenchmark_run() { var ma, mb, mr; ma = new IntegerMatrix(10, 10); mb = new IntegerMatrix(10, 10); ma.fillFor(this); mb.fillFor(this); mr = ma.multiplyBy(mb); } /********** MMFloatBenchmark **********/ function FloatMatrix(rowCount, columnCount) { this.rows = rowCount; this.columns = columnCount; this.data = new Array(rowCount); for (var i = rowCount - 1; i >= 0; i--) { this.data[i] = new Array(columnCount); } this.fillFor = FloatMatrix_fillFor; this.dotProduct = FloatMatrix_dotProduct; this.multiplyBy = FloatMatrix_multiplyBy; } function FloatMatrix_fillFor(bm) { for (var i = this.rows - 1; i >= 0; i--) { for (var j = this.columns - 1; j >= 0; j--) { this.data[i][j] = (1.0 * ((bm.rand() % 120) - 60)); } } } function FloatMatrix_dotProduct(row, rowSize, otherM, columnIndex) { var sum = 0; for (var i = 0; i < rowSize; i++) { sum = sum + (row[i] * otherM.data[i][columnIndex]); } return sum; } function FloatMatrix_multiplyBy(m) { var rowCount = this.rows; var columnCount = m.columns; result = new FloatMatrix(rowCount, columnCount); for (var i = 0; i < rowCount; i++) { for (var j = 0; j < columnCount; j++) { result.data[i][j] = this.dotProduct(this.data[i], this.columns, m, j); } } return result; } function MMFloatBenchmark() { this.run = MMFloatBenchmark_run; } MMFloatBenchmark.prototype = new AbstractBenchmark; function MMFloatBenchmark_run() { var ma, mb, mr; ma = new FloatMatrix(10, 10); mb = new FloatMatrix(10, 10); ma.fillFor(this); mb.fillFor(this); mr = ma.multiplyBy(mb); } /********** AtAllPutBenchmark **********/ function AtAllPutBenchmark() { this.run = AtAllPutBenchmark_run; } AtAllPutBenchmark.prototype = new AbstractBenchmark; function AtAllPutBenchmark_run() { var i; for (i = AbstractBenchmark.Vect.length - 1; i >= 0; i--) { AbstractBenchmark.Vect[i] = 5; } if (AbstractBenchmark.Vect[1] != 5) this.error("AtAllPutBenchmark"); } /********** StorageBenchmark **********/ function StorageBenchmark() { this.count = 0; this.run = StorageBenchmark_run; this.buildTreeDepth = buildTreeDepth; } StorageBenchmark.prototype = new AbstractBenchmark; function buildTreeDepth(depth) { this.count++; if (depth == 1) { return new Array(Math.floor((this.rand() % 10) + 1)); } else { newNode = new Array(4); newNode[0] = this.buildTreeDepth(depth - 1); newNode[1] = this.buildTreeDepth(depth - 1); newNode[2] = this.buildTreeDepth(depth - 1); newNode[3] = this.buildTreeDepth(depth - 1); return newNode; } } function StorageBenchmark_run() { this.randInit(); this.count = 0; this.buildTreeDepth(6); if (this.count != 1365) { this.error("StorageBenchmark"); } } /********** SumAllBenchmark **********/ function SumAllBenchmark() { this.run = SumAllBenchmark_run; } SumAllBenchmark.prototype = new AbstractBenchmark; function SumAllBenchmark_run() { var elementValue, sum, i; elementValue = AbstractBenchmark.Vect[1]; sum = 0; for (i = AbstractBenchmark.Vect.length - 1; i >= 0; i--) { sum = sum + AbstractBenchmark.Vect[i]; } if (sum != (AbstractBenchmark.Vect.length * elementValue)) { this.error("SumAllBenchmark"); } } /********** SumFromToBenchmark **********/ function SumFromToBenchmark() { this.run = SumFromToBenchmark_run; this.sumFromTo = sumFromTo; } SumFromToBenchmark.prototype = new AbstractBenchmark; function sumFromTo(start, end) { var sum = 0; for (var i = start; i <= end; i++) { sum = sum + i; } return sum; } function SumFromToBenchmark_run() { for (var i = 9; i > 0; i--) this.sumFromTo(1, 10000); if (this.sumFromTo(1, 10000) != 50005000) { this.error("SumFromToBenchmark"); } } /********** TakBenchmark **********/ function TakBenchmark() { this.run = TakBenchmark_run; this.tak = tak; } TakBenchmark.prototype = new AbstractBenchmark; function tak(x, y, z) { if (y < x) { return this.tak( this.tak(x - 1, y, z), this.tak(y - 1, z, x), this.tak(z - 1, x, y)); } else { return z; } } function TakBenchmark_run() { var r = this.tak(18, 12, 6); if (r != 7) this.error("TakBenchmark"); } /********** TaklBenchmark **********/ function ListElement(n) { this.val = n; this.next = null; } function listn(n) { if (n == 0) { return null; } else { var newEl = new ListElement(n); newEl.next = listn(n - 1); return newEl; } } function takl_length(l) { if (l.next == null) { return 1; } else { return 1 + takl_length(l.next); } } function shorterp(x, y) { var xTail, yTail; xTail = x; yTail = y; while (yTail != null) { if (xTail == null) return true; xTail = xTail.next; yTail = yTail.next; } return false; } function takl(x, y, z) { if (shorterp(y, x)) { return takl( takl(x.next, y, z), takl(y.next, z, x), takl(z.next, x, y)); } else { return z; } } function TaklBenchmark_run() { r = takl(listn(18), listn(12), listn(6)); if (takl_length(r) != 7) { this.error("TaklBenchmark"); } } function TaklBenchmark() { this.run = TaklBenchmark_run; } TaklBenchmark.prototype = new AbstractBenchmark; /********** TowersBenchmark **********/ function TowersDisk(size) { this.diskSize = size; this.next = null; } function TowersBenchmark() { this.piles = new Array(4); this.movesdone = 0; this.push = push; this.pop = pop; this.moveTopDisk = moveTopDisk; this.buildTowerAt = buildTowerAt; this.emptyPileAt = emptyPileAt; this.tower = tower; this.run = TowersBenchmark_run; } TowersBenchmark.prototype = new AbstractBenchmark; function push(d, pileIndex) { var top = this.piles[pileIndex]; if ((top != null) && (d.diskSize >= top.diskSize)) { this.error("TowersBenchmark: cannot put a big disk on a smaller one"); } d.next = top; this.piles[pileIndex] = d; } function pop(pileIndex) { var top = this.piles[pileIndex]; if (top == null) { this.error("TowersBenchmark: attempting to remove a disk from an empty pile"); } this.piles[pileIndex] = top.next; top.next = null; return top; } function moveTopDisk(fromPileIndex, toPileIndex) { this.push(this.pop(fromPileIndex), toPileIndex); this.movesdone++; } function buildTowerAt(pileIndex, levels) { for (var i = levels; i > 0; i--) { this.push(new TowersDisk(i), pileIndex); } } function emptyPileAt(pileIndex) { this.piles[pileIndex] = null; } function tower(i, j, k) { if (k == 1) { this.moveTopDisk(i, j); } else { var other = (6 - i) - j; this.tower(i, other, k - 1); this.moveTopDisk(i, j); this.tower(other, j, k - 1); } } function TowersBenchmark_run() { this.emptyPileAt(1); this.emptyPileAt(2); this.emptyPileAt(3); this.buildTowerAt(1, 14); this.movesdone = 0; this.tower(1, 2, 14); if (this.movesdone != 16383) this.error("TowersBenchmark"); } /********** TreeSortBenchmark **********/ function TreeNode(n) { this.left = null; this.right = null; this.val = n; this.checkTree = checkTree; this.insert = insert; } function checkTree() { return ((this.left == null) || ((this.left.val < this.val) && this.left.checkTree())) && ((this.right == null) || ((this.right.val >= this.val) && this.right.checkTree())); } function insert(n) { if (n < this.val) { if (this.left == null) { this.left = new TreeNode(n); } else { this.left.insert(n); } } else { if (this.right == null) { this.right = new TreeNode(n); } else { this.right.insert(n); } } } function TreeSortBenchmark() { this.run = TreeSortBenchmark_run; } TreeSortBenchmark.prototype = new AbstractSortBenchmark; function TreeSortBenchmark_run() { var vSize = 1000; var v = this.randomArray(vSize); var tree = new TreeNode(v[1]); for (var i = 2; i <= vSize; i++) { tree.insert(v[i]); } if (!tree.checkTree()) { this.error("TreeSortBenchmark"); } } /********** BenchmarkRunner **********/ function print2col(col1, col2) { while (col1.length < 30) col1 += " "; print(col1 + col2); } function timeit(name, benchmark) { benchmark.run(); var startTime = new Date(); benchmark.run(); var elapsedTime = (new Date()).getTime() - startTime.getTime(); print2col(name, elapsedTime); return elapsedTime; } function BenchmarkRunner() { var total = 0; print("Benchpress(v3) in JavaScript..."); print2col("benchmark", "time (ms)"); total = total + timeit("AtAllPutBenchmark", new AtAllPutBenchmark()); total += timeit("BounceBenchmark", new BounceBenchmark()); total += timeit("BubbleSortBenchmark", new BubbleSortBenchmark()); total += timeit("IncrementAllBenchmark", new IncrementAllBenchmark()); total += timeit("MMIntBenchmark", new MMIntBenchmark()); total += timeit("MMFloatBenchmark", new MMFloatBenchmark()); total += timeit("NestedForLoopBenchmark", new NestedForLoopBenchmark()); total += timeit("NestedWhileLoopBenchmark", new NestedWhileLoopBenchmark()); total += timeit("PermBenchmark", new PermBenchmark()); total += timeit("QueensBenchmark", new QueensBenchmark()); total += timeit("QuicksortBenchmark", new QuicksortBenchmark()); total += timeit("RecurseBenchmark", new RecurseBenchmark()); total += timeit("SieveBenchmark", new SieveBenchmark()); total += timeit("StorageBenchmark", new StorageBenchmark()); total += timeit("SumAllBenchmark", new SumAllBenchmark()); total += timeit("SumFromToBenchmark", new SumFromToBenchmark()); total += timeit("TakBenchmark", new TakBenchmark()); total += timeit("TaklBenchmark", new TaklBenchmark()); total += timeit("TowersBenchmark", new TowersBenchmark()); total += timeit("TreeSortBenchmark", new TreeSortBenchmark()); print2col("total", total); } BenchmarkRunner();