-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Multiple requests per process #14953
Multiple requests per process #14953
Conversation
2f43b09
to
705ad70
Compare
Any idea why there is no status for tests for quite some time now? |
We updated Drone and are currently checking the new config: |
You should be able to rebase on master now so tests run again. |
705ad70
to
6ab9fbd
Compare
…ltiple requests per process approach for document previews and gallery previews Signed-off-by: Tomasz Grobelny <[email protected]>
Signed-off-by: Tomasz Grobelny <[email protected]>
Signed-off-by: Tomasz Grobelny <[email protected]>
Signed-off-by: Tomasz Grobelny <[email protected]>
f5abd68
to
0532e40
Compare
Tests should be more or less fixed - any potential failures are not related to my changes to my knowledge. Therefore PR is ready to be reviewed. |
@@ -54,7 +54,7 @@ public function __construct(array $urlParams = array()) { | |||
); | |||
}); | |||
$container->registerService('ProvisioningApiMiddleware', function(SimpleContainer $c) use ($server) { | |||
$user = $server->getUserManager()->get($c['UserId']); | |||
$user = $server->getUserManager()->get($server['UserId']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this required? So all middlewares should ge the user from server, instead of the container? what's the difference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes and no. This is required in the sense that otherwise tests failed. This resulted from moving registration of UserId from DIContainer to Server class (which is also a container). This in turn was needed to be able to replace one of session objects in external application. On the other hand I could try writing compatibility code ($this->registerService('UserId', ...)) that would make this specific change not required. I was thinking that explicitly querying specific container seems to be a hack anyway so I didn't pay too much attention to it.
Please let me know what is your preference (keep as is or add compatibility in DIContainer).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nickvergessen, any thoughts on this one? Should it be changed or can it stay as is?
@@ -213,6 +213,14 @@ class Filesystem { | |||
/** @var bool */ | |||
private static $logWarningWhenAddingStorageWrapper = true; | |||
|
|||
public static function reset() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this scares me a bit. I think a lot of apps keep their own "cache" and need to be made aware of a potential context/user switch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also a lot of the code that we currently use is actually building on that fact. There are properties in objects that cache given things for the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nickvergessen, @MorrisJobke: as per explanation below - do you think this is ok?
In general I like the overall idea, but then we should go for only that way of running Nextcloud. Either it should be an application server or a request based approach. Mixing those two in one code base just screams for horrible bugs that are super hard to find. Also maintaining both ways means a lot of effort on our side. Don't get me wrong, but I doubt that you will maintain all of this in parallel to our general pace of implementing and fixing stuff. I get that you want to improve the performance heavily by basically changing the stack Nextcloud is running on (mod_php/php-fpm vs a services that continuously runs via ReactPHP). We have a lot of instances out there that run with the first of them and they all then need to be migrated over somehow. Also this is something I highly doubt to be worth the effort. We should look into bootstrapping less on every request - this is how PHP was designed - bootstrap the whole thing per request. Thus that is the part where we need to improve. We simply bootstrap too much on every request and thus have those not perfect timings. Still I think that moving over to a complete new stack is the wrong approach here, because we need to evolve slowly and can't do too radical changes here, as there are a few hundreds of thousand instances out there that rely on us and how our stack looks like now. |
@MorrisJobke thanks a lot for your review. There are a few parts that I need more clarity on and I would like to provide more clarity from my side:
Do you think those changes could go into Nextcloud codebase given fixes to parts mentioned by @nickvergessen are provided? |
Co-Authored-By: tomasz-grobelny <[email protected]>
Co-Authored-By: tomasz-grobelny <[email protected]>
@tomasz-grobelny Thanks for this detailed explanation. It makes in this way a lot more sense. 👍 |
@tomasz-grobelny I guess the best way to get changes in is to split them a bit more up. Some general restructurings in here are totally fine, but where the comments are on are still not decided. So the best approach is to leave this here as it is now and take the changes without comments and create a new PR for them. Those will most likely be accepted. Then we can focus on the remaining items in here. Does that make sense for you as well? |
@MorrisJobke, @nickvergessen - actually it seems we have two points that have open discussions:
|
@MorrisJobke, @nickvergessen, any thoughts? Maybe instead of leaving out the reset() method it would make sense to provide some means of notification that the request context changed? And BTW, here you can have a look how application using those changes might look like: https://cloud.grobelny.net/s/aDFDzeqL2WadmRa This one speeds up file serving for my case by a factor of 5+ once it warms up. It is not finished by any means, but a strong PoC. |
This would be no small change, so would need to be planned out very carefully, but in my opinion will have to happen sooner or later to achieve decent performance. +1 |
I have a feeling that this issue is trying to address the symptom rather than the cause, I don't know of any other web interface that is so slow at passing EXISTING prebuilt images to the browser, most of the damage is happening at the bootstrap sequence, cross linking here to #13709 (comment) |
@dgtlmoon, I long forgot about this PR of mine, but I cannot agree that it addresses "the symptom rather than the cause". As you mentioned the reason for extremely slow response time even for trivial operations is that for each request all of Nextcloud needs to be bootstrapped (DI, all apps, handlers - a ton of tiny code pieces). My PR allows to execute the bootstrap sequence only once and then serve multiple requests (eg. multiple thumbnails) from a single backend process. This is not "custom code" as you mentioned in other comment, but makes use of ReactPHP which uses an event loop approach tested in many other frameworks. I am ready to discuss the proposed solution and possibly some other solutions that might appear, even though I lost interest in Nextcloud recently mainly because of response times (both server response and human response to my improvement attempts). |
@tomasz-grobelny thanks for the honest reply, yeah I can say that after a week of poking with nextcloud it feels to me like there's some very sick/wrong with this project and project management as a whole, I see a lot of pull requests that dont improve basic functionality but are aimed at some perhaps client-driven functionality, virtually no helpful technical feedback and a really overly complex codebase that looks like it was written by one guy in a huge outpouring of code in a few months 6 years ago. I've been into coding opensource for just on 20 years now, and I know red flags when I see them. back to the issue - I had a quick run with SabreDAV project this morning, setup a basic HTTP server and sent/received files from it, the docker image I used runs PHP5 (!), even so, I was able to send and retrieve files via webdav within 0.0026969 seconds.. (used In other words What I'm getting at - this is a lot of work to speed up nextcloud, but is it going to serve 74 images in the same time? when other frameworks do this without this added complexity? (in my opinion, the best way to solve a problem is to remove complexity and have a hard look at the underlying performance) |
By the way, on the same machine that was taking 200ms to serve a thumbnail via Nextcloud, if I try this test/benchmark code - which is the ultimate easy best/fastest case and does not take into consideration access control etc
I get So I am
and still it's 1,086 (One thousand and eighty six) times faster than using Nextcloud... I don't think that having multiple requests in a single nextcloud request (this PR) is going to come anywhere near it, the only way forwards is to reduce complexity and simplify how the parts connect together. I havent looked but I'm willing to bet that this PR adds MORE code to the system right? |
I'm wondering if PHP 7.4 new preloading feature would make a difference? |
I wouldn't say this PR adds much code - it mostly shuffles code around to make a clear distinction between bootstrapping phase and request processing phase. With the current processing model each HTTP request has to execute both the bootstrapping code (which takes eg. 180ms) and actual request processing (which takes eg. 20ms). This PR makes it possible to start a process that executes bootstrapping code and then serve multiple requests. This means that for each HTTP request we execute only per request piece of code (20ms). This would be the first step only - once this is done you can focus your efforts on this 20ms piece of code and maybe optimize it and not even look into this 180ms piece of code which is executed only once either way. About your numbers: I don't think the comparison you are making is fair. For two main reasons:
I believe there is no point being excited about potential 1000 times speed improvement based on dubious assumptions when you can have 5 times speed improvement even in very limited number of scenarios (preview generation), but with no loss in functionality and only very limited changes to the codebase. |
@klausenbusk, in theory yes, it would help. The problem is separating what you preload. If you have no clear distinction between bootstrapping and request processing then you will not be able to preload much. To be more specific to this PR: consider loading middlewares - if middleware classes are instantiated with request then you cannot preload them. However, if they are instantiated without any reference to request and request is passed as parameter to dispatch call then we can preload all instantiated middleware classes. See lib/private/AppFramework/Http/Dispatcher.php changes from this PR. So preloading might be a good mechanism, but someone needs to make use of it. |
@tomasz-grobelny I tried to bring some visibility to your idea, I am not sure if you read this https://ownyourbits.com/2019/10/16/a-new-architecture-for-nextcloud/ I did it in hope your PRs received some more love, unsuccessfully so far it seems. Sad to see that you have given up on this but I don't blame you. Cheers |
I wasn't aware of it, very nice piece of writing :-) One note is that this PR does not have any ReactPHP specific code - it only separates bootstrapping from request processing to some extent (not even fully) allowing ReactPHP to be used to speed up processing of some requests (tested on thumbnails). Might be those same changes would allow using the preloading feature or appserver.io.
Hopefully with enough voices like yours, mine, @dgtlmoon's, @mvogt1's and others' (in particular here: nextcloud/gallery#458) Nextcloud devs will start treating performance as something important. Maybe in a year or two from now :-) |
Just for the record: We do value performance. The main problem is that this "little" code change is prone to break a lot of existing code. Many classes think they are set up once to deliver one request. But with this change they can not load data for a user once only, if later on they are used for a different user, etc. It is always quick to find something that solves 1 case, but we have to make sure the full bigger picture remains intact. It needs to be fully thought through and come up with a good and possible transition plan, that helps apps to be prepared for those changes in the future. |
Nice to read that. So when exactly during last 8 months did it change? Last week? (Sorry for the irony here, but I just could not resist.) But to the point...
Define "a lot". With this PR I changed interface for middlewares. So how many third-party middlewares are you actually aware of? Maybe we should contact their authors and involve them in the discussion? I believe breaking changes do happen in nextcloud once in a while. Yes, this change does break compatibility, but still IMO this should not be a single reason not to incorporate it. Or at least discuss it from technical and organizational point of view.
And this is precisely the problem I was trying to solve...
Ok, here I see a real technical/product issue. Now I see two options, maybe there are others:
I fully agree here. The problem is how do we come up with this "possible transition plan" if there is no discussion whatsoever? |
Took a look inside a little.
|
Browser caching is far more efficient. Otherwise other pages that only load one asset more or less would get a complete new bundle. And as those are all per app, the whole process can't be done on build time, but on request time due to the option to enabled/disabled apps. Thus we went for the approach to get as few assets per app (one CSS and one JS per app would be perfect of course). |
As this sounds like a nice feature, the requests for this are quite low. Thus I will close this ticket for now. This does not mean we don't want this feature, but it is simply not on our roadmap for the near future. People that seemed interested in that feature, I do see you. By no mean this is a gesture of dismissal in the grand scheme of things. But it seems quite obvious that there is very little activity for this in the last 3 years. Both from external reviews and internal Nextcloud reviews. If someone wants to re-open and solve the various conflicts, I would encourage opening a thread to discuss the technicalities that seemed to arise on the previous comments Thanks for the interest in Nextcloud and the effort put into this! 🙇 |
Changes required to allow third-party Nextcloud application to use multiple requests per process approach for document previews and gallery previews.
Key points about this pull request:
Please review the changes and let me know if you are ok with them or you have some questions about any part.