Skip to content

Conversation

@butonic
Copy link
Member

@butonic butonic commented Oct 25, 2018

Today, the node api currently iterates over all storages when resolving a node by id to return all possible paths to the file. Even when it has found a path it continues to iterate over the other storages in order to find all nodes in the users tree.

That causes some overhead.

Actually, we never really use anything but the first node ... so this pr adds an optional parameter to only return the first node that is found. as you can see, quite a few places can profit.

Furthermore, the Jail Wrapper needs to intercept the IVersionedStorage calls, so it can adjust the paths correctly. However it should not implement the interface AFAICT because the wrapped storages might not actually implement versioning. I may get the logic in instanceOfStorage() wrong but this can be tested.

Finally, the Meta endpoint iterates over all possible storages, because it does not yet use the LazyRootFolder ...

All of this together significantly improves versions performance.

I won't start on the tests until I get a response on the approach. Especially, because I don't inject the UserFolder but fetch if from the $server.

@DeepDiver1975 did you intend the Meta endpoint to be able to access any fileid? then, limiting the versioning meta nodes to versions might not be the right approach. We might have to query the db table directly to immediately lookup storage and path ...

}

return $nodes[0];
return \array_shift($nodes);
Copy link
Member

Choose a reason for hiding this comment

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

Why? calling a built in function is more expensive then staying in the language

Copy link
Contributor

Choose a reason for hiding this comment

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

indeed, this would not only return the first element but also need to update the array

Copy link
Member Author

Choose a reason for hiding this comment

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

ack .... wanted to unify this and several places used this. will change to array access

