-
Notifications
You must be signed in to change notification settings - Fork 138
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
Startup/Scan speed optimisation #409
Comments
It only scans public classes, so if you make other classes internal it should help. |
Thanks. If I specified all of the |
I don't think so, but you can try it :) |
Just completed an experiment moving all the Stores/Effects/Reducers to their own project and it didn't affect the scan time or Store Initializer. Which I think implies it wasn't due to the speed of having to scan the whole assembly, but actually the registration of the types themselves? These are the total stores I have: 43 Would this be what you would expect for these numbers? I'm not really sure where to go with it next, except to dive into the Fluxor code and understand where the time is lost? |
FYI, I tried using the Interestingly, if I run my startup code though a unit test, the timing is approx 50-100ms - so the issue is with the startup performance specifically in the browser/on wasm. |
It looks like the main culprit is the AssemblyScanSettings.FilterMethods method. I guess because the reflection is slow in Web Assembly. So probably the solution would require providing an alternative mechanism where I could make the service registrations without the need for reflection. I could then potentially use source generators to do the reflection to generate the registration code. I note that a similar approach was mentioned here. Anyone who uses a Wasm project and has a decent number of Types and Methods is likely going to see this degradation: which is not insignificant for a browser-based web app. |
If your assembly is purely store classes, then giving Fluxor a list of classes to scan isn't going to be any quicker, because it'll scan the same classes. Even a code gen that creates a list of methods to scan at compile time won't speed it up, because it'll still need to fetch the MethodInfo. The problem isn't that there are too many methods being scanned that aren't matches, but that there are so many that are matches. |
I've added a benchmark app. It seems that having 100 classes each with 1 reducer or effect method takes about 4 times the amount of time as it does to have a single class with 100 reducer or effect methods in it. I'm not sure if I am going to be able to do anything about this or not. At the moment I wrap reducer/effect methods with instances of [FluxorClasses(typeof(State1), typeof(Reducers1), typeof(Effects1), typeof(State2), etc); Then the reflection would only have to scan attributes on the assembly and be given all of them in one go. I don't know how much this will bloat the app. If it bloats the app too much then it will make the first ever download take longer. By the way, my timings were
1.5 seconds. |
Appreciate your input and time on this @mrpmorris. So that benchmarking app is running on Wasm? If so, I think those timings look comparable with my specific case.
Interesting. That could work - what would the bloat be from? Presumably the source generator creating the single, large, attribute would be in a separate assembly? Hard for me to assist with too many specifics as I'm not yet familiar with how Fluxor works internally - I only really have a high-level overview. I suppose I was thinking more radically about pre-creating what appear to be delegates which currently are created from reflection (using Given I have
Then I could declaratively define them:
The idea being that I should then be able create a source generator to do the reflection over my Features/Reducers/Effects and generate this declarative code (in fact, the logic for the source generator could live in Fluxor as a "helper" method which people could just create the "shell" of the source generator and just call this one method to have them generated). Appreciate this is a pretty different approach and I'm not familiar enough with all the different internal things to consider - attributes vs interface Features/Reducers/Effects, middleware etc. |
Reducers are actually written like this...
Effects are written in a similar way. When I encounter a Which means that if you use those attributes, there will always be a |
PS: Changing the code in the way I suggested changed a 1.6 MB DLL to 2.4 MB. I don't suppose that's so bad seeing as it gets downloaded and cached. Adding 1 second for a one-off download is better than waiting an extra 1 second each time the app starts I suppose. |
I've made some improvements in the Before : ScanAssemblies 31.47 ms Not fantastic, but an improvement. Please give it a try and let me know. |
Thanks @mrpmorris. I've tried my app against the Benchmarks branch (up to this commit). It may have had a small benefit - possibly making it more consistent - but I am still seeing approx 500ms for the startup. BTW, the benchmark app will measure the speed of your code relative to changes you make, but if you want to see the true speed you'll need to have a test WASM app with those test Features/Effects/Reducers. |
Also, if you're looking for any other micro-optimisations, |
@oatsoda I believe everything is passed as an array. Isn't that the case? |
Hi
In a large Blazor Wasm project, I'm seeing the startup scan taking 500-700ms on average, and then the Store Initialiser taking approx 200-300ms.
I have the
<Fluxor.Blazor.Web.StoreInitializer />
in myApp
component and I have the following startup registration:Presumably the large-ish assembly is the cause of this as it scans looking for all the registrations?
Is there anything I can do to optimise (aside from split the assembly up)? I notice there is a
TypesToScan
on the startup options - would this be more targeted? Is it just the Store types I need or is it all Store, Reducer and Effect types required?Any clues would be gratefully received!
The text was updated successfully, but these errors were encountered: