mirror of
https://github.com/josdejong/mathjs.git
synced 2025-12-08 19:46:04 +00:00
* Add unit parser benchmark * Add LRU to memoize function * Memoize _findUnit This fixes some performance issues in my heavily-unit-parsing app. Another idea might be to do an index of reversed unit names, and search in that, but this is much easier to implement and still should provide an improvement in the majority of cases (since I'd imagine that most users tend to prefer a few units at a time, depending on their application). * Optimize memoize function This should be just a little bit faster than before by using Maps, which have less overhead than javascript objects.
149 lines
4.3 KiB
JavaScript
149 lines
4.3 KiB
JavaScript
import assert from 'assert'
|
|
import { maxArgumentCount, memoize, memoizeCompare } from '../../../src/utils/function.js'
|
|
import { deepStrictEqual } from '../../../src/utils/object.js'
|
|
|
|
describe('util.function', function () {
|
|
describe('memoize', function () {
|
|
it('should memoize a function with one argument', function () {
|
|
const f = function (x) { return x * x }
|
|
|
|
const m = memoize(f)
|
|
|
|
assert.strictEqual(m(2), 4)
|
|
assert.strictEqual(m(3), 9)
|
|
})
|
|
|
|
it('should memoize a function with two arguments', function () {
|
|
const f = function (x, y) { return x * y }
|
|
|
|
const m = memoize(f)
|
|
|
|
assert.strictEqual(m(2, 3), 6)
|
|
|
|
// hash should differ
|
|
assert.strictEqual(m(1, 23), 23)
|
|
assert.strictEqual(m(12, 3), 36)
|
|
})
|
|
|
|
it('should memoize a function with objects as arguments', function () {
|
|
const f = function (obj) { return obj.x * obj.y }
|
|
|
|
const m = memoize(f)
|
|
|
|
assert.strictEqual(m({ x: 2, y: 3 }), 6)
|
|
assert.deepStrictEqual([...m.cache.values.keys()], ['[{"x":2,"y":3}]'])
|
|
assert.strictEqual(m.cache.values.get('[{"x":2,"y":3}]'), 6)
|
|
})
|
|
|
|
it('should memoize a function with a custom hashIt function', function () {
|
|
const f = function (obj) { return obj.id }
|
|
const hashIt = function (args) {
|
|
return 'id:' + args[0].id
|
|
}
|
|
|
|
const m = memoize(f, { hasher: hashIt })
|
|
|
|
assert.strictEqual(m({ id: 2 }), 2)
|
|
assert.deepStrictEqual([...m.cache.values.keys()], ['id:2'])
|
|
assert.strictEqual(m.cache.values.get('id:2'), 2)
|
|
})
|
|
|
|
it('should really return the cached result', function () {
|
|
let a = 2
|
|
const f = function (x) { return a } // trick: no pure function
|
|
|
|
const m = memoize(f)
|
|
|
|
assert.strictEqual(m(4), 2)
|
|
a = 3
|
|
assert.strictEqual(m(4), 2)
|
|
})
|
|
})
|
|
|
|
it('should limit the number of values stored', function () {
|
|
let a = 1
|
|
const f = function (x) { a++; return a } // trick: no pure function
|
|
|
|
const m = memoize(f, { limit: 2 })
|
|
|
|
assert.strictEqual(m(1), 2)
|
|
assert.strictEqual(m(2), 3)
|
|
// this should evict m(1)
|
|
assert.strictEqual(m(3), 4)
|
|
|
|
assert.strictEqual(m(1), 5)
|
|
})
|
|
|
|
describe('memoizeCompare', function () {
|
|
it('should memoize using comparison', () => {
|
|
let execCount = 0
|
|
|
|
function multiply (obj) {
|
|
execCount++
|
|
return obj.x * obj.y
|
|
}
|
|
|
|
const m = memoizeCompare(multiply, deepStrictEqual)
|
|
|
|
assert.strictEqual(m({ x: 2, y: 3 }), 6)
|
|
assert.strictEqual(execCount, 1)
|
|
assert.strictEqual(m({ x: 2, y: 3 }), 6)
|
|
assert.strictEqual(execCount, 1)
|
|
|
|
assert.strictEqual(m({ x: 2, y: 3, z: 4 }), 6)
|
|
assert.strictEqual(execCount, 2)
|
|
|
|
const fn1 = (a, b) => a + b
|
|
const fn2 = (a, b) => a + b
|
|
assert.strictEqual(m({ x: 2, y: 3, add: fn1 }), 6)
|
|
assert.strictEqual(execCount, 3)
|
|
assert.strictEqual(m({ x: 2, y: 3, add: fn1 }), 6)
|
|
assert.strictEqual(execCount, 3)
|
|
assert.strictEqual(m({ x: 2, y: 3, add: fn2 }), 6)
|
|
assert.strictEqual(execCount, 4)
|
|
|
|
assert.strictEqual(m({ x: 2, y: 3, z: undefined }), 6)
|
|
assert.strictEqual(execCount, 5)
|
|
assert.strictEqual(m({ x: 2, y: 3, z: undefined }), 6)
|
|
assert.strictEqual(execCount, 5)
|
|
})
|
|
})
|
|
|
|
describe('maxArgumentCount', function () {
|
|
it('should calculate the max argument count of a typed function', function () {
|
|
const a = function () {}
|
|
a.signatures = {
|
|
'number, number': function () {},
|
|
number: function () {}
|
|
}
|
|
assert.strictEqual(maxArgumentCount(a), 2)
|
|
|
|
const b = function () {}
|
|
b.signatures = {
|
|
number: function () {},
|
|
'number, number': function () {}
|
|
}
|
|
assert.strictEqual(maxArgumentCount(b), 2)
|
|
|
|
const c = function () {}
|
|
c.signatures = {
|
|
number: function () {},
|
|
BigNumber: function () {}
|
|
}
|
|
assert.strictEqual(maxArgumentCount(c), 1)
|
|
|
|
const d = function () {}
|
|
d.signatures = {
|
|
'number,number': function () {},
|
|
number: function () {},
|
|
'number,any,number': function () {}
|
|
}
|
|
assert.strictEqual(maxArgumentCount(d), 3)
|
|
})
|
|
|
|
it('should return -1 for regular functions', function () {
|
|
assert.strictEqual(maxArgumentCount(function () {}), -1)
|
|
})
|
|
})
|
|
})
|