* returns only the first node because we only really need the id anyway
*/
private function getNode() {
$folder = \OC::$server->getUserFolder();
Copy link
Member

Choose a reason for hiding this comment

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

please inject if possible - yes - my view should have been injected as well ....

* @return resource
* @since 10.0.9
*/
public function getContentOfVersion($internalPath, $versionId) {
Copy link
Member

Choose a reason for hiding this comment

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

funny ..... was that missed somehow?

@PVince81 PVince81 added this to the development milestone Oct 25, 2018
@DeepDiver1975
Copy link
Member

@butonic drone is red - please have a look as well - THX

@butonic butonic force-pushed the fix-versions-performance branch from a947244 to 88d9dff Compare October 26, 2018 09:34
@codecov
Copy link

codecov bot commented Oct 26, 2018

Codecov Report

Merging #33302 into master will increase coverage by 0.34%.
The diff coverage is 90.61%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master   #33302      +/-   ##
============================================
+ Coverage     64.42%   64.76%   +0.34%     
- Complexity    18320    18330      +10     
============================================
  Files          1197     1198       +1     
  Lines         69264    69382     +118     
  Branches       1276     1276              
============================================
+ Hits          44625    44938     +313     
+ Misses        24267    24072     -195     
  Partials        372      372
Flag Coverage Δ Complexity Δ
#javascript 52.98% <ø> (ø) 0 <ø> (ø) ⬇️
#phpunit 66.13% <90.61%> (+0.37%) 18330 <27> (+10) ⬆️
Impacted Files Coverage Δ Complexity Δ
...s/systemtags/tests/unit/activity/ExtensionTest.php 81.81% <ø> (ø) 3 <0> (?)
lib/private/Files/Config/CachedMountInfo.php 72.22% <0%> (+7.22%) 6 <0> (-1) ⬇️
lib/private/Files/Node/NonExistingFolder.php 4.28% <0%> (ø) 35 <1> (ø) ⬇️
lib/private/Files/Node/LazyRoot.php 6.55% <0%> (ø) 61 <1> (ø) ⬇️
apps/comments/appinfo/app.php 16% <0%> (ø) 0 <0> (ø) ⬇️
lib/private/Files/Node/AbstractFolder.php 87.87% <100%> (ø) 16 <1> (ø) ⬇️
apps/comments/tests/unit/ActivityListenerTest.php 100% <100%> (ø) 2 <2> (?)
lib/private/Files/Node/Folder.php 96.15% <100%> (+0.06%) 45 <6> (+1) ⬆️
apps/comments/lib/Activity/Listener.php 95.34% <100%> (+69.76%) 11 <0> (ø) ⬇️
apps/files_sharing/lib/SharedMount.php 93.51% <100%> (ø) 33 <0> (ø) ⬇️
... and 24 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 79813c6...15f00cc. Read the comment docs.

@butonic
Copy link
Member Author

butonic commented Oct 26, 2018

I used $node = $nodes[0] ?? null where it makes sense. checking drone after the build

@butonic
Copy link
Member Author

butonic commented Oct 26, 2018

I wanted to inject the UserFolder ... but .. besides that requiring a lot of changes ... urgh ... the meta endpoint is hopelessly inefficient. For every request to the versions endpoint

  1. the MetaRootNode does a node lookup by id
  2. the MetaVersionCollection does a lookup by id

As a result the same file id is looked up twice for each version AND twice for every thumbnail.

But there is no caching whatsoever ...

This calls for cacheception: #28166 With that all fileids would have been cached when listing the files while browsing to it ...

@DeepDiver1975
Copy link
Member

I used $node = $nodes[0] ?? null where it makes sense. checking drone after the build

this is okay for master (php7.1+) - but needs to be adapted in the backport

@butonic butonic force-pushed the fix-versions-performance branch 2 times, most recently from 0bed389 to 60a725f Compare October 26, 2018 18:07
Copy link
Contributor

@mrow4a mrow4a left a comment

Choose a reason for hiding this comment

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

My worry here is to also not break any IVersionedStorage functionality, meaning versioning for s3. I would also look into adding new function like getById() doing proper thing, instead of adding additional ambiguous flag.

* This restricts access to a subfolder of the wrapped storage with the subfolder becoming the root folder new storage
*/
class Jail extends Wrapper {
class Jail extends Wrapper /* implements IVersionedStorage */
Copy link
Contributor

Choose a reason for hiding this comment

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

So it sometimes should implement IVersionedStorage? Sounds dirty

Copy link
Contributor

Choose a reason for hiding this comment

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

this is the unfortunately reality of the wrapper pattern

@butonic butonic dismissed DeepDiver1975’s stale review October 29, 2018 13:16

drone is green now

@PVince81
Copy link
Contributor

@mrow4a please click "resolve conversation" after aknowledging @butonic's comments

@mrow4a
Copy link
Contributor

mrow4a commented Oct 31, 2018

@PVince81 done

@PVince81
Copy link
Contributor

PVince81 commented Nov 7, 2018

any update ? @butonic

@PVince81
Copy link
Contributor

@butonic please finish this or hand over

@butonic butonic force-pushed the fix-versions-performance branch from 60a725f to 703e2c3 Compare November 29, 2018 12:13
return null;
}
$nodes = $userNode->getParent()->getById($this->getRootId(), true);
return $nodes[0] ?? null;
Copy link
Contributor

Choose a reason for hiding this comment

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

note to self: will clash on backport due to PHP 5.6 compat

@PVince81
Copy link
Contributor

PVince81 commented Dec 6, 2018

went through with @tomneedham and it looks ok.

  • check code coverage report as the web page doesn't open locally...
  • merge
  • backport (beware of PHP 5.6 specifics)

@PVince81
Copy link
Contributor

So... I spent a few hours adding coverage where coverage was missing and it wasn't easy and my head hurts from too many mocks...

Let's hope this will bring the coverage to an acceptable level for merging.

See my comments on the remaining items, I'm not sure if covering those is worth it.

@PVince81
Copy link
Contributor

I'll need a review on the coverage commit: 5e6e445 @butonic @DeepDiver1975

@butonic
Copy link
Member Author

butonic commented Dec 10, 2018

@PVince81 omg I love you!

@PVince81 PVince81 force-pushed the fix-versions-performance branch from 5e6e445 to bf6ce2d Compare December 11, 2018 09:42
@PVince81
Copy link
Contributor

fixed code style issues and rebased

@PVince81 PVince81 force-pushed the fix-versions-performance branch from bf6ce2d to 244dfbb Compare December 11, 2018 13:14
@PVince81
Copy link
Contributor

Had to delete again the test for comments/appinfo/app.php uncovered code, because it's unreliable as its state depend on other tests. A proper way would be to first refactor app.php into an Application class and then test the latter. Something which I do not want to start in this PR as it would require regression testing things unrelated to what this PR fixes...

@PVince81 PVince81 force-pushed the fix-versions-performance branch from 244dfbb to 3d7f3b0 Compare December 11, 2018 14:09
@PVince81
Copy link
Contributor

I've added even more tests, some covering the issues in this PR, I hope this will make us reach the necessary threshold...

@PVince81
Copy link
Contributor

stable10: #33859

@PVince81
Copy link
Contributor

it's the second time this new test fails on object store:

1) OCA\SystemTags\Tests\unit\ActivityListenerTest::testActivityOnMapperEvent with data set #1 ('OCP\SystemTag\ISystemTagObjec...gnTags', 'unassign_tag')
OCP\Files\StorageNotAvailableException: 

/drone/src/lib/private/Files/Storage/Wrapper/Availability.php:76
/drone/src/lib/private/Files/Storage/Wrapper/Availability.php:239
/drone/src/lib/private/Files/Storage/Wrapper/Wrapper.php:221
/drone/src/lib/private/Files/View.php:1363
/drone/src/lib/private/Files/View.php:1409
/drone/src/lib/private/Share/Share.php:122
/drone/src/lib/public/Share.php:77
/drone/src/apps/systemtags/lib/Activity/Listener.php:170
/drone/src/apps/systemtags/tests/unit/ActivityListenerTest.php:195

Sadly there is a non-mockable static method in there which is why I had to use an actual user/storage. No idea why the storage would not be available for object store.

@PVince81
Copy link
Contributor

PVince81 commented Dec 11, 2018

but first debug the above problem...

@PVince81
Copy link
Contributor

PVince81 commented Dec 11, 2018

  • keep backport in sync

butonic and others added 2 commits December 12, 2018 15:41
Added more tests for meta node collection
Add tests for comments activity listener
Add activity listener test for system tags
Add test coverage for files' ActivityHelper
Test for legacy shares in fed share provider
@PVince81 PVince81 force-pushed the fix-versions-performance branch from 3d7f3b0 to 15f00cc Compare December 12, 2018 15:43
@PVince81
Copy link
Contributor

I managed to get something close to the object store issue. It turns out that Share::getUsersSharingFile() is calling initMountPoints() which itself would attempt to setup the object store in some inconsistent way. Instead of digging further I decided to mock the former method by wrapping it in an instance method in the activity Listener class, which is cleaner than trying to meddle with the setup.

The tests should all pass now.

@PVince81
Copy link
Contributor

all green, please review the tests now @DeepDiver1975 @butonic

@PVince81 PVince81 merged commit 1f99c6c into master Dec 13, 2018
@delete-merged-branch delete-merged-branch bot deleted the fix-versions-performance branch December 13, 2018 11:18
@PVince81
Copy link
Contributor

this now triggered unit test failures in storage-related apps:

will look into this...

@PVince81
Copy link
Contributor

ok, the issue is simply that the unit tests in those apps are using returnValueMap for the getById method, so I needed to add the extra false argument to the PHPUnit matcher.

@phil-davis
Copy link
Contributor

Backport stable10 is PR #33859

@lock lock bot locked as resolved and limited conversation to collaborators Apr 2, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants