Reference counting is not faster than tracing GC for general purpose workloads, at least not without a lot of extensive tuning that includes stuff like using tracing and moving GC for the young generation (prior to the first collection), deferring reference count increment/decrements using write barriers, limiting reference count bits (and reclaiming stuck objects with some variant of full heap tracing), and so on. Many of these benefits cannot be effectively realized if you insist on prompt execution of finalizers, either. Languages like Rust and C++ gain their performance benefits not from using reference counting or immediate reclamation, but from avoiding creating garbage in the first place by stack allocating most stuff, creating large objects by-value and within vectors to reduce pointer chasing, using direct interior references into data structures in ways that it would be difficult to trace efficiently, and using data structures like arenas to emulate the benefits of generational GC in controlled contexts where a maximum lifetime can be statically determined.
My personal feeling is that it's very hard to directly compare manual memory management and GC from a performance perspective because so many of the techniques that make tracing fast involve moving pointers, which is very costly to combine with many of the techniques that make manual memory management fast which rely on values not moving in memory. I think any such solution that is efficient for both kinds of memory will probably require the programmer to have very tight control over when the garbage collector can execute, whether pointers can move at particular times, etc., and the complexity of maintaining that kind of control (and getting it right!) seems so high that I'm not sure it would ever be usable for general purpose programming.