Skip to content

[native] Drop <chrono> from the timing code - #12550

Merged
simonrozsival merged 2 commits into
dev/simonrozsival/clr-timing-free-listfrom
dev/simonrozsival/clr-drop-chrono
Aug 28, 2026
Merged

[native] Drop <chrono> from the timing code#12550
simonrozsival merged 2 commits into
dev/simonrozsival/clr-timing-free-listfrom
dev/simonrozsival/clr-drop-chrono

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Part of the drop-libc++ work for CoreCLR.

FastTiming::get_time() has always read the clock with clock_gettime() directly — the comment above it even says we do that to avoid calling into libc++:

// We cheat a bit here, by avoiding a call to libc++ code that performs the same action.
// We can do it because we know our target platform.

std::chrono::steady_clock was then used only as the type tag of the chrono::time_point we wrapped the result in. So we were paying for <chrono> without using the clock it provides.

This PR stores timestamps as a plain uint64_t nanosecond count and removes <chrono> from the four files that included it. In mainthread-dso-loader.hh the include was entirely unused.

Sharing the interval formatting

Four places repeated the same seconds / milliseconds / nanoseconds-within-the-millisecond split, so they now share one helper:

struct time_interval
{
	unsigned long long seconds;
	unsigned long long milliseconds;
	unsigned long long nanoseconds;

	explicit constexpr time_interval (time_point interval) noexcept
		: seconds { interval / NANOSECONDS_PER_SECOND },
		  milliseconds { interval / NANOSECONDS_PER_MILLISECOND },
		  nanoseconds { interval % NANOSECONDS_PER_MILLISECOND }
	{}
};

The split reproduces chrono::duration_cast exactly, including the fact that the middle field is the total milliseconds rather than a remainder. The timing output is byte-for-byte unchanged, which matters because the format after the first colon is parsed by our performance measuring utilities.

I verified this rather than assuming it: a standalone harness compared the old chrono computation against time_interval over the nine interesting edge cases (0, 999999, 1000000, 1000001, 999999999, 1000000000, …, INT64_MAX) plus 2,000,000 random values — 2,000,009 checked, 0 mismatches.

CLOCK_MONOTONIC_RAW → CLOCK_MONOTONIC

We now read CLOCK_MONOTONIC, the clock steady_clock is specified to use, instead of CLOCK_MONOTONIC_RAW. The two differ only in that CLOCK_MONOTONIC is slewed by NTP, which is irrelevant at the granularity we measure.

Results

This does not remove any undefined libc++ symbols — the count stays at 59. <chrono> is header-only, so it never contributed any. What it does do is shrink the binary slightly and remove one more libc++ header from the build, which is a prerequisite for eventually building without libc++ headers at all:

before after delta
libnet-android.release.so 539,912 539,832 −80 B
timing-internal.cc.o 39,880 39,872 −8 B

(Measured against a real rebuild of the parent commit, not remembered numbers.)

Testing

  • CoreCLR and MonoVM both build clean (only the pre-existing format_managed_type_name warning).
  • time_interval verified against chrono over 2,000,009 inputs as described above.

Copilot AI lite review requested due to automatic review settings August 27, 2026 21:37
@simonrozsival simonrozsival added the drop-libcpp Work to remove the libc++ dependency from Android NativeAOT label Aug 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

Review tier: Lite
Findings: 1 Low severity

New issues introduced by this change (1)
Severity Finding
Low severity src/​native/​common/​include/​runtime-base/​timing-internal.hh — Suggestion (documentation): The comment above time_interval says “whole milliseconds”, which can…
What changed in this PR

This PR advances the CoreCLR “drop-libc++ headers” effort by removing <chrono> from native timing code paths and representing timing points/intervals as a plain uint64_t nanosecond count, while preserving the existing timing output format relied on by performance tooling.

Changes:

  • Replace std::chrono-tagged time points with uint64_t nanosecond timestamps (time_point) and compute durations via integer arithmetic.
  • Introduce a shared time_interval helper to centralize the seconds / total-milliseconds / nanoseconds-within-millisecond split used in multiple log formats.
  • Switch the timing clock source from CLOCK_MONOTONIC_RAW to CLOCK_MONOTONIC and remove an unused <chrono> include.
File Description
src/​native/​mono/​monodroid/​monodroid-glue.cc Use time_interval for JIT timing log formatting instead of std::chrono duration casts.
src/​native/​common/​runtime-base/​timing-internal.cc Remove <chrono> usage and format accumulated timing results via time_interval.
src/​native/​common/​include/​runtime-base/​timing.hh Use time_interval for managed timing sequence log formatting; initialize start/end as 0.
src/​native/​common/​include/​runtime-base/​timing-internal.hh Redefine time_point as uint64_t, add time_interval, remove <chrono>, and update get_time() implementation/clock.
src/​native/​common/​include/​runtime-base/​mainthread-dso-loader.hh Drop unused <chrono> include.

Comment thread src/native/common/include/runtime-base/timing-internal.hh Outdated
@simonrozsival
simonrozsival force-pushed the dev/simonrozsival/clr-drop-chrono branch 2 times, most recently from f47cca6 to 0d37fc3 Compare August 28, 2026 06:10
@simonrozsival
simonrozsival force-pushed the dev/simonrozsival/clr-drop-chrono branch 2 times, most recently from 864a3eb to ce91e4c Compare August 28, 2026 07:54
@simonrozsival
simonrozsival force-pushed the dev/simonrozsival/clr-drop-chrono branch from ce91e4c to 8941965 Compare August 28, 2026 08:47
@simonrozsival
simonrozsival force-pushed the dev/simonrozsival/clr-drop-chrono branch from 8941965 to bf9157b Compare August 28, 2026 08:56
@simonrozsival
simonrozsival force-pushed the dev/simonrozsival/clr-drop-chrono branch from bf9157b to 67df971 Compare August 28, 2026 09:51
@simonrozsival
simonrozsival force-pushed the dev/simonrozsival/clr-drop-chrono branch from 67df971 to f50052b Compare August 28, 2026 10:29
simonrozsival and others added 2 commits August 28, 2026 14:02
`FastTiming::get_time()` already read the clock with `clock_gettime()`;
`std::chrono::steady_clock` was only used as the type tag of the
`chrono::time_point` the result was wrapped in.  Store the timestamps as a
plain `uint64_t` nanosecond count instead and drop `<chrono>` from the four
files that included it (it was entirely unused in mainthread-dso-loader.hh).

All four places that formatted an interval repeated the same
seconds/milliseconds/nanoseconds split, so they now share a `time_interval`
helper.  The split is reproduced exactly as `chrono::duration_cast` computed
it, so the timing output is unchanged - this matters because the format after
the first colon is parsed by our performance measuring utilities.

Also read `CLOCK_MONOTONIC` rather than `CLOCK_MONOTONIC_RAW`, so that we keep
using the same clock `steady_clock` was documented to use.  The two differ only
in that `CLOCK_MONOTONIC` is slewed by NTP, which is irrelevant at the
granularity we measure.

This does not remove any undefined libc++ symbols - `<chrono>` is header only
- but it does shrink libnet-android.release.so by 80 bytes and removes one
more libc++ header from the build.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0a35a0db-502d-48c0-8468-e73b5dd0ab2e
…tals

Addresses review feedback. Both fields are totals for the whole interval and both
are printed, so `milliseconds` is not milliseconds-within-the-second. The output
format is consumed by performance measuring utilities, so spell this out to keep a
future change from "correcting" it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0a35a0db-502d-48c0-8468-e73b5dd0ab2e
@simonrozsival
simonrozsival force-pushed the dev/simonrozsival/clr-drop-chrono branch from f50052b to d350d84 Compare August 28, 2026 12:06
Base automatically changed from dev/simonrozsival/clr-replace-std-function to dev/simonrozsival/clr-timing-free-list August 28, 2026 12:42
@simonrozsival
simonrozsival merged commit d350d84 into main Aug 28, 2026
7 of 44 checks passed
@simonrozsival
simonrozsival deleted the dev/simonrozsival/clr-drop-chrono branch August 28, 2026 12:42
@simonrozsival

Copy link
Copy Markdown
Member Author

Consolidated into #12545 to reduce the depth of the #12546 stack.

No code changed: the commits from this PR are now part of #12545 unmodified, and the resulting tree is byte-identical. This PR sat directly on top of #12545 and touched the same files, so reviewing them together is easier than reviewing the same file across two intermediate states.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

drop-libcpp Work to remove the libc++ dependency from Android NativeAOT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants