Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Giant refactor #14

Merged
merged 26 commits into from
Oct 9, 2016
Merged

Giant refactor #14

merged 26 commits into from
Oct 9, 2016

Conversation

keithamus
Copy link
Member

@keithamus keithamus commented Jun 7, 2016

We've had a few PRs against deep-eql which overlap some of this work. I'm just going to set up this PR for now, as a placeholder so we can refer to it while I finish the work left on it.

This will fix #13, #7, #4 and possibly #9
Also supersedes #12

object-is has semantically identical code (it is a polyfill for Object.is
which uses ES6 sameValue). By removing our implementation of sameValue we
remove any extra burden on maintaining that code
@coveralls
Copy link

Coverage Status

Coverage increased (+13.2%) to 94.792% when pulling 5778bbd on keithamus:giant-refactor into b509572 on chaijs:master.

@keithamus keithamus mentioned this pull request Jun 24, 2016
10 tasks
@montogeek
Copy link

How is this coming?

@keithamus
Copy link
Member Author

This is pretty much at final draft stage, I'd like to get people's thoughts (@meeber, @lucasfcosta, @hildjj) for any serious roadblockers, I have one or two tests to fix, then I'm going to clean up the readme and commits and people can take a final review before we get it merged.

@JoshuaWise
Copy link

Has it been confirmed that #11 is fixed in this branch?

@ghost
Copy link

ghost commented Sep 16, 2016

@keithamus @JoshuaWise

Hi. I saw this module, and I can supply with this:

  1. Set() can have a circular reference. Doesn't work.
  2. Set() can have a deep set with arrays and nested array. Doesn't work.
new Set([
    [],
    [],
]);

or even deeper then this

  1. transitive equivalence for circular references of arrays doesnt' work.
  2. transitive equivalence for circular references of objects doesnt' work.
  3. Expando properties comparison doesn't seem to work propertly
  4. Map() does seem to have the same issues as Set()
  5. Array check, not only on length, but properties included mostly fails. And so is deeply nested arrays.
  6. Performance
// simple === comparison on primitives
lodash x 55,261,863 ops/sec ±1.11% (91 runs sampled)
nodejS assert x 45,242,272 ops/sec ±1.09% (87 runs sampled)
chai x 16,690,551 ops/sec ±0.41% (92 runs sampled)

@ghost
Copy link

ghost commented Oct 3, 2016

@keithamus @meeber The last days I started to work on a similiar algorithm, and I found more issues in your current implementation. When run in browsers, you will get trouble with the core.js library with your feature detection. Example Symbol(). There are also issues with your generator implementation, and some other things.
Search for "kewlr" on NPM and you find my work in progress. Within a few days it's completed, and all your tests passes with that module (almost all). You also have a few issues with strict mode where you actualy accept loose comparison.

I would recommend to run a benchmark.

Update
@lucasfcosta You can find a benchmark on NPM if you search for Kewlr. Note that Kewlr supports more
features then similiar modules. Because of this the performance is little slower compared to Lodash, but faster on primitives. Comparing against this Chai implementation, it's just Bye bye!

@ghost
Copy link

ghost commented Oct 4, 2016

@keithamus I updated the benchmark results on NPM for kewlr. Look at the readme.
Example:

