The fastest object diff library in JavaScript(github.com) |
The fastest object diff library in JavaScript(github.com) |
Seems that this particular library is aware of these potential issues (which motivated me to write this comment): https://github.com/AsyncBanana/microdiff/issues/2
Symmetry doesn't get a lot of activity, but I've been using it in production for many years. It does some more work on array diffing, which this benchmark doesn't cover, by implementing part of Myers' algorithm.
I added three more libraries, and also the size in bytes of `JSON.stringify(result)` for each. (That was also important for me in making symmetry.)
The results from benchmark.js are a lot more consistent on my laptop:
Benchmark: Small object (baseline)
- @n1ru4l/json-patch-plus x 1,426,241 ops/sec ±0.29% (94 runs sampled) (94 bytes)
- deep-diff x 337,122 ops/sec ±0.45% (95 runs sampled) (193 bytes)
- deep-object-diff x 2,138,118 ops/sec ±0.25% (96 runs sampled) (60 bytes)
- diff x 59,277 ops/sec ±0.60% (97 runs sampled) (268 bytes)
- jsondiffpatch x 841,880 ops/sec ±0.38% (96 runs sampled) (113 bytes)
- microdiff x 6,979,471 ops/sec ±0.77% (95 runs sampled) (171 bytes)
- symmetry x 8,666,619 ops/sec ±0.21% (97 runs sampled) (7 bytes)
Benchmark: Large Object (300 properties)
- @n1ru4l/json-patch-plus x 16,902 ops/sec ±0.66% (92 runs sampled) (515 bytes)
- deep-diff x 8,378 ops/sec ±0.68% (96 runs sampled) (1194 bytes)
- deep-object-diff x 19,647 ops/sec ±0.40% (94 runs sampled) (410 bytes)
- diff x 737 ops/sec ±0.45% (94 runs sampled) (12051 bytes)
- jsondiffpatch x 14,306 ops/sec ±0.76% (95 runs sampled) (714 bytes)
- microdiff x 22,131 ops/sec ±0.25% (95 runs sampled) (935 bytes)
- symmetry x 21,432 ops/sec ±0.92% (98 runs sampled) (424 bytes)
Fast is great, but unless you know that your data doesn't have cycles, infinite loops take a long time :)
It’s a bit different, but I think it covers more cases.
That should be the job of a minifier, makes the code less readable.
(I admit there are many other parts to optimize too, but if I can just plug this for some extra juice, why not?)
Since performance is a goal, why not define an enum and use integer values? I don't know about speed, but the resulting diff would be smaller.
Also I wonder what "const t = true" is for.
// x.js
export const foo = "foo"
// y.js
if (x.foo === "foo") {
// ^ as cheap as int
}
const foo2 = "FOO".toLowerCase()
if (x.foo === foo2) {
// ^ questionable
// depends on jit/optimization
}
https://stackoverflow.com/questions/5276915/do-common-javasc...Wonder what everyone else is doing to make it slow.
Also curious what mobx and reacts object diffing looks like now.
Some diff libraries have React specific optimizations, if values might be React elements/components.
This code has 3 actual code commits over 6 days, none of which changed anything fundamental. What are you talking about?
It's quite possible to compete against this on multiple levels. One would be correctness. The other a bit less wasteful interface. Another would be handling arrays in a more useful way (or at all). And yet another would be safety. Another would be speed and memory use. Yet another would be non-recursive implementation. Another would be documentation (what's this diffing? enumerable/non-enumerable properties? how it deals with getters? how about inherited properties? - I can't know any of this without looking long and hard at the code)... etc. etc.
You could profile this lib and figure out where it’s spending most of its time and figure out if there any ways to improve (starts getting into implications of JS <-> system), but as you get more idiosyncratic you lose flexibility and ease of use.
Eg type checks, heap additions, recursion, etc can get “slow”
That's fine, of course, but probably should be in the README.
[1] https://github.com/AsyncBanana/microdiff/issues/2#issuecomme...
The code is clean, well organized and nice to look at, easy to read through and understand, and it's great that someone has made the effort to create this and share it for us to use.
For libraries above 1-2k lines of code that can be quite complicated (eg. things like database connectors), it starts being reasonable to mold expectations of my app around the library.
Also using coherent large utility libraries is something worthwhile (or was in the past), libs like underscore/lodash, etc.
But composing app from random underdocumented 2 function "libraries" from npm is just pain if you know what you're looking for. 1) you can't trust the code, so 2) you have to read it anyway and reading is often slower than writing
It's a good point about edge cases in diffing. Dynamic value diffing in dynamically-typed languages is an interesting problem to think about.
Every so often I try to reach for an npm library, only to find out that it's suboptimal, doesn't handle my edge cases, or just plain worse than the code I would have written.
The last time I tried to do this, I wanted a hash map with custom equality functions on the keys, since JS doesn't have one built-in by default. I searched for about 2 hours and didn't find a single one that actually worked (several claimed to be, but actually didn't work...)
So I wrote my own in about 100 lines. [0]
Data structures and algorithms tend to be really awful on npm.
[0] https://github.com/magcius/noclip.website/blob/master/src/Ha...