7 ms·
Remember Lisp machines? The M1 is a Swift machine.
by lisper 6y ago
Remember Lisp machines? The M1 is a Swift machine.
- brundolf 6y agoI'm wondering if the "optimized for reference-counting" thing applies to other languages too. i.e. if I write a piece of software in Rust, and I make use of Rc<>, will Macs be extra tolerant of that overhead? In theory it seems like the answer should be yes
- lilyball 6y agoI sure hope so. In macOS 10.15, the fast path for a retain on a (non-tagged-pointer) Obj-C object does a C11 relaxed atomic load followed by a C11 relaxed compare-and-exchange. This seems pretty standard for retain-release and I'd expect Rust's Rc<> to be doing something similar. It's possible Apple added some other black magic to the runtime in 10.16 (and they haven't released the 10.16 objc sources yet) but it's hard to imagine what they'd do that makes more sense than just optimizing for relaxed atomic operations.
- steveklabnik 6y ago(Rc does not use atomics, Arc does and from a peek at the source it does indeed use Relaxed)
- wahern 6y agoI didn't understand why the implementation wouldn't just do an atomic increment, but I guess Obj-C semantics provide too much magic to permit such a simple approach. The actual code, in addition to [presumably] not being inlined, does not seem easy to optimize at the hardware level: https://github.com/apple/swift-corelibs-foundation/blob/main/CoreFoundation/Base.subproj/CFRuntime.c#L1365 https://github.com/apple/swift-corelibs-foundation/blob/main... The native Swift retain (swift_retain above) seems to be somewhere inside this mess: https://github.com/apple/swift/blob/main/stdlib/public/runtime/HeapObject.cpp https://github.com/apple/swift/blob/main/stdlib/public/runti...
- lilyball 6y agoWhat you’ve linked is CoreFoundation’s retain, Objective-C’s can be found in https://opensource.apple.com/source/objc4/objc4-787.1/runtime/objc-object.h.auto.html https://opensource.apple.com/source/objc4/objc4-787.1/runtim... (look for objc_object::rootRetain). The short answer for why it can’t just be an increment is because the reference count is stored in a subset of the bits of the isa pointer, and when the reference count grows too large it has to overflow into a separate sidetable. So it does separate load and CAS operations in order to implement this overflow behavior.
- saagarjha 6y agoI’d think the bigger win would have to be in the release part of the code, which actually cares about contention.
- plorkyeran 6y agoYes, it applies to everything which uses atomics and is not something special in the runtime. It's also worth noting that this is an optimization that iphones have had for the last few years ever since those switched to arm64.
- saagarjha 6y agoThe fast atomics are relatively new.
- favorited 6y agoNo, because Rc<> isn't atomic. Arc<>, however, would get the benefit. The reason retain/release in ObjC/Swift are so much faster here is because they are atomic operations.
- amelius 6y agoSo, useful for structural sharing between threads.
- klelatti 6y agoBut how? It has an Arm CPU - how does it differ from any other machine with a 64 bit Arm CPU?
- brundolf 6y agoThe M1 is much more than a CPU, and a CPU is much more than an instruction set
- klelatti 6y agoI know it's a fast Arm CPU - I've read the Anandtech analysis etc - and that there is lots of extra hardware on the SoC. But the specific point was why is it a Swift machine. What makes it particularly suited to running Swift?
- brundolf 6y agoThe exact reason is out of my depth, but the original quote makes it clear that there is something. Memory bandwidth would be one possibility.
- dathinab 6y agoMy guess: 1. "weak" memory ordering (atomic Aquire/Release loads/stores) 2. low memory latencies between cache and system memory (so dirty pages in caches are faster updated etc.) 3. potential a coherency impl. optimized for this kind of atomic access (purely speculative: e.g. maybe sometimes updating less then a page in a cache when detecting certain atomic operations which changed a page or maybe wrt. the window marked for exclusive access in context of ll/sc-operations and similar) Given that it's common for a object to stay in the same thread I'm not sure how much 2. matters for this point (but it does matters for general perf.). But I guess there is a lot in 3. where especially with low latency ram you might be able to improve performance for this cases.
- gwking 6y ago
- mpweiher 6y agoIf anything, an Objective-C machine: they apparently have a special branch predictor for objc_msgSend()! But they learned the lesson from SOAR (Smalltalk On A RISC) and did not follow the example of LISP machines, Smalltalk machines, Java machines, Rekursiv, etc. and build specialized hardware and instructions. The benefits of the specialization are much, much less than expected, and the costs of being custom very high. Instead, they gave the machine large caches and tweaked a few general purpose features so they work particularly well for their preferred workloads. I wonder if they made trap on overflow after arithmetic fast.