> This should be obvious because pure reference counting requires modifying counts whenever locals are assigned, which happen orders of magnitude more often than main memory updates, and now each local assignment requires touching main memory too.
I guess so, but it's worth noting that this isn't the case in Rust, because Rc benefits from move semantics. Most assignments don't touch the reference counts at all.
Reference counting has always been slower, even in single-threaded cases. This should be obvious because pure reference counting requires modifying counts whenever locals are assigned, which happen orders of magnitude more often than main memory updates, and now each local assignment requires touching main memory too.
As soon as you defer these updates somehow to recover that cost, you've introduced partial tracing. You can find papers from way back acknowledging this overhead, and suggesting optimizations [1].
[1] http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.25.9...