diff options
| author | Stefan Boberg <[email protected]> | 2025-03-12 14:48:46 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2025-03-12 14:48:46 +0100 |
| commit | cd128dd76526ed01c9a6c125b7ecddd9e3e08e57 (patch) | |
| tree | 62e1285564daefd49690a867bf76e54f23c8457b | |
| parent | fixes for log timestamps (#304) (diff) | |
| download | zen-cd128dd76526ed01c9a6c125b7ecddd9e3e08e57.tar.xz zen-cd128dd76526ed01c9a6c125b7ecddd9e3e08e57.zip | |
ProgressBar improvements (#305)
* changed ProgressBar so it doesn't use printf. printf by default is very slow on Windows due to weird buffering behaviour. During a 2 minute build download I profiled 35 CPU seconds inside printf
* changed so ProgressBar uses plain output mode if stdout is not a console/tty
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -rw-r--r-- | src/zen/zen.cpp | 43 | ||||
| -rw-r--r-- | src/zen/zen.h | 1 |
3 files changed, 44 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 25af743fe..febd32eb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ - Improvement: Reduced I/O usage during upload and download - Improvement: Faster block regeneration when uploading in response to PutBuild/FinalizeBuild - Improvement: More trace scopes for build upload operations + - Improvement: Progress bar automatically switches to plain mode when stdout is not a console + - Improvement: Progress bar is much more efficient on Windows (switched away from printf) - Bugfix: Ensure that temporary folder for Jupiter downloads exists during verify phase - Bugfix: Fixed crash during download when trying to write outside a file range - Bugfix: MacOS / Linux zen build download now works correctly diff --git a/src/zen/zen.cpp b/src/zen/zen.cpp index 0fcf9d871..9d0eab7dc 100644 --- a/src/zen/zen.cpp +++ b/src/zen/zen.cpp @@ -32,6 +32,7 @@ #include <zencore/scopeguard.h> #include <zencore/string.h> #include <zencore/trace.h> +#include <zencore/windows.h> #include <zenhttp/httpcommon.h> #include <zenutil/logging.h> #include <zenutil/zenserverprocess.h> @@ -56,6 +57,10 @@ ZEN_THIRD_PARTY_INCLUDES_END #include <zencore/memory/newdelete.h> +#ifndef ZEN_PLATFORM_WINDOWS +# include <unistd.h> +#endif + ////////////////////////////////////////////////////////////////////////// namespace zen { @@ -261,8 +266,22 @@ ZenCmdBase::ResolveTargetHostSpec(const std::string& InHostSpec) return ResolveTargetHostSpec(InHostSpec, /* out */ Dummy); } +static bool +IsStdoutTty() +{ +#if ZEN_PLATFORM_WINDOWS + static HANDLE hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE); + DWORD dwMode = 0; + static bool IsConsole = ::GetConsoleMode(hStdOut, &dwMode); + return IsConsole; +#else + return isatty(fileno(stdout)); +#endif +} + ProgressBar::ProgressBar(bool PlainProgress, bool ShowDetails) -: m_PlainProgress(PlainProgress) +: m_StdoutIsTty(IsStdoutTty()) +, m_PlainProgress(PlainProgress || !m_StdoutIsTty) , m_ShowDetails(ShowDetails) , m_LastUpdateMS(m_SW.GetElapsedTimeMs() - 10000) { @@ -323,7 +342,27 @@ ProgressBar::UpdateState(const State& NewState, bool DoLinebreak) ETA, NewState.Details.empty() ? "" : fmt::format(". {}", NewState.Details)); std::string::size_type EraseLength = m_LastOutputLength > Output.length() ? (m_LastOutputLength - Output.length()) : 0; - printf("%s%s%s", Output.c_str(), std::string(EraseLength, ' ').c_str(), DoLinebreak ? "\n" : ""); + + ExtendableStringBuilder<128> LineToPrint; + LineToPrint << Output << std::string(EraseLength, ' '); + if (DoLinebreak) + LineToPrint << "\n"; + +#if ZEN_PLATFORM_WINDOWS + static HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + + if (m_StdoutIsTty) + { + WriteConsoleA(hStdOut, LineToPrint.c_str(), (DWORD)LineToPrint.Size(), 0, 0); + } + else + { + ::WriteFile(hStdOut, (LPCVOID)LineToPrint.c_str(), (DWORD)LineToPrint.Size(), 0, 0); + } +#else + fwrite(LineToPrint.c_str(), 1, LineToPrint.Size(), stdout); +#endif + m_LastOutputLength = DoLinebreak ? 0 : Output.length(); m_State = NewState; } diff --git a/src/zen/zen.h b/src/zen/zen.h index 835c2b6ac..6765101db 100644 --- a/src/zen/zen.h +++ b/src/zen/zen.h @@ -94,6 +94,7 @@ public: bool HasActiveTask() const; private: + const bool m_StdoutIsTty = true; const bool m_PlainProgress; const bool m_ShowDetails; Stopwatch m_SW; |