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

core(computed-artifact): use deep equality over strict #4409

Merged
merged 4 commits into from
Feb 8, 2018

Conversation

patrickhulce
Copy link
Collaborator

needed by #3618 and the introduction of audit options (multiple different audits will request the same lantern simulation settings for example)

@patrickhulce patrickhulce changed the title refactor(computed-artifact): use deep equality over strict core(computed-artifact): use deep equality over strict Feb 1, 2018
assert.equal(map.get('foo'), 4);
});

it('is not hella slow', () => {
Copy link
Member

Choose a reason for hiding this comment

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

wanna set a custom .timeout(x) on this it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

sure

}

static deepEquals(objA, objB, maxDepth = 5) {
if (objA === objB) return true;
Copy link
Member

Choose a reason for hiding this comment

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

not crazy about maintaining this, even though is VERY well tested. :)

how about we try/catch assert.deepStrictEqual and use that? And we can use our assertTraceEventsEqual thats in asset-saver-test.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

discussed offline, basically exceptions are a dog, the "is not hella slow" test takes 55s a.k.a it's hella slow so we'll just use jdalton's isEqual from lodash instead :)

class ComputedArtifact {
/**
* @param {!ComputedArtifacts} allComputedArtifacts
*/
constructor(allComputedArtifacts) {
/** @private {!Map} */
this._cache = new Map();
this._cache = new CustomMap(CustomMap.deepEquals);
Copy link
Member

Choose a reason for hiding this comment

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

instead of passing it into the constructor i'm thinking it might be helpful to clarify the intent of the arg.

how about:

this._cache = new CustomMap();
this._cache.setEqualityFn(CustomMap.deepEquals);

without it being set, it's just using a === b

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

good plan 👍

@@ -5,13 +5,15 @@
*/
'use strict';

const CustomMap = require('../../lib/custom-map');
Copy link
Member

Choose a reason for hiding this comment

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

this impl doesn't support new CustomMap([[x, 1], [y, 2]]).

given that maybe call it CacheMap? really anything to give it some distance appearing as a true subclass of Map

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ah yeah, good call I'll add support :)

Copy link
Member

Choose a reason for hiding this comment

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

hmmm. I don't think we have a real usecase for supporting that constructor API. can we keep it out of scope?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

alright alright, cache map it is

@wardpeet
Copy link
Collaborator

wardpeet commented Feb 6, 2018

It's a really stupid question probably but why does this help us for project Lantern? Which use case do we want to tackle here? (not sure why we need deep equal yet)

@patrickhulce
Copy link
Collaborator Author

why does this help us for project Lantern? Which use case do we want to tackle here?

not stupid question, it's hard/impossible to tell from just this PR :)

basically simulator.js accepts options for what type of connection/cpu/etc to simulate but there's no mechanism for a LH user to control those options, audit/gatherer options gives us this

however, because computed artifacts cache their contents based on strict equality the options objects won't match even if they all request lantern on 3G and so the entire graph would be re-computed for every performance opportunity, introducing caching based on deep equality allows us to maintain the status quo computing the graph just once per setting. make sense?

* It is not meant to be performant and is well-suited to use cases where the number of entries is
* likely to be small (like computed artifacts).
*/
module.exports = class CacheMap {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

for the record, I'm still not a huge fan of this name, something like ArbitraryEqualityMap would make more sense 😛

Copy link
Member

Choose a reason for hiding this comment

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

I'm fine with calling it ArbitraryEqualityMap.

@wardpeet
Copy link
Collaborator

wardpeet commented Feb 7, 2018

however, because computed artifacts cache their contents based on strict equality the options objects won't match even if they all request lantern on 3G and so the entire graph would be re-computed for every performance opportunity, introducing caching based on deep equality allows us to maintain the status quo computing the graph just once per setting. make sense?

Yes but where does the cpu options come in? Do we store it in the computed artifacts?

@patrickhulce
Copy link
Collaborator Author

Yes but where does the cpu options come in? Do we store it in the computed artifacts?

Not 100% sure what you're asking, but each audit will have default options that can be overridden from config. Audit will pass the blended final options to the computed artifact and if it hasn't been requested with the same options before will compute it otherwise return the corresponding one from cache.

Copy link
Member

@paulirish paulirish left a comment

Choose a reason for hiding this comment

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

% nit

class ComputedArtifact {
/**
* @param {!ComputedArtifacts} allComputedArtifacts
*/
constructor(allComputedArtifacts) {
/** @private {!Map} */
this._cache = new Map();
this._cache = new CacheMap();
this._cache.setEqualsFn(CacheMap.deepEquals);
Copy link
Member

Choose a reason for hiding this comment

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

setEqualityFn

@paulirish
Copy link
Member

lgtm just waiting for CI

@patrickhulce patrickhulce merged commit f9cdfc5 into master Feb 8, 2018
@patrickhulce patrickhulce deleted the computed_art_deep_eqls branch February 8, 2018 18:57
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.

4 participants