Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Lazy resource store #1195

Merged
merged 31 commits into from
Aug 22, 2013
Merged

Lazy resource store #1195

merged 31 commits into from
Aug 22, 2013

Conversation

jarnoux
Copy link
Contributor

@jarnoux jarnoux commented Jul 15, 2013

This pull request implements an optional lazy resolution of resources that potentially makes the resource store creation independent of the number of dimensions and linear with the number of resources.
It also introduces the ability for plugins to alter configurations

jarnoux and others added 13 commits July 15, 2013 19:59
…haker), replaced access to _mojitDetails with _resolveMojit() method that resolves and caches resources at runtime, the 'chosen' member of the resources is not irrelevant since we don't chose any of them. It might overload the Y instance with a few useless addons
…n the plugin and its host when the config is later modified by another plugin
added JSON chached resources on the first request
transformed for in loops to index  based loops
… have been loaded do we want to reload the resources
…at allows to trigger lazy resolution of resources only if it is truthy
@gomezd
Copy link
Collaborator

gomezd commented Jul 15, 2013

Just a note from the description of this PR: "It also introduces the ability for plugins to alter configurations". This is part of a previous PR:
#1187

dgomez added 2 commits July 16, 2013 17:39
…ource_store

Conflicts:
	lib/app/addons/rs/selector.js
	lib/app/autoload/store.server.js
@isao
Copy link
Contributor

isao commented Jul 22, 2013

This looks good to me. I think some of these changes should be the new default behavior (not a separate code path + config), but drewfish is back tomorrow. We'll get his input before proceeding.

@drewfish
Copy link
Contributor

I tried this approach and found that it caused mojito to be slower. The interpretation is that _mojitRVs is so big that it causes a large GC walk which slows things down. (Or, having the large _mojitRVs causes other memory pressure, trigger more GC walks or something like that.)

I'll look at the details later.

@jarnoux
Copy link
Contributor Author

jarnoux commented Jul 23, 2013

I see, did you try stringifying the mojitRVs like you do for the cache?

@jarnoux
Copy link
Contributor Author

jarnoux commented Jul 23, 2013

also how much slower?

@drewfish
Copy link
Contributor

OK, I found the experiment I did earlier. It's from March 21st this year.

Here's what I did:

  • Ran a search-app-news search results page and captured the calls to store.expandInstanceForEnv().
  • Wrote a script that loads those calls and replays them, looking for GC events.
  • Tweaked the RS to do two types of changes: calculate _mojitoDetails at startup or on demand (AKA lazily), store the _mojitoDetails JSON.stringify()ed or as a raw datastructure.
  • Ran the script with the four experiments (2 x 2).

Alas, it only captured the GC events of the scripts, not the total runtime. Here are the results:

  • lazy/stringified - 9 GC events
  • lazy/raw - 9 GC events
  • startup/stringified - 5 GC events
  • startup/raw - 6 GC events

From this I surmised that keeping the source data (_appRVs and _mojitRVs) is a lot of data which causes enough memory pressure to cause more GC runs (and more data to walk on each run).

(I had written all these results into a trello card but alas I can't find it.)

@caridy
Copy link
Contributor

caridy commented Jul 24, 2013

@drewfish
Copy link
Contributor

Just moved the card to the right board, so it's now located at:
https://trello.com/c/Cz5hCgj6/256-search-perf-0-gc-profiling

@isao
Copy link
Contributor

isao commented Jul 24, 2013

this test would be interesting to repeat in node 0.10.x. Before then node would trigger GC "whenever the event loop was idle." But the behavior was removed because in practice, V8 was better at deciding when to GC. http://blog.nodejs.org/2013/03/11/node-v0-10-0-stable/ (search for "idle garbage collection")

I think the count of GC events would not mean GC was required more often, for pre 0.10 versions..

@drewfish
Copy link
Contributor

The .chosen for resource versions was added as part of pull #1108 (to fix issue #1107) so we should be careful to preserve that.

@@ -191,6 +192,10 @@ YUI.add('mojito-resource-store', function(Y, NAME) {
this._appPkg = null; // metadata about the applicaions's NPM package
this._specPaths = {}; // spec name: full path

// Let's try to be more efficient
this._smarterDetails = {}; // MojitType: selector: environment: non-stringified details
Copy link
Contributor

Choose a reason for hiding this comment

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

This structure is useful for the new algorithm, but should be called something else. It contains resource versions and is used by _resolveVersions() so perhaps it should be called _mojitDetailRVs.

this._appPkg = null; // metadata about the applicaions's NPM package
this._specPaths = {}; // spec name: full path

this._mojitDetails = {}; // mojitType: selector: environment: non-stringified details
this._mojitDetailsCache = {}; // mojitType+poslString+env : resolved resources
Copy link
Contributor

Choose a reason for hiding this comment

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

For both of these "environment" is really "affinity" no? If so it'd be clearer to say "affinity" instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

semantically, it is environment: a request has an environment and goes there to look for resources which have affinities, but are indexed by environment.

Copy link
Contributor

Choose a reason for hiding this comment

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

"Environment" is traditionally (in mojito code and docs) as things like "development", "production", "staging", etc. "Runtime" is used to describe the client vs. server. "Affinity" is used to describe which runtime a particular piece of code is intended for.

Unless there's a strongly compelling reason to use different semantics here, it is strongly recommended to stay with the existing semantics. (If we want to change it, we should change it everywhere: all code and documentation.) That work (and discussion with the whole mojito team about the value of that work) is beyond the scope of this pull request, so please stick to existing semantics. Consistency aids clarity.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh hmm... excepts a lot of places in the resource store "env"/"environment" is used for runtime (that is "client" or "server"). However, each resource has an "affinity" ("client", "server", or "common") for a particular "environment". If a field contains the affinity of a resource it should be labelled as "affinity".

@drewfish
Copy link
Contributor

Looks like travis build failed due to environmental issues (bad network) and not anything to do with code quality.

* @method resolveResourceVersions
* @return {nothing}
* @return {[type]} [description]
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmm... this @return is confusing. What is the intended return value of this resolveResourceVersions() method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nothing, dead code

/**
* Find a mojit details in the resource store at runtime
* @param {String} type the mojit type
* @param {String} env the environment: {'client', 'server', 'common'}
Copy link
Contributor

Choose a reason for hiding this comment

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

I think "environment" here is just "client" or "server".

@drewfish
Copy link
Contributor

I've confirmed that this (as of 8e6fc76) doesn't regress issue #1107.

@drewfish
Copy link
Contributor

+1

@drewfish
Copy link
Contributor

Looks like travis build failed due to environmental issues (bad network) and not anything to do with code quality.

@drewfish
Copy link
Contributor

Oh, still need test(s) to make sure that app.json resourceStore.lazyLoad (a) actually causes a lazy load, and (b) an app still works with lazy load.

@drewfish
Copy link
Contributor

One last task. Please add a note in the HISTORY.md file mentioning the new feature. You could add something like this in the "Features" section:

* There is a new `resourceStore.lazyResolve:true` option in `application.json`. 
Normally, the resource store at server start pre-calculates the details for all mojits for all contexts/selectors.
(It's optimized to only do this for dimensions/selectors that are actually used.)
By setting this new option the resource store will skip this calculation at srever start and instead do it at runtime as needed.
This might be a good option to use if you have a large number of dimensions defined in `dimensions.json` and a lot of selectors defined in `application.json`,
yet your app will only serve traffic from a subset of those.                    

@drewfish
Copy link
Contributor

Travis is having issues, but the union of builds for 3cf8896 and 91c6bf2 give full tests coverage and passing tests.

@drewfish
Copy link
Contributor

+1 :shipit:

@imalberto
Copy link
Contributor

lgtm +1

drewfish added a commit that referenced this pull request Aug 22, 2013
@drewfish drewfish merged commit 4b7da37 into YahooArchive:develop Aug 22, 2013
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants