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

Multiple requests per process #14953

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

@tomasz-grobelny
Copy link
Contributor

@tomasz-grobelny tomasz-grobelny commented Apr 3, 2019

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:

  1. Idea behind this change is to keep the current request processing pipeline intact (one process per request model) and at the same time allow for multiple requests per process model to be implemented by external applications. This model allows to skip significant number of per request processing (loading php code, loading Nextcloud applications) therefore reducing time needed to process single request.
  2. It is a followup to https://github.com/tomasz-grobelny/server/tree/reactphp_poc, stripped down to only the parts that are needed in the core of Nextcloud. All other code from that PoC can be implemented in a separate application. See also previous discussion here: #14131
  3. These changes should keep backward compatibility - if you think this is not the case then please speak up. It also does not introduce additional dependencies on Nextcloud environment.
  4. These changes by themselves do not improve performance, but allow external applications to implement performance improvement.
  5. These changes might not be complete - in particular all middlewares should be adapted to use HttpContext and not request injected through constructor. However, this is just enough to have a useful application that makes use of proposed changes.

Please review the changes and let me know if you are ok with them or you have some questions about any part.

@tomasz-grobelny tomasz-grobelny added this to the Nextcloud 17 milestone Apr 3, 2019
@tomasz-grobelny tomasz-grobelny force-pushed the multiple_requests_per_process branch 2 times, most recently from 2f43b09 to 705ad70 Apr 4, 2019
@tomasz-grobelny tomasz-grobelny requested review from blizzz and schiessle Apr 4, 2019
@tomasz-grobelny
Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny commented Apr 4, 2019

Any idea why there is no status for tests for quite some time now?

@nickvergessen
Copy link
Member

@nickvergessen nickvergessen commented Apr 4, 2019

We updated Drone and are currently checking the new config:
#14958

@nickvergessen
Copy link
Member

@nickvergessen nickvergessen commented Apr 5, 2019

You should be able to rebase on master now so tests run again.

@tomasz-grobelny tomasz-grobelny force-pushed the multiple_requests_per_process branch from 705ad70 to 6ab9fbd Apr 6, 2019
…ltiple requests per process approach for document previews and gallery previews

Signed-off-by: Tomasz Grobelny <tomasz@grobelny.net>
Signed-off-by: Tomasz Grobelny <tomasz@grobelny.net>
Signed-off-by: Tomasz Grobelny <tomasz@grobelny.net>
Signed-off-by: Tomasz Grobelny <tomasz@grobelny.net>
@tomasz-grobelny tomasz-grobelny force-pushed the multiple_requests_per_process branch from f5abd68 to 0532e40 Apr 10, 2019
@tomasz-grobelny
Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny commented Apr 10, 2019

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']);
Copy link
Member

@nickvergessen nickvergessen Apr 11, 2019

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?

Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny Apr 20, 2019

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).

Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny May 6, 2019

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() {
Copy link
Member

@nickvergessen nickvergessen Apr 11, 2019

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

Copy link
Member

@MorrisJobke MorrisJobke Apr 11, 2019

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.

Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny May 6, 2019

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?

lib/private/legacy/util.php Outdated Show resolved Hide resolved
@MorrisJobke
Copy link
Member

@MorrisJobke MorrisJobke commented Apr 11, 2019

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.

@tomasz-grobelny
Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny commented Apr 20, 2019

@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:

  1. You mention that PHP was designed for one request per process model. This is of course true and probably comes from the fact that when PHP was designed this was the dominant model (CGI and stuff). At the same time all major contemporary web application frameworks (ASP.NET MVC, Node.js, Java) use application server model. Also worth noting is that ReactPHP supports PHP 5.3 which is a framework released almost 10 years ago and ReactPHP is being developed since 2012. Therefore I think that application server model is proven and mature enough even in PHP to start considering it for use in Nextcloud.
  2. As for reducing bootstrap time: I simply do not believe it would happen ever. First of all, I do not currently see any significant effort at reducing this time. Second, given my profiling attempts, I see no quick wins. This means that a really significant amount of code would need to be reworked to reduce bootstrap time millisecond after millisecond after millisecond. Even if somebody would be willing to do it - it would cause huge amount of changes, each one introducing potential bugs and incompatibilities. IMO the effort is not worth it given the benefit we get from application server approach.
  3. Compatibility: I totally understand huge amount of deployed instances and the need to keep them all running on the same platform. That's why this code does nothing to break that platform compatibility. I believe the changes proposed are evolutionary (as you say: "we need to evolve slowly") yet at the same time give application developers new possibilities. Also note that these changes are relatively small so the overhead of keeping both models running is also relatively small.
  4. Also please note that it is not my attempt to have the application server model running for every single request - most of the time Nextcloud works really (or reasonably) well. I noticed there are a few key request endpoints that need performance improvements: serving image previews and WebDAV are the two that are most important for me. If other developers want to join in improving performance - great. If not - we still get benefit for at least one endpoint that people already complained about.
  5. As for potential bugs: every change brings the possibility of introducing bugs. In this approach I believe the most probable one is when someone uses some request based variable in middleware's constructor (therefore caching it). However, we do not write that many new middlewares. Secondly, if all existing middlewares are converted I thing the temptation to write the code incorrectly would be minimal. Thirdly, if we encounter any unexpected issues we could write tests to guard us against it happening again.

Do you think those changes could go into Nextcloud codebase given fixes to parts mentioned by @nickvergessen are provided?

nickvergessen and others added 2 commits Apr 20, 2019
Co-Authored-By: tomasz-grobelny <tomasz@grobelny.net>
Co-Authored-By: tomasz-grobelny <tomasz@grobelny.net>
@MorrisJobke
Copy link
Member

@MorrisJobke MorrisJobke commented May 2, 2019

@tomasz-grobelny Thanks for this detailed explanation. It makes in this way a lot more sense. 👍

@MorrisJobke
Copy link
Member

@MorrisJobke MorrisJobke commented May 6, 2019

@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?

@tomasz-grobelny
Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny commented May 23, 2019

@MorrisJobke, @nickvergessen - actually it seems we have two points that have open discussions:

  1. Changes in apps/provisioning_api/lib/AppInfo/Application.php - here it would be great to have input from @nickvergessen which way I should go: provide compatibility (if possible) or keep as in this PR?
  2. Changes in lib/private/Files/Filesystem.php - I can of course leave out the reset() method, but I am not sure where that leads us - either apps will be able to get the same functionality by some convoluted means (eg. reflection) therefore complicating code or they will not be able to achieve this so we miss the whole point of those changes.

@tomasz-grobelny
Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny commented May 29, 2019

@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.

@nachoparker
Copy link
Member

@nachoparker nachoparker commented Jun 29, 2019

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

@dgtlmoon
Copy link

@dgtlmoon dgtlmoon commented Nov 17, 2019

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)

@tomasz-grobelny
Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny commented Nov 18, 2019

@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).

@dgtlmoon
Copy link

@dgtlmoon dgtlmoon commented Nov 18, 2019

@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 microtime(true) at the start and end of the PHP stack to get a rough measurement)`

In other words 0.2/0.0026969 = 74.. so other frameworks are 74 times faster, in the same 200ms that Nextcloud is serving out one request, others are doing 74. (probably even faster with PHP7!)

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)

@dgtlmoon
Copy link

@dgtlmoon dgtlmoon commented Nov 18, 2019

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

<?php
$now=microtime(true);
header("Content-type: image/jpeg");
print file_get_contents("public/stuff/antique-vintage-old-exterior-lighting.jpg");
$time= microtime(true)-$now;
file_put_contents('/tmp/timing.txt', $time);

I get 0.00018405914306641 which is 0.2/0.00018405914306641 = 1086.60725389

So I am

  • Executing the PHP interpreter
  • Reading the file from disk into memory
  • Send a file to the webserver and browser, with headers

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?

@klausenbusk
Copy link

@klausenbusk klausenbusk commented Nov 18, 2019

I'm wondering if PHP 7.4 new preloading feature would make a difference?

@tomasz-grobelny
Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny commented Nov 18, 2019

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:

  1. If you reduce the RTT a thousand times from 200ms you are going to get 0,2ms - looks nice until you realized that you will not notice it because of browser processing time, network delay, actual processing logic, etc. Reducing RTT to 20ms would allow nextcloud to serve 50 images per second which should be enough for most installations.
  2. Most complexity in nextcloud (and any other fair sized system) is there for a reason. The reason is usually functionality. Therefore you cannot reduce complexity without reducing functionality. If you want only file access server then go for Samba - I am sure they are pretty well optimized for this scenario.

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.

@tomasz-grobelny
Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny commented Nov 18, 2019

@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.

@nachoparker
Copy link
Member

@nachoparker nachoparker commented Nov 19, 2019

@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

@tomasz-grobelny
Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny commented Nov 19, 2019

@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 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.

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.

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 :-)

@nickvergessen
Copy link
Member

@nickvergessen nickvergessen commented Dec 4, 2019

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.
E.g. in Nextcloud different users have different apps enabled. If an app is loaded, it will run, listen to hooks, etc. It will not check on each invocation whether it should still execute. So while this little change might work in your Nextcloud setup, it has an effect on the full Ecosystem of all the apps that are available for Nextcloud and there is no simple way to ensure that all apps still work as expected with a change like this.

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.

@tomasz-grobelny
Copy link
Contributor Author

@tomasz-grobelny tomasz-grobelny commented Dec 7, 2019

Just for the record:

We do value performance.

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...

The main problem is that this "little" code change is prone to break a lot of existing code.

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.

Many classes think they are set up once to deliver one request.

And this is precisely the problem I was trying to solve...

E.g. in Nextcloud different users have different apps enabled.

Ok, here I see a real technical/product issue. Now I see two options, maybe there are others:

  1. We can load the application server per user. While it might be less performant than loading the application only once, it still has the potential to be faster than the current approach at least in some setups.
  2. We can have a different definition of "enabled". I mean an application is loaded all the time, but it does not receive any hooks when it is disabled for particular user. This way the application will not be able to do anything if not enabled even if it is "loaded".

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.

I fully agree here. The problem is how do we come up with this "possible transition plan" if there is no discussion whatsoever?

@virtimus
Copy link

@virtimus virtimus commented May 25, 2020

Took a look inside a little.
About performance - I would go with joining all this css/js stuff to be gathered in one go.
As far as I understand - each reference generates bootstrap processing ?

<link rel="icon" href="/nextcloud/apps/theming/favicon/files?v=0">
--
  | <link rel="apple-touch-icon" href="/nextcloud/apps/theming/icon/files?v=0">
  | <link rel="mask-icon" sizes="any" href="/nextcloud/core/img/favicon-mask.svg" color="#0082c9">
  | <link rel="manifest" href="/nextcloud/apps/theming/manifest?v=0">
  | <link rel="stylesheet" href="/nextcloud/css/core/7681-c12d-server.css?v=32ef7dc01a3ffbcbbaf8fb9483f9bd03-55726334-0">
  | <link rel="stylesheet" href="/nextcloud/css/core/7681-c12d-css-variables.css?v=32ef7dc01a3ffbcbbaf8fb9483f9bd03-55726334-0">
  | <link rel="stylesheet" href="/nextcloud/apps/files_pdfviewer/css/style.css?v=6a154fe0-0">
  | <link rel="stylesheet" href="/nextcloud/css/notifications/783c-c12d-styles.css?v=32ef7dc01a3ffbcbbaf8fb9483f9bd03-783c3f18-0">
  | <link rel="stylesheet" href="/nextcloud/css/core/7681-c12d-results.css?v=32ef7dc01a3ffbcbbaf8fb9483f9bd03-55726334-0">
  | <link rel="stylesheet" href="/nextcloud/css/files/9eeb-c12d-merged.css?v=32ef7dc01a3ffbcbbaf8fb9483f9bd03-9eeb65bb-0">
  | <link rel="stylesheet" href="/nextcloud/css/text/d233-c12d-icons.css?v=32ef7dc01a3ffbcbbaf8fb9483f9bd03-d233662f-0">
  | <link rel="stylesheet" href="/nextcloud/apps/files_rightclick/css/app.css?v=5e585c9e-0">
  | <link rel="stylesheet" href="/nextcloud/css/files_sharing/c5f2-c12d-icons.css?v=32ef7dc01a3ffbcbbaf8fb9483f9bd03-c5f24915-0">
  | <link rel="stylesheet" href="/nextcloud/css/activity/6c1e-c12d-style.css?v=32ef7dc01a3ffbcbbaf8fb9483f9bd03-6c1e7ede-0">
  | <link rel="stylesheet" href="/nextcloud/css/spreed/6c9a-c12d-merged-files.css?v=32ef7dc01a3ffbcbbaf8fb9483f9bd03-6c9aa7b1-0">
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/core/js/dist/main.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/js/core/merged-template-prepend.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/core/search/js/search.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/core/js/backgroundjobs.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files_pdfviewer/js/previewplugin.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files_sharing/js/dist/main.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files_videoplayer/js/main.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/notifications/js/notifications.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/core/search/js/searchprovider.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/core/js/files/fileinfo.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/core/js/files/client.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/js/files/merged-index.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files_sharing/js/dist/collaboration.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/spreed/js/collections.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/text/js/files.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/federatedfilesharing/js/external.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files_rightclick/js/script.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files_rightclick/js/files.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/recommendations/js/main.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/core/js/dist/systemtags.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/systemtags/js/systemtags.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/comments/js/comments.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files_versions/js/files_versions.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files_sharing/js/dist/files_sharing.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files_sharing/js/dist/additionalScripts.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files/js/dist/sidebar.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files/js/fileinfomodel.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/js/activity/activity-sidebar.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files_sharing/js/dist/files_sharing_tab.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/spreed/js/talk-files-sidebar.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/spreed/js/talk-files-sidebar-loader.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/viewer/js/viewer.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/files_trashbin/js/files_trashbin.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=" defer src="/nextcloud/apps/firstrunwizard/js/about.js?v=55726334-0"></script>
  | <script nonce="NVpsRzd1V2xOb2o4K0Y3YlowN2FZdFZscVFPQ2tWTUVTYjRZL0NaRy94MD06dCs4SG5hTFJVY3kydVEyK1gzcXBFK2RXeEh2TnBSSkJJTmhidVI0Sngwdz0=">

@MorrisJobke
Copy link
Member

@MorrisJobke MorrisJobke commented May 25, 2020

About performance - I would go with joining all this css/js stuff to be gathered in one go.
As far as I understand - each reference generates bootstrap processing ?

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).

@MorrisJobke MorrisJobke removed their request for review Jul 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Performance
  
Awaiting triage
Linked issues

Successfully merging this pull request may close these issues.

None yet

9 participants