|
30 | 30 | /** Used to assign each benchmark an incrimented id */ |
31 | 31 | var counter = 0; |
32 | 32 |
|
| 33 | + /** Used to make every compiled test unique */ |
| 34 | + var uidCounter = 0; |
| 35 | + |
33 | 36 | /** Used to detect primitive types */ |
34 | 37 | var rePrimitive = /^(?:boolean|number|string|undefined)$/; |
35 | 38 |
|
|
1571 | 1574 | // lazy define for hi-res timers |
1572 | 1575 | clock = function(clone) { |
1573 | 1576 | var deferred; |
| 1577 | + templateData.uid = uid + uidCounter++; |
| 1578 | + |
1574 | 1579 | if (clone instanceof Deferred) { |
1575 | 1580 | deferred = clone; |
1576 | 1581 | clone = deferred.benchmark; |
1577 | 1582 | } |
1578 | | - |
1579 | 1583 | var bench = clone._original, |
1580 | 1584 | fn = bench.fn, |
1581 | 1585 | fnArg = deferred ? getFirstArgument(fn) || 'deferred' : '', |
|
1588 | 1592 | 'teardown': getSource(bench.teardown, interpolate('m#.teardown()')) |
1589 | 1593 | }); |
1590 | 1594 |
|
| 1595 | + // use API of chosen timer |
| 1596 | + if (timer.unit == 'ns') { |
| 1597 | + if (timer.ns.nanoTime) { |
| 1598 | + _.extend(templateData, { |
| 1599 | + 'begin': interpolate('s#=n#.nanoTime()'), |
| 1600 | + 'end': interpolate('r#=(n#.nanoTime()-s#)/1e9') |
| 1601 | + }); |
| 1602 | + } else { |
| 1603 | + _.extend(templateData, { |
| 1604 | + 'begin': interpolate('s#=n#()'), |
| 1605 | + 'end': interpolate('r#=n#(s#);r#=r#[0]+(r#[1]/1e9)') |
| 1606 | + }); |
| 1607 | + } |
| 1608 | + } |
| 1609 | + else if (timer.unit == 'us') { |
| 1610 | + if (timer.ns.stop) { |
| 1611 | + _.extend(templateData, { |
| 1612 | + 'begin': interpolate('s#=n#.start()'), |
| 1613 | + 'end': interpolate('r#=n#.microseconds()/1e6') |
| 1614 | + }); |
| 1615 | + } else if (perfName) { |
| 1616 | + _.extend(templateData, { |
| 1617 | + 'begin': interpolate('s#=n#.' + perfName + '()'), |
| 1618 | + 'end': interpolate('r#=(n#.' + perfName + '()-s#)/1e3') |
| 1619 | + }); |
| 1620 | + } else { |
| 1621 | + _.extend(templateData, { |
| 1622 | + 'begin': interpolate('s#=n#()'), |
| 1623 | + 'end': interpolate('r#=(n#()-s#)/1e6') |
| 1624 | + }); |
| 1625 | + } |
| 1626 | + } |
| 1627 | + |
1591 | 1628 | var count = bench.count = clone.count, |
1592 | 1629 | decompilable = support.decompilation || stringable, |
1593 | 1630 | id = bench.id, |
|
1609 | 1646 | ns = timer.ns = new applet.Packages.nano; |
1610 | 1647 | } |
1611 | 1648 | } |
| 1649 | + // define `timer` methods |
| 1650 | + timer.start = createFunction( |
| 1651 | + interpolate('o#'), |
| 1652 | + interpolate('var n#=this.ns,${begin};o#.elapsed=0;o#.timeStamp=s#') |
| 1653 | + ); |
| 1654 | + |
| 1655 | + timer.stop = createFunction( |
| 1656 | + interpolate('o#'), |
| 1657 | + interpolate('var n#=this.ns,s#=o#.timeStamp,${end};o#.elapsed=r#') |
| 1658 | + ); |
1612 | 1659 |
|
1613 | 1660 | // Compile in setup/teardown functions and the test loop. |
1614 | 1661 | // Create a new compiled test, instead of using the cached `bench.compiled`, |
|
1643 | 1690 | // pretest to determine if compiled code is exits early, usually by a |
1644 | 1691 | // rogue `return` statement, by checking for a return object with the uid |
1645 | 1692 | bench.count = 1; |
1646 | | - compiled = (compiled.call(bench, context, timer) || {}).uid == uid && compiled; |
| 1693 | + compiled = (compiled.call(bench, context, timer) || {}).uid == templateData.uid && compiled; |
1647 | 1694 | bench.count = count; |
1648 | 1695 | } |
1649 | 1696 | } catch(e) { |
|
1762 | 1809 | */ |
1763 | 1810 | function interpolate(string) { |
1764 | 1811 | // replaces all occurrences of `#` with a unique number and template tokens with content |
1765 | | - return _.template(string.replace(/\#/g, /\d+/.exec(uid)), templateData || {}); |
| 1812 | + var data = templateData || { 'uid': uid }; |
| 1813 | + return _.template(string.replace(/\#/g, /\d+/.exec(data.uid)), data); |
1766 | 1814 | } |
1767 | 1815 |
|
1768 | 1816 | /*----------------------------------------------------------------------*/ |
|
1816 | 1864 | if (timer.res == Infinity) { |
1817 | 1865 | throw new Error('Benchmark.js was unable to find a working timer.'); |
1818 | 1866 | } |
1819 | | - // use API of chosen timer |
1820 | | - if (timer.unit == 'ns') { |
1821 | | - if (timer.ns.nanoTime) { |
1822 | | - _.extend(templateData, { |
1823 | | - 'begin': interpolate('s#=n#.nanoTime()'), |
1824 | | - 'end': interpolate('r#=(n#.nanoTime()-s#)/1e9') |
1825 | | - }); |
1826 | | - } else { |
1827 | | - _.extend(templateData, { |
1828 | | - 'begin': interpolate('s#=n#()'), |
1829 | | - 'end': interpolate('r#=n#(s#);r#=r#[0]+(r#[1]/1e9)') |
1830 | | - }); |
1831 | | - } |
1832 | | - } |
1833 | | - else if (timer.unit == 'us') { |
1834 | | - if (timer.ns.stop) { |
1835 | | - _.extend(templateData, { |
1836 | | - 'begin': interpolate('s#=n#.start()'), |
1837 | | - 'end': interpolate('r#=n#.microseconds()/1e6') |
1838 | | - }); |
1839 | | - } else if (perfName) { |
1840 | | - _.extend(templateData, { |
1841 | | - 'begin': interpolate('s#=n#.' + perfName + '()'), |
1842 | | - 'end': interpolate('r#=(n#.' + perfName + '()-s#)/1e3') |
1843 | | - }); |
1844 | | - } else { |
1845 | | - _.extend(templateData, { |
1846 | | - 'begin': interpolate('s#=n#()'), |
1847 | | - 'end': interpolate('r#=(n#()-s#)/1e6') |
1848 | | - }); |
1849 | | - } |
1850 | | - } |
1851 | | - |
1852 | | - // define `timer` methods |
1853 | | - timer.start = createFunction( |
1854 | | - interpolate('o#'), |
1855 | | - interpolate('var n#=this.ns,${begin};o#.elapsed=0;o#.timeStamp=s#') |
1856 | | - ); |
1857 | | - |
1858 | | - timer.stop = createFunction( |
1859 | | - interpolate('o#'), |
1860 | | - interpolate('var n#=this.ns,s#=o#.timeStamp,${end};o#.elapsed=r#') |
1861 | | - ); |
1862 | | - |
1863 | 1867 | // resolve time span required to achieve a percent uncertainty of at most 1% |
1864 | 1868 | // http://spiff.rit.edu/classes/phys273/uncert/uncert.html |
1865 | 1869 | options.minTime || (options.minTime = max(timer.res / 2 / 0.01, 0.05)); |
|
0 commit comments