Just curious, why? Is this true even if you did something like a per-CPU histogram that uses atomic ops to increment?

If you have a per-cpu metric there would not be a reason to use atomic instructions to mutate it.

In general your unpinned userspace threads will hit the same CPU 99.99% of the time, but not 100%.

Sure. You get the pointer, you lock the mutex, 99.99% of the time that is uncontended, then you set all the metrics and release it.

Taking the mutex uses (uncontended) atomic ops.