Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
bc1a566
Prepare for merging from rust-lang/rust
Feb 17, 2026
d58d3e2
Merge ref '3c9faa0d037b' from rust-lang/rust
Feb 17, 2026
b3b48e5
Merge pull request #4861 from rust-lang/rustup-2026-02-17
oli-obk Feb 17, 2026
7f17343
Prepare for merging from rust-lang/rust
Feb 18, 2026
61065bb
Merge ref '8387095803f2' from rust-lang/rust
Feb 18, 2026
c1e4c33
Merge pull request #4864 from rust-lang/rustup-2026-02-18
RalfJung Feb 18, 2026
c57ecb0
Prepare for merging from rust-lang/rust
Feb 19, 2026
9437c83
Merge ref 'e0cb264b8145' from rust-lang/rust
Feb 19, 2026
8b03e83
fix genmc build
RalfJung Feb 19, 2026
d4b4ba8
Merge pull request #4865 from rust-lang/rustup-2026-02-19
RalfJung Feb 19, 2026
054d4af
Print a warning when trying to open a file in `/proc`
y1lan Feb 13, 2026
220d514
clean up path check
RalfJung Feb 21, 2026
1650751
Merge pull request #4857 from y1lan/warning_of_openning_proc_files
RalfJung Feb 21, 2026
e3062fa
Avoid keeping ThreadData borrowed while formatting tracing arguments
Stypox Feb 16, 2026
041e3a5
Remove RDTSC timer and always rely on Instant instead
Stypox Feb 16, 2026
b0b2e8c
Update documentation for tracing
Stypox Feb 16, 2026
e077016
Merge pull request #4860 from Stypox/fix-nested-tracing
RalfJung Feb 21, 2026
7be6269
Fix typo in tracing.md for `tracing_separate_thread`
willschlitzer Feb 22, 2026
4a2f129
Prepare for merging from rust-lang/rust
Feb 22, 2026
40289de
Merge ref '5fb2ff8611e5' from rust-lang/rust
Feb 22, 2026
20de36c
Merge pull request #4866 from willschlitzer/patch-1
RalfJung Feb 22, 2026
3607191
register Miri-specific symbols with the interner
RalfJung Feb 22, 2026
361416e
Merge pull request #4867 from rust-lang/rustup-2026-02-22
RalfJung Feb 22, 2026
e7e512d
Prepare for merging from rust-lang/rust
Feb 23, 2026
93e3234
Merge ref 'c78a29473a68' from rust-lang/rust
Feb 23, 2026
ca026f5
Merge pull request #4869 from rust-lang/rustup-2026-02-23
RalfJung Feb 23, 2026
7ed7b2b
Prepare for merging from rust-lang/rust
RalfJung Feb 24, 2026
4c14efb
Merge ref 'b3869b94cd1e' from rust-lang/rust
RalfJung Feb 24, 2026
4ab624f
Merge pull request #4870 from RalfJung/rustup
RalfJung Feb 24, 2026
2e17c9b
remove FIXME about size of Pointer type
RalfJung Feb 24, 2026
b6c1924
Merge pull request #4872 from RalfJung/ptr-size-comment
RalfJung Feb 25, 2026
d398074
Start socket shim
WhySoBad Feb 22, 2026
e4d35f5
Merge pull request #4868 from WhySoBad/network-socket-start
RalfJung Feb 26, 2026
6d271ba
Prepare for merging from rust-lang/rust
RalfJung Feb 26, 2026
8ebf937
Merge ref 'bb779a91568a' from rust-lang/rust
RalfJung Feb 26, 2026
470706d
silence clippy lint that makes code harder to read
RalfJung Feb 26, 2026
b8d5538
add test for deallocating partially-interior-mutable ref
RalfJung Feb 26, 2026
7ca67a4
Merge pull request #4874 from RalfJung/rustup
RalfJung Feb 26, 2026
3c492b4
Merge pull request #4875 from RalfJung/cell-dealloc-test
RalfJung Feb 26, 2026
7b8534e
Prepare for merging from rust-lang/rust
RalfJung Feb 28, 2026
c64335d
Merge ref 'ba1567989ee7' from rust-lang/rust
RalfJung Feb 28, 2026
1e25d52
Merge pull request #4878 from RalfJung/rustup
RalfJung Feb 28, 2026
a49c083
native-lib: better organize fn ptr tests
RalfJung Mar 1, 2026
71f4b75
native-lib: also test fn ptrs that are instances of generics
RalfJung Mar 1, 2026
1472b9f
Merge pull request #4880 from RalfJung/native-lib-fnptr
RalfJung Mar 1, 2026
a36fc5c
FCNTL F_SETFL Ignore creation flags
MousseARaser06 Feb 1, 2026
7dc80de
use ignorelist instead of allowlist for file flags
RalfJung Mar 1, 2026
0500cdc
Merge pull request #4881 from RalfJung/setfl
RalfJung Mar 1, 2026
b3434a2
Prepare for merging from rust-lang/rust
Mar 4, 2026
12dbc5e
Merge ref 'd933cf483edf' from rust-lang/rust
Mar 4, 2026
a512d62
Merge pull request #4884 from rust-lang/rustup-2026-03-04
oli-obk Mar 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/tools/miri/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ you can visualize in [Perfetto](https://ui.perfetto.dev/). For example:
MIRI_TRACING=1 ./miri run --features=tracing tests/pass/hello.rs
```

See [doc/tracing.md](./doc/tracing.md) for more information.

### UI testing

We use ui-testing in Miri, meaning we generate `.stderr` and `.stdout` files for the output
Expand Down
12 changes: 9 additions & 3 deletions src/tools/miri/doc/tracing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

Miri can be traced to understand how much time is spent in its various components (e.g. borrow tracker, data race checker, etc.). When tracing is enabled, running Miri will create a `.json` trace file that can be opened and analyzed in [Perfetto](https://ui.perfetto.dev/). For any questions regarding this documentation you may contact [Stypox](https://rust-lang.zulipchat.com/#narrow/dm/627563-Stypox) on Zulip.

> [!WARNING]
> Tracing in Miri at the moment is broken due to two bugs in tracing libraries: https://github.com/tokio-rs/tracing/pull/3392 and https://github.com/davidbarsky/tracing-tree/issues/93. Also see https://github.com/rust-lang/miri/issues/4752.

## Obtaining a trace file

### From the Miri codebase
Expand Down Expand Up @@ -240,7 +243,7 @@ let _trace = enter_trace_span!(M, "borrow_tracker", borrow_tracker = "on_stack_p

### `tracing_separate_thread` parameter

Miri saves traces using the the `tracing_chrome` `tracing::Layer` so that they can be visualized in Perfetto. To instruct `tracing_chrome` to put some spans on a separate trace thread/line than other spans when viewed in Perfetto, you can pass `tracing_separate_thread = tracing::field::Empty` to the tracing macros. This is useful to separate out spans which just indicate the current step or program frame being processed by the interpreter. As explained in [The timeline](#the-timeline), those spans end up under the "Global Legacy Events" track. You should use a value of `tracing::field::Empty` so that other tracing layers (e.g. the logger) will ignore the `tracing_separate_thread` field. For example:
Miri saves traces using the `tracing_chrome` `tracing::Layer` so that they can be visualized in Perfetto. To instruct `tracing_chrome` to put some spans on a separate trace thread/line than other spans when viewed in Perfetto, you can pass `tracing_separate_thread = tracing::field::Empty` to the tracing macros. This is useful to separate out spans which just indicate the current step or program frame being processed by the interpreter. As explained in [The timeline](#the-timeline), those spans end up under the "Global Legacy Events" track. You should use a value of `tracing::field::Empty` so that other tracing layers (e.g. the logger) will ignore the `tracing_separate_thread` field. For example:
```rust
let _trace = enter_trace_span!(M, step::eval_statement, tracing_separate_thread = tracing::field::Empty);
```
Expand Down Expand Up @@ -277,9 +280,12 @@ So the solution was to copy-paste [the only file](https://github.com/thoren-d/tr

### Time measurements

tracing-chrome originally used `std::time::Instant` to measure time, however on some x86/x86_64 Linux systems it might be unbearably slow since the underlying system call (`clock_gettime`) would take ≈1.3µs. Read more [here](https://btorpey.github.io/blog/2014/02/18/clock-sources-in-linux/) about how the Linux kernel chooses the clock source.
tracing-chrome uses `std::time::Instant` to measure time. On most modern systems this is ok, since the underlying system call (`clock_gettime`) uses very fast hardware counters (e.g. `tsc`) and has a latency of ≈16ns.

On some x86/x86_64 Linux systems, however, `tsc` is not "reliable" and the system thus relies on other timers, e.g. `hpet` which takes ≈1.3µs. Read [here](https://btorpey.github.io/blog/2014/02/18/clock-sources-in-linux/) how the Linux kernel chooses the clock source, and how to check if your system is using `tsc`. If it doesn't use `tsc`, then expect most of the trace time being spent in time measurements, which degrades traces' usefulness... See [here](https://github.com/rust-lang/miri/issues/4563) for some discussion.

Therefore, on x86/x86_64 Linux systems with a CPU that has an invariant TSC counter, we read from that instead to measure time, which takes only ≈13ns. There are unfortunately a lot of caveats to this approach though, as explained [in the code](https://github.com/rust-lang/miri/blob/master/src/bin/log/tracing_chrome_instant.rs) and [in the PR](https://github.com/rust-lang/miri/pull/4524). The most impactful one is that: every thread spawned in Miri that wants to trace something (which requires measuring time) needs to pin itself to a single CPU core (using `sched_setaffinity`).
> [!WARNING]
> A (somewhat risky) workaround is to add `tsc=reliable clocksource=tsc hpet=disable` to the kernel boot parameters, which forces it to use `tsc` even if it is unreliable. But this may render the system unstable, so try it at your own risk!

## Other useful stuff

Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7bee525095c0872e87c038c412c781b9bbb3f5dc
d933cf483edf1605142ac6899ff32536c0ad8b22
6 changes: 5 additions & 1 deletion src/tools/miri/src/alloc_addresses/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
if let Some(GlobalAlloc::Function { instance, .. }) =
this.tcx.try_get_global_alloc(alloc_id)
{
let fn_sig = this.tcx.fn_sig(instance.def_id()).skip_binder().skip_binder();
let fn_sig = this.tcx.instantiate_bound_regions_with_erased(
this.tcx
.fn_sig(instance.def_id())
.instantiate(*this.tcx, instance.args),
);
let fn_ptr = crate::shims::native_lib::build_libffi_closure(this, fn_sig)?;

#[expect(
Expand Down
1 change: 0 additions & 1 deletion src/tools/miri/src/bin/log/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
pub mod setup;
mod tracing_chrome;
mod tracing_chrome_instant;
61 changes: 39 additions & 22 deletions src/tools/miri/src/bin/log/tracing_chrome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@ use std::{
thread::JoinHandle,
};

use crate::log::tracing_chrome_instant::TracingChromeInstant;

/// Contains thread-local data for threads that send tracing spans or events.
#[derive(Clone)]
struct ThreadData {
/// A unique ID for this thread, will populate "tid" field in the output trace file.
tid: usize,
Expand All @@ -61,7 +60,7 @@ struct ThreadData {
out: Sender<Message>,
/// The instant in time this thread was started. All events happening on this thread will be
/// saved to the trace file with a timestamp (the "ts" field) measured relative to this instant.
start: TracingChromeInstant,
start: std::time::Instant,
}

thread_local! {
Expand Down Expand Up @@ -562,28 +561,46 @@ where
#[inline(always)]
fn with_elapsed_micros_subtracting_tracing(&self, f: impl Fn(f64, usize, &Sender<Message>)) {
THREAD_DATA.with(|value| {
let mut thread_data = value.borrow_mut();
let (ThreadData { tid, out, start }, new_thread) = match thread_data.as_mut() {
Some(thread_data) => (thread_data, false),
None => {
let tid = self.max_tid.fetch_add(1, Ordering::SeqCst);
let out = self.out.lock().unwrap().clone();
let start = TracingChromeInstant::setup_for_thread_and_start(tid);
*thread_data = Some(ThreadData { tid, out, start });
(thread_data.as_mut().unwrap(), true)
// Make sure not to keep `value` borrowed when calling `f` below, since the user tracing
// code that `f` might invoke (e.g. fmt::Debug argument formatting) may contain nested
// tracing calls that would cause `value` to be doubly-borrowed mutably.
let (ThreadData { tid, out, start }, new_thread) = {
let mut thread_data = value.borrow_mut();
match thread_data.as_mut() {
Some(thread_data) => (thread_data.clone(), false),
None => {
let tid = self.max_tid.fetch_add(1, Ordering::SeqCst);
let out = self.out.lock().unwrap().clone();
let start = std::time::Instant::now();
*thread_data = Some(ThreadData { tid, out: out.clone(), start });
(ThreadData { tid, out, start }, true)
}
}
};

start.with_elapsed_micros_subtracting_tracing(|ts| {
if new_thread {
let name = match std::thread::current().name() {
Some(name) => name.to_owned(),
None => tid.to_string(),
};
let _ignored = out.send(Message::NewThread(*tid, name));
}
f(ts, *tid, out);
});
// Obtain the current time (before executing `f`).
let instant_before_f = std::time::Instant::now();

// Using the current time (`instant_before_f`), calculate the elapsed time (in
// microseconds) since `start` was instantiated, accounting for any time that was
// previously spent executing `f`. The "accounting" part is not computed in this
// line, but is rather done by shifting forward the `start` down below.
let ts = (instant_before_f - start).as_nanos() as f64 / 1000.0;

// Run the function (supposedly a function internal to the tracing infrastructure).
if new_thread {
let name = match std::thread::current().name() {
Some(name) => name.to_owned(),
None => tid.to_string(),
};
let _ignored = out.send(Message::NewThread(tid, name));
}
f(ts, tid, &out);

// Measure how much time was spent executing `f` and shift `start` forward
// by that amount. This "removes" that time from the trace.
// See comment at the top of this function for why we have to re-borrow here.
value.borrow_mut().as_mut().unwrap().start += std::time::Instant::now() - instant_before_f;
});
}
}
Expand Down
183 changes: 0 additions & 183 deletions src/tools/miri/src/bin/log/tracing_chrome_instant.rs

This file was deleted.

Loading
Loading