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

FIX: Performance optimisation for draft pages in treeview #181

Merged
merged 4 commits into from
Sep 21, 2018
Merged

FIX: Performance optimisation for draft pages in treeview #181

merged 4 commits into from
Sep 21, 2018

Conversation

sminnee
Copy link
Member

@sminnee sminnee commented Sep 17, 2018

When draft pages are rendered in the treeview, an attempt to look up
their live Version # is made. This leads to a cache miss and a
subsequent query for each record.

This change marks a cache as “complete” when all records of a given
stage are pre-cached. This will suppress the record-specific query
in the case of a cache miss.

Parent issue

When draft pages are rendered in the treeview, an attempt to look up
their live Version # is made. This leads to a cache miss and a
subsequent query for each record.

This change marks a cache as “complete” when all records of a given
stage are pre-cached. This will suppress the record-specific query
in the case of a cache miss.
@chillu
Copy link
Member

chillu commented Sep 17, 2018

Note that unless this fix is considered "critical" and rebased against the 1.2 branch, it won't be available for the targeted project (since they're trying to avoid a 4.3 recipe upgrade). I'd say it's non-critical, and has a moderate chance of functional regressions, so it's targeted correctly with 1. But that won't help the targeted project which it has been written for.

@maxime-rainville
Copy link
Contributor

I tested on our key project. It doesn't look like it makes much of a difference. I've compared building the treeview for the North Island page in black fire.

This is comparing the original version to the patched version.

image

We save 245 queries ( out of 2 381 ) and improve performance time by about 2.2%.

@chillu I can review this in greater details if you want, but it's not going to resolve our treeview issues for our key project.

@chillu
Copy link
Member

chillu commented Sep 18, 2018

Assuming this is the PR which reduces number of queries, it'll have a far bigger impact in SSP with a remote database than on your local. No need to set up Blackfire on SSP for this, but I think it's still worthwhile to get peer reviewed and merged this week.

@sminnee
Copy link
Member Author

sminnee commented Sep 18, 2018

Note that this requires unpublished draft page to have much of an effect.

Copy link
Contributor

@maxime-rainville maxime-rainville left a comment

Choose a reason for hiding this comment

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

Looks good and it should be functionally equivalent.

I've added some unit test to improve code coverage.

$this->assertNull(
Versioned::get_versionnumber_by_stage(VersionedTest\TestObject::class, Versioned::DRAFT, 888, true),
'get_versionnumber_by_stage should return null when fetching a version number for unexisting object with prepopulate_versionnumber_caching'
);
Copy link
Contributor

Choose a reason for hiding this comment

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

This test is actually six or seven different tests, or different scenarios for one test. Can you please split it up or use a data provider?

Copy link
Contributor

Choose a reason for hiding this comment

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

What about I split it in 4:

  • 1 for getting an existing version number that is uncached and cached (2 assertions)
  • 1 for getting an non-existing version number without the cache flag (1 assertion)
  • 1 for getting an non-existing version number that is uncached and cached (2 assertions)
  • 1 for getting an non-existing version number after a call to prepopulate_versionnumber_cache (1 assertion)

I'd rather avoid splitting the uncached/cached assertions.

Copy link
Member

Choose a reason for hiding this comment

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

Given Robbie is only available in EU timezone, I'll say: Yep, that sounds good ;)

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry yeah sounds good

Copy link
Contributor

@ScopeyNZ ScopeyNZ Sep 20, 2018

Choose a reason for hiding this comment

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

Sounds fine to me too, although you might find it easier with 6 separate tests using a data provider. And it's probably worth it if you think each of the assertions could fail in isolation.

Copy link
Contributor

Choose a reason for hiding this comment

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

I've switched to using a data provider and use a more thorough parameter coverage. I've moved the logic to a separate file because I need to have some setUp and setUpBeforeClass customisation.

The new tests actually found a bug, so I fix that as well.

Copy link
Member

Choose a reason for hiding this comment

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

Heh its funny, I've just commented on how unreadable the data provider refactor made this code ;) But I'd say it's good enough to merge

Move VersionedNumber caching to their own test suite and tweak
them to use a data provider. Also, fix a bug when trying to bypass
the completed cache and fetch an non existing version number.
Copy link
Contributor

@tractorcow tractorcow left a comment

Choose a reason for hiding this comment

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

Smart idea good job.

if ($cache) {
if (isset(self::$cache_versionnumber[$baseClass][$stage][$id])) {
return self::$cache_versionnumber[$baseClass][$stage][$id] ?: null;
} elseif (isset(self::$cache_versionnumber[$baseClass][$stage]['_complete'])) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This can technically be just an if as you're returning in the preceding if statement. Not a blocker though - super super minor.

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, I'll keep it as-is just to make it clear the second bit will only run if the first if statement is false.

@sminnee
Copy link
Member Author

sminnee commented Sep 21, 2018

OK this looks like we've addressed Robbie's feedback. Since I wrote this does @chillu want to merge?


public function cacheDataProvider()
{
return [
Copy link
Member

Choose a reason for hiding this comment

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

As a sidenote, I find that data providers should only be used if the data within them is pretty self explanatory. If you find yourself going back and forth between the provider and the implementation (like I'm doing in this case), it's not helping readability. And in unit tests, I think readability overrules DRY principles.

Copy link
Contributor

Choose a reason for hiding this comment

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

@robbieaverill @chillu You guys are tough customers to please 😉

I'll keep it in mind for the next time.

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.

6 participants