-
-
Notifications
You must be signed in to change notification settings - Fork 605
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
Test environment for faster startup #3365
base: main
Are you sure you want to change the base?
Conversation
Thanks for the pull request, @EmberLightVFX! When I run _slow_startup.py or _fast_startup.py, I get this exception (after commenting out the
And when I run a simple script like from nicegui import ui
ui.label('Hello, world!')
ui.run(native=True) I get
So I'm a bit lost here. Can you or anyone else help to get this working? Thanks! |
@falkoschindler I most have accidentally pasted some arguments on the _open_window function. I removed them and it should work for you now. |
I'm still gettting a CancelledError when running either of both scripts:
And there are several undefined symbols like |
For some reason that causes an "asyncio.exceptions.CancelledError" error
I have no idea how my files got so scrambled... For some reason I had to comment out For me slow takes 13 seconds and fast takes 7 seconds to process. |
@EmberLightVFX You seem to be measuring the time until When I measure the time within a startup handler app.on_startup(lambda: print(time.time() - start)) there is no significant difference between the slow and the fast script. But I guess the measurement is still flawed, because the |
That's why I had the "on_startup" command close the UI with app.shutdown() for me as soon as it showed up, but it was broken for me with the lateat main commits. What you can do is to simply use your phones stopwatch and measure how long it takes from when you start the script till you see the UI. "Slow" will take around double the time to start. |
Ok, I can confirm that _fast_startup.py is indeed faster than _slow_startup.py. It takes only 1-2 seconds on my machine, so it's hard to measure. But the difference is clearly noticeable. I'm still struggling to understand why the location of window.py plays such a great role. What exactly is taking up so much time? Is it the import of webview? And how does it relate to window.py being located in a different package? |
By moving all code that the new thread needs to run into a new package/library there is no need to import anything from NiceGUI as it doesn't need anything from NiceGUI, thus not re-initializing anything in the new thread, thus cutting the startup time in half. |
Another solution could be to wrap all that root-code within a |
Very interesting... Unfortunately, we're currently focusing on some other issues that need to get done for the upcoming 2.0 release. The approach described in this PR doesn't feel quite right. Hopefully we can avoid splitting the NiceGUI package and still avoid re-loading everything. Maybe someone from the community likes to experiment with this branch and can come up with an idea how to speed up native mode more elegantly. |
Yeah splitting the package into two packages isn't ideal. |
We're still hoping for a solution without such an init call. And even that's impossible, the need for |
Got it! I'll try and figure something out! |
I've also been trying to find a workaround for this issue as I have some lengthy startup scripts and logic that I'd rather not run twice. A workaround I've found is to create a lock file after the first pass of the file, which can be used to block code execution on the second pass that occurs when native=True I'll admit I'm not too familiar with what's happening under the hood in niceui, but with the code snippet below everything appears to be working as intended. (which is a significantly reduced example of the actuall application I'm working on). This would obviously not work if reload=True, though some additional logic could resolve that. from nicegui import ui
from pathlib import Path
class test_ui():
def __init__(self, native: bool) -> None:
print("Initialising UI")
self.native = native
print(f"native = {self.native}")
self.lock_file = Path(__file__).resolve().parent / "app.lock"
if self.native:
if not self.lock_file.is_file():
print("Lock file not present!")
with open(self.lock_file, "w") as _:
pass
self.compose()
else:
print("lock file present!")
self.lock_file.unlink()
else:
self.compose()
def compose(self) -> None:
print("Composing UI")
ui.label("Hello World!")
ui.button("Ding!", on_click=self.on_ding)
def on_ding(self) -> None:
ui.notify("Dong!")
def run(self) -> None:
if (self.native and self.lock_file.is_file()) or not self.native:
print("Running UI")
ui.run(port= 1000, native=self.native, reload=False)
test_ui(True).run() |
This is a PR for a test environment for this issue: #3356
I couldn't get a correct NiceGUI dev-environment up and running but I hope this PR works for you or at least shows you the setup.