hash function does multiple toStrings when it could do 1
Bug report
Description / Observed Behavior
I was looking through the codebase and specifically src/_internal/utils/hash.ts
There are 3 calls to isObjectType which in turn executes OBJECT.prototype.toString.call(value).
Expected Behavior
Given that OBJECT.prototype.toString.call(value) will be constant across these three calls the code could be changed to call that toString just once.
Repro Steps / Code Example
const isObjectType = ( value: any, type: string ) => {
return getTypeName( value ) === `[object ${ type }]`
}
...
const isDate = isObjectType( arg, 'Date' );
const isRegex = isObjectType( arg, 'RegExp' );
const isPlainObject = isObjectType( arg, 'Object' );
...
becomes
const getTypeName = ( value: any ) => {
return Object.prototype.toString.call( value )
}
const isObjectTypeName = ( typeName: string, type: string ) => {
return typeName === `[object ${ type }]`
}
...
const typeName = getTypeName( arg );
const isDate = isObjectTypeName( typeName, 'Date' );
const isRegex = isObjectTypeName( typeName, 'RegExp' );
const isPlainObject = isObjectTypeName( typeName, 'Object' );
...
Additional Context
This is a micro performance optimisation which I don't generally condone - but in this case - every use of stableHash goes through those three lines before performing any other work. Therefore it's a hot spot in the code and I believe worthy of examination.
Of the work done on every call - these three lines are the expensive ones.
In my brief experimentation the performance gain is considerable when there is a cache hit (nearly 3x faster), and marginal when there is a miss (the other work performed on a miss includes calls to .sort and .toJson which will be very computationally expensive).
Happy do turn this into a pull request if you're in agreement with the change.
Thanks, feel free to open a PR for this!