// chai
string literal              x 4,255,021 ops/sec ±1.08% (88 runs sampled
// kewlr
string literal              x 72,032,383 ops/sec ±1.56% (87 runs sampled)
// lodash
string literal              x 56,845,867 ops/sec ±2.48% (85 runs sampled)

This commit removes the bootstrap, which is used for testing in the browser,
switching instead to Karma, using browserify - which means `require` works in
both the browser and node, negating the need for the bootstrap and index.html
Only include `index.js` and `type-detect.js` (npm will automatically
include `package.json` and `README.md` for us
Add support for ES6 types

BREAKING CHANGE:

Many types will now return `false` if they are not deeply equal. Types which are not recognised
will likely default to returning `false`. Beforehand, unrecognised types would return `true`
@keithamus
Copy link
Member Author

Just pushed up some changes, which, IMO completes this PR.

Circular references are fixed. I've measured bench speed to be at least on par if not faster than the similar libs out there.

@zubuzon want to give this one more run through? Then if @meeber or @lucasfcosta could give it a review, that'd be grand 😄

@ghost
Copy link

ghost commented Oct 5, 2016

@keithamus I have a client meeting now, but will reply within 6 - 7 hours. I noticed you are using the typeof operator for string and booleans. That's not safe cross-browser. Or it depends. Safari 5 - 9 have major issues, and Safari 10 when it comes to function detection and window.proxy. Arguments is one issue, and the fact that Safari also returns 'object' for typed array and other constructors. There are also similar issues with IE 9 or IE10. Can't remember just now which IE has the issues.

@keithamus
Copy link
Member Author

Thanks for that @zubuzon. I'm about to push up some final changes which address some performance concerns, and it looks like it puts kewlr and deep-eql neck and neck with each other. Plus your comments here helped me find some perf issues around type-detect - so thanks for your awesome work!

equal references                     x 30,185,728 ops/sec ±0.79% (84 runs sampled)
equal references            (lodash) x 33,477,174 ops/sec ±1.08% (87 runs sampled)
equal references              (node) x 29,223,010 ops/sec ±1.16% (83 runs sampled)
equal references             (kewlr) x 29,725,254 ops/sec ±1.29% (83 runs sampled)
string literal                       x 26,777,833 ops/sec ±0.74% (86 runs sampled)
string literal              (lodash) x 33,178,445 ops/sec ±1.09% (85 runs sampled)
string literal                (node) x 24,795,377 ops/sec ±7.67% (76 runs sampled)
string literal               (kewlr) x 23,520,363 ops/sec ±1.69% (81 runs sampled)
array literal                        x 4,791,924 ops/sec ±2.65% (84 runs sampled)
array literal               (lodash) x 1,737,135 ops/sec ±2.53% (80 runs sampled)
array literal                 (node) x 3,924,768 ops/sec ±1.12% (85 runs sampled)
array literal                (kewlr) x 3,893,244 ops/sec ±1.80% (76 runs sampled)
boolean literal                      x 26,365,728 ops/sec ±1.61% (81 runs sampled)
boolean literal             (lodash) x 33,787,034 ops/sec ±1.01% (80 runs sampled)
boolean literal               (node) x 27,132,650 ops/sec ±3.56% (79 runs sampled)
boolean literal              (kewlr) x 26,790,226 ops/sec ±1.41% (77 runs sampled)
object literal                       x 160,121 ops/sec ±2.89% (81 runs sampled)
object literal              (lodash) x 375,221 ops/sec ±7.32% (79 runs sampled)
object literal                (node) x 392,734 ops/sec ±2.38% (85 runs sampled)
object literal               (kewlr) x 204,473 ops/sec ±4.86% (77 runs sampled)
object from null                     x 743,242 ops/sec ±2.16% (83 runs sampled)
object from null            (lodash) x 44,200 ops/sec ±7.57% (72 runs sampled)
object from null              (node) x 402,530 ops/sec ±5.67% (58 runs sampled)
object from null             (kewlr) x 683,462 ops/sec ±5.90% (75 runs sampled)
regex literal                        x 1,043,467 ops/sec ±1.84% (83 runs sampled)
regex literal               (lodash) x 335,548 ops/sec ±2.18% (82 runs sampled)
regex literal                 (node) x 1,084,563 ops/sec ±1.03% (87 runs sampled)
regex literal                (kewlr) x 1,088,024 ops/sec ±1.48% (83 runs sampled)
number literal                       x 25,318,512 ops/sec ±1.72% (84 runs sampled)
number literal              (lodash) x 21,410,354 ops/sec ±10.98% (60 runs sampled)
number literal                (node) x 28,936,738 ops/sec ±6.79% (71 runs sampled)
number literal               (kewlr) x 26,593,925 ops/sec ±2.67% (85 runs sampled)
null                                 x 26,548,814 ops/sec ±1.82% (78 runs sampled)
null                        (lodash) x 37,122,760 ops/sec ±1.23% (82 runs sampled)
null                          (node) x 28,943,744 ops/sec ±1.37% (82 runs sampled)
null                         (kewlr) x 25,639,640 ops/sec ±1.29% (83 runs sampled)
undefined                            x 26,793,512 ops/sec ±1.68% (83 runs sampled)
undefined                   (lodash) x 28,996,034 ops/sec ±3.45% (75 runs sampled)
undefined                     (node) x 16,685,232 ops/sec ±3.38% (62 runs sampled)
undefined                    (kewlr) x 13,301,426 ops/sec ±3.48% (59 runs sampled)
buffer                               x 1,166,637 ops/sec ±6.09% (73 runs sampled)
buffer                      (lodash) x 305,298 ops/sec ±4.90% (73 runs sampled)
buffer                        (node) x 611,182 ops/sec ±2.47% (65 runs sampled)
buffer                       (kewlr) x 1,805,370 ops/sec ±7.01% (80 runs sampled)
date                                 x 1,477,489 ops/sec ±1.61% (84 runs sampled)
date                        (lodash) x 383,568 ops/sec ±3.92% (76 runs sampled)
date                          (node) x 1,579,520 ops/sec ±7.81% (55 runs sampled)
date                         (kewlr) x 1,355,922 ops/sec ±3.70% (82 runs sampled)
map                                  x 428,304 ops/sec ±1.50% (83 runs sampled)
map                         (lodash) x 114,511 ops/sec ±6.13% (55 runs sampled)
map                           (node) x 363,201 ops/sec ±7.88% (66 runs sampled)
map                          (kewlr) x 353,101 ops/sec ±1.62% (77 runs sampled)
map (complex)                        x 208,892 ops/sec ±2.06% (79 runs sampled)
map (complex)               (lodash) x 86,200 ops/sec ±1.94% (83 runs sampled)
map (complex)                 (node) x 215,696 ops/sec ±2.14% (83 runs sampled)
map (complex)                (kewlr) x 211,474 ops/sec ±1.80% (83 runs sampled)
regex constructor                    x 991,261 ops/sec ±1.43% (86 runs sampled)
regex constructor           (lodash) x 337,164 ops/sec ±1.45% (83 runs sampled)
regex constructor             (node) x 1,096,757 ops/sec ±1.31% (85 runs sampled)
regex constructor            (kewlr) x 885,270 ops/sec ±1.20% (87 runs sampled)
set                                  x 457,339 ops/sec ±1.83% (85 runs sampled)
set                         (lodash) x 286,578 ops/sec ±1.80% (85 runs sampled)
set                           (node) x 456,365 ops/sec ±1.59% (81 runs sampled)
set                          (kewlr) x 429,694 ops/sec ±1.53% (83 runs sampled)
string constructor                   x 514,869 ops/sec ±1.63% (83 runs sampled)
string constructor          (lodash) x 411,920 ops/sec ±1.30% (87 runs sampled)
string constructor            (node) x 494,610 ops/sec ±1.65% (83 runs sampled)
string constructor           (kewlr) x 493,242 ops/sec ±2.16% (85 runs sampled)
arguments                            x 380,972 ops/sec ±1.73% (83 runs sampled)
arguments                   (lodash) x 78,450 ops/sec ±1.79% (84 runs sampled)
arguments                     (node) x 253,400 ops/sec ±7.33% (75 runs sampled)
arguments                    (kewlr) x 241,532 ops/sec ±10.82% (53 runs sampled)
string literal (differing)           x 22,658,949 ops/sec ±6.82% (67 runs sampled)
string literal (differing)  (lodash) x 26,871,927 ops/sec ±2.31% (78 runs sampled)
string literal (differing)    (node) x 24,070,769 ops/sec ±6.00% (76 runs sampled)
string literal (differing)   (kewlr) x 23,785,463 ops/sec ±2.73% (80 runs sampled)
array literal (differing)            x 3,297,624 ops/sec ±1.45% (81 runs sampled)
array literal (differing)   (lodash) x 1,597,478 ops/sec ±2.83% (82 runs sampled)
array literal (differing)     (node) x 3,077,185 ops/sec ±1.22% (84 runs sampled)
array literal (differing)    (kewlr) x 3,142,476 ops/sec ±0.76% (84 runs sampled)
boolean literal (differing)          x 21,808,373 ops/sec ±1.13% (84 runs sampled)
boolean literal (differing) (lodash) x 23,210,323 ops/sec ±1.54% (83 runs sampled)
boolean literal (differing)   (node) x 22,206,355 ops/sec ±0.81% (85 runs sampled)
boolean literal (differing)  (kewlr) x 21,797,564 ops/sec ±0.89% (83 runs sampled)
object literal (differing)           x 321,539 ops/sec ±1.39% (84 runs sampled)
object literal (differing)  (lodash) x 370,935 ops/sec ±1.43% (87 runs sampled)
object literal (differing)    (node) x 304,948 ops/sec ±1.45% (86 runs sampled)
object literal (differing)   (kewlr) x 302,986 ops/sec ±1.51% (85 runs sampled)
regex literal (differing)            x 1,045,493 ops/sec ±1.12% (87 runs sampled)
regex literal (differing)   (lodash) x 322,744 ops/sec ±1.22% (87 runs sampled)
regex literal (differing)     (node) x 1,000,455 ops/sec ±0.96% (87 runs sampled)
regex literal (differing)    (kewlr) x 977,459 ops/sec ±1.14% (86 runs sampled)
number literal (differing)           x 25,332,882 ops/sec ±1.01% (85 runs sampled)
number literal (differing)  (lodash) x 26,136,136 ops/sec ±1.24% (83 runs sampled)
number literal (differing)    (node) x 24,783,195 ops/sec ±0.78% (84 runs sampled)
number literal (differing)   (kewlr) x 26,254,105 ops/sec ±0.87% (85 runs sampled)
null & undefined                     x 22,480,849 ops/sec ±1.01% (85 runs sampled)
null & undefined            (lodash) x 28,684,519 ops/sec ±1.26% (83 runs sampled)
null & undefined              (node) x 22,619,411 ops/sec ±0.92% (85 runs sampled)
null & undefined             (kewlr) x 21,442,276 ops/sec ±0.74% (86 runs sampled)
buffer (differing)                   x 3,099,370 ops/sec ±1.24% (86 runs sampled)
buffer (differing)          (lodash) x 521,279 ops/sec ±1.28% (87 runs sampled)
buffer (differing)            (node) x 3,100,834 ops/sec ±0.75% (87 runs sampled)
buffer (differing)           (kewlr) x 3,098,341 ops/sec ±0.90% (88 runs sampled)
date (differing)                     x 1,609,713 ops/sec ±1.23% (86 runs sampled)
date (differing)            (lodash) x 362,763 ops/sec ±6.24% (79 runs sampled)
date (differing)              (node) x 1,657,047 ops/sec ±3.13% (79 runs sampled)
date (differing)             (kewlr) x 1,476,759 ops/sec ±1.63% (84 runs sampled)
error                                x 435,380 ops/sec ±3.23% (76 runs sampled)
error                       (lodash):
error                         (node) x 384,822 ops/sec ±2.39% (80 runs sampled)
error                        (kewlr) x 449,851 ops/sec ±2.01% (82 runs sampled)
map (differing)                      x 456,880 ops/sec ±2.78% (82 runs sampled)
map (differing)             (lodash) x 113,193 ops/sec ±4.54% (75 runs sampled)
map (differing)               (node) x 437,193 ops/sec ±6.25% (65 runs sampled)
map (differing)              (kewlr) x 467,565 ops/sec ±1.96% (83 runs sampled)
regex ctor (differing)               x 1,003,114 ops/sec ±2.04% (83 runs sampled)
regex ctor (differing)      (lodash) x 305,026 ops/sec ±2.77% (80 runs sampled)
regex ctor (differing)        (node) x 1,021,049 ops/sec ±2.24% (78 runs sampled)
regex ctor (differing)       (kewlr) x 1,072,173 ops/sec ±3.20% (79 runs sampled)
set (differing)                      x 245,355 ops/sec ±6.00% (71 runs sampled)
set (differing)             (lodash) x 201,888 ops/sec ±2.85% (70 runs sampled)
set (differing)               (node) x 442,345 ops/sec ±4.19% (74 runs sampled)
set (differing)              (kewlr) x 179,609 ops/sec ±5.62% (67 runs sampled)
string ctor (differing)              x 499,227 ops/sec ±4.43% (67 runs sampled)
string ctor (differing)     (lodash) x 421,705 ops/sec ±2.81% (81 runs sampled)
string ctor (differing)       (node) x 500,065 ops/sec ±5.93% (81 runs sampled)
string ctor (differing)      (kewlr) x 455,706 ops/sec ±2.04% (82 runs sampled)
weakmap                              x 4,454,606 ops/sec ±0.94% (84 runs sampled)
weakmap                     (lodash) x 322,357 ops/sec ±1.43% (88 runs sampled)
weakmap                       (node) x 4,069,507 ops/sec ±1.00% (86 runs sampled)
weakmap                      (kewlr) x 4,577,305 ops/sec ±0.99% (81 runs sampled)
weakset                              x 4,270,687 ops/sec ±1.39% (85 runs sampled)
weakset                     (lodash) x 469,673 ops/sec ±2.03% (87 runs sampled)
weakset                       (node) x 4,269,730 ops/sec ±0.88% (82 runs sampled)
weakset                      (kewlr) x 4,064,133 ops/sec ±0.75% (86 runs sampled)
arguments (differing)                x 470,369 ops/sec ±1.67% (86 runs sampled)
arguments (differing)       (lodash) x 81,100 ops/sec ±1.50% (85 runs sampled)
arguments (differing)         (node) x 476,720 ops/sec ±1.81% (86 runs sampled)
arguments (differing)        (kewlr) x 472,966 ops/sec ±1.43% (86 runs sampled)
function                             x 23,314,291 ops/sec ±0.96% (88 runs sampled)
function                    (lodash) x 473,043 ops/sec ±1.45% (85 runs sampled)
function                      (node) x 25,134,161 ops/sec ±0.90% (83 runs sampled)
function                     (kewlr) x 25,218,572 ops/sec ±0.95% (82 runs sampled)
promise                              x 4,802,371 ops/sec ±0.87% (84 runs sampled)
promise                     (lodash) x 466,869 ops/sec ±1.65% (88 runs sampled)
promise                       (node) x 4,728,301 ops/sec ±0.89% (79 runs sampled)
promise                      (kewlr) x 4,582,195 ops/sec ±1.13% (81 runs sampled)
arrow function (differing)           x 24,921,516 ops/sec ±1.03% (82 runs sampled)
arrow function (differing)  (lodash) x 472,261 ops/sec ±1.44% (87 runs sampled)
arrow function (differing)    (node) x 22,965,940 ops/sec ±0.97% (86 runs sampled)
arrow function (differing)   (kewlr) x 23,221,593 ops/sec ±0.90% (86 runs sampled)
generator func (differing)           x 22,682,591 ops/sec ±0.96% (84 runs sampled)
generator func (differing)  (lodash) x 475,910 ops/sec ±1.33% (85 runs sampled)
generator func (differing)    (node) x 24,884,980 ops/sec ±1.13% (84 runs sampled)
generator func (differing)   (kewlr) x 21,185,077 ops/sec ±1.18% (84 runs sampled)

@meeber @lucasfcosta I'd say when I push up these changes this will be a 100% complete PR. I don't want to make any more changes to it (unless of course anything comes up in your final review). But I'd say we're good to go, and good to fold into chai 4.0!

@lucasfcosta
Copy link
Member

@keithamus that looks awesome!
Great job, you've done a great work improving this module's performance. I've learned a lot by reading this issue and your code, thank you very much!

I'll be happy to review your changes as soon as you push them 😄

@keithamus
Copy link
Member Author

@lucasfcosta @meeber pushed! Let's merge this thing!

@keithamus keithamus changed the title WIP! Giant refactor Giant refactor Oct 8, 2016
@keithamus
Copy link
Member Author

keithamus commented Oct 8, 2016

FYI we should probably wait for chaijs/type-detect#79 before merging... in fact all the tests are failing because it has been written against that version.

@ghost
Copy link

ghost commented Oct 8, 2016

@keithamus Glad i could help :) Chai is a awsome library!! A last tip. I saw you was still using forEach for Map() and Set() too solve IE11 issue. In Kewlr I feature detect IE, and only using forEach for IE, and faster solution for everything else!

@meeber
Copy link
Contributor

meeber commented Oct 8, 2016

LGTM! Excellent work @keithamus and @zubuzon!

Edit: Assuming type-detect gets updated to 3.0.0 in package.json and the tests pass of course :D

@ghost
Copy link

ghost commented Oct 9, 2016

@keithamus @meeber @lucasfcosta

I wish you all three luck with Chai. "Chai" is sort of a word everyone knows, and that is something to be proud of! This was the first time I contributed in open source, and I'm now off Github and back to RL and my companies. I will continue ofc to use Chai as everyone else!

A tip for next release - 4.0 - would be not only offer a common.js module, but also NodeJS module. Many libraries now offer this, and it's the future to come. And make it easier for end-users to import this library!

My time is up, and once again! Great work with this! And good luck to you all!

ZubuZon

@keithamus
Copy link
Member Author

@lucasfcosta can we get your seal of approval and merge this sucker?

@lucasfcosta
Copy link
Member

lucasfcosta commented Oct 9, 2016

LGTM too!
Awesome job @keithamus and thanks for the help @zubuzon for the performance improvement help and @meeber for the excellent review!

It's great to work with such talented people!
Here we go!

WE'VE GOT A LIFT OFF

@lucasfcosta lucasfcosta merged commit 5794440 into chaijs:master Oct 9, 2016
@keithamus keithamus deleted the giant-refactor branch October 9, 2016 18:17

var comparatorResult = comparator && comparator(leftHandOperand, rightHandOperand);
if (comparatorResult === false || comparatorResult === true) {
memoizeSet(leftHandOperand, rightHandOperand, options.memoize, comparatorResult);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why set these twice, rather than check both in the memoizeResult check on L161?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Update componentjs authentication
7 participants