-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Update status periodically in smart terminals #2516
base: master
Are you sure you want to change the base?
Update status periodically in smart terminals #2516
Conversation
Respect for the low-level timer implementations! I'm actually working on a complete rewrite of Ninja's frontend that also fixes this. It does change a lot other stuff too though. In order to have this working without an environment variable and to fix a few issues with ninja's frontend that require breaking changes, my plan would be to do this in ninja 2.0. This new v2 would live alongside ninja v1 so that we can test stuff and experiment with ideas (you mentioned some in #2515 (comment)). The new v2 would be heavier and shipped as a second binary (see #1499). I will open a PR for that in the next few days. |
Interesting, would you care sharing your plans about this rewrite? This might have a very important impact on the Fuchsia fork, as we try very hard to stay close to upstream (i.e. I routinely rebase our stack of patchs on top of upstream Ninja to make them manageable without any merges). Since we are sharing our intentions: I didn't mention here is that for the Fuchsia fork, which also needs to implement a client/server mode, we refactored Ninja considerably to introduce an AsyncLoop abstraction which allows for waiting for different types of I/O events, and made I didn't want to introduce such level of complexity here, and I don't think upstream needs the I have also another branch to implement For the record, this has been used by my team for over a year, and has helped tremendously in identifying build commands that were bogging the build for no good reason, which led to several build performance improvements that would not have been possible with Ninja's current output. Which is why I think having such a feature in v1 would benefit Finally, we are working to introduce in our own fork a new Status sub-class to generate a Build Event Protocol stream. The BEP originated in Bazel but has become a format supported by many other build / CI analytics tools, it is a binary protobuf with a well-known fixed schema that provides rich information about what's happening during the build, is easy to convert to other formats (in particular into perfetto traces), and doesn't have the problems of JSON (slow encoding + bad non-UTF8 support). We do not expect upstream to accept such a feature though, but any change to how the frontend works is important for us. Surprisingly it doesn't add much code to the source tree. FWIW, the Android Ninja fork already has such a feature, except that they use their own custom protobuf schema, which includes far more metrics in the event stream, but we prefer to stick to BEP for compatibility. They have been using it for years and are very happy with it. Finally, I am a little wary about delivery. A major rewrite like the one you describe would take a large amount of work, and I didn't have the feeling that you have a lot of time to work on this. How many months / years are you forecasting for such work? I am really curious to know. |
Interesting! I think some kind of async event loop is a good idea. I've used Boost.Asio since I'm not good enough to implement that from scratch, but I guess Boost is banned at Google because NIH? I guess a hand-crafted solution is also much faster to compile, results in a smaller binary and can be tuned for performance. Those extensions you have in your Fuchsia branch are very interesting! That's why I dig the idea of a second v2 binary / folder: I could basically merge PRs that only touch v2 right away without much considerations, because it would be marked as "beta" and I don't have to worry about breaking something for existing users. These are the breaking changes I have in mind:
** IMPORTANT NOTE BEFORE PEOPLE START COMPLAINING: ** These are only ideas!
As that would be in parallel I would guess years? Because it's a second binary and the source would be in a For the past years there were many good PRs that added useful functionality but weren't merged because there's always the risk of breaking something. I want to change that while keeping the stable ninja v1. btw: My changes don't touch the existing code that much, nearly nothing at all. So you shouldn't have any problem rebasing the Fuchsia fork on top of them :) |
Allow the DoWork() method to return after a given timeout has expired. The new method returns a WorkResult value which is an enum that can take three values to indicate process completion, user interruption or that the timeout has expired.
Add a method to the abstract Status interface to refresh the status after some time has passed. Implement it properly in StatusPrinter. + Fix a bug in FormatProgressMessage() which ignored the value pass as argument (time_millis), and was using a member value instead (time_millis_). In practice, they were the same, but this is no longer true after this change.
bd66585
to
a8d5a9f
Compare
Use the new Subprocess::DoWork(int64_t) method to wait for at most one second before updating the status in the Ninja terminal. NOTE: A new output_test.py is added to check this feature, but since it is time-dependent, it tends to fail on Github CI so is disabled by default. It is possible to run it manually though on a lightly-loaded machine.
a8d5a9f
to
c36bdc2
Compare
Ensure that time-related
NINJA_STATUS
formatters such as%w
as properly updated when running in a smart terminal.This fixes issue #2515 by ensuring that Ninja can refresh its status even when only long commands are running.
Subprocess::DoWork()
to accept a timeout, and return an enum describing the exit condition.Status::Refresh()
andStatusPrinter::Refresh()
to update the status on smart terminals.RealCommandRunner
to callDoWork()
with a timeout, and callstatus->Refresh()
on expiration to trigger the update.The end result is that the status is properly updated in smart terminals when a single long command is invoked (see the example build plan in #2515).
NOTE: This adds a new regression test in
misc/output_test.py
, however, the test is flaky since it is time-dependent, i.e. it runs successfully on a lightly loaded laptop, but fails frequently on Github CI. Hence it is disabled by default but can be run manually during development.