Skip to content

Commit 64df84d

Browse files
committed
Replace murmur hash with djb2 hash
In profiling StyleSheet.create, I noticed that much of the time was spent hashing. So, I found a faster hashing algorithm. The implementation was taken from: https://github.com/darkskyapp/string-hash According to this StackExchange post, this algorithm doesn't have as good of randomness, but it has about the same percentage of collisions. I don't think randomness matters for this application, so I think this is okay. http://softwareengineering.stackexchange.com/a/145633 Using similar methodology to #202, this appears to make StylSheet.create ~15% faster (~220ms to ~185ms).
1 parent e30ed7b commit 64df84d

1 file changed

Lines changed: 13 additions & 42 deletions

File tree

src/util.js

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -152,52 +152,23 @@ export const stringifyValue = (
152152
};
153153

154154
/**
155-
* JS Implementation of MurmurHash2
155+
* JS Implementation of djb2
156156
*
157-
* @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
158-
* @see http://github.com/garycourt/murmurhash-js
159-
* @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
160-
* @see http://sites.google.com/site/murmurhash/
161-
*
162-
* @param {string} str ASCII only
163-
* @return {string} Base 36 encoded hash result
157+
* @see https://github.com/darkskyapp/string-hash
164158
*/
165-
function murmurhash2_32_gc(str) {
166-
let l = str.length;
167-
let h = l;
168-
let i = 0;
169-
let k;
170-
171-
while (l >= 4) {
172-
k = ((str.charCodeAt(i) & 0xff)) |
173-
((str.charCodeAt(++i) & 0xff) << 8) |
174-
((str.charCodeAt(++i) & 0xff) << 16) |
175-
((str.charCodeAt(++i) & 0xff) << 24);
176-
177-
k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
178-
k ^= k >>> 24;
179-
k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
180-
181-
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
182-
183-
l -= 4;
184-
++i;
185-
}
186159

187-
/* eslint-disable no-fallthrough */ // forgive existing code
188-
switch (l) {
189-
case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
190-
case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
191-
case 1: h ^= (str.charCodeAt(i) & 0xff);
192-
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
193-
}
194-
/* eslint-enable no-fallthrough */
160+
function djb2Hash(str) {
161+
let hash = 5381;
162+
let i = str.length;
195163

196-
h ^= h >>> 13;
197-
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
198-
h ^= h >>> 15;
164+
while(i) {
165+
hash = (hash * 33) ^ str.charCodeAt(--i);
166+
}
199167

200-
return (h >>> 0).toString(36);
168+
/* JavaScript does bitwise operations (like XOR, above) on 32-bit signed
169+
* integers. Since we want the results to be always positive, convert the
170+
* signed int to an unsigned by doing an unsigned bitshift. */
171+
return "" + (hash >>> 0);
201172
}
202173

203174
// Hash a javascript object using JSON.stringify. This is very fast, about 3
@@ -208,7 +179,7 @@ function murmurhash2_32_gc(str) {
208179
// this to produce consistent hashes browsers need to have a consistent
209180
// ordering of objects. Ben Alpert says that Facebook depends on this, so we
210181
// can probably depend on this too.
211-
export const hashObject = (object /* : ObjectMap */) /* : string */ => murmurhash2_32_gc(JSON.stringify(object));
182+
export const hashObject = (object /* : ObjectMap */) /* : string */ => djb2Hash(JSON.stringify(object));
212183

213184

214185
const IMPORTANT_RE = /^([^:]+:.*?)( !important)?;$/;

0 commit comments

Comments
 (0)