components produce partial updates • A central loop aggregates them for application Event Component A Component B Component C Partial Update A Partial Update B Partial Update C Aggregator Final Result 9
= 6,441 bytes • 50/58 members were of non-trivial types (e.g., class, String, Array) struct Update { var needsReRender: Bool var fooUpdate: FooUpdate? var barUpdate: BarUpdate? // ... dozens more optional fields ... var zooUpdate: ZooUpdate? } 11
byte Double 8 bytes Non-trivial Types (Example: Reference-counted) Reference / Pointer Reference Count 8 bytes Data ... points to heap Trivial vs non-trivial in Swift • Trivial (BitwiseCopyable): can be moved/copied with direct memory operations (effectively memcpy); no special destroy needed • Non-trivial: requires runtime work for copy/destroy (reference counting, CoW checks, custom destructors) • Any non-trivial member makes an aggregate non-trivial 14
Int } func pairFoo() -> (Foo, Foo) { let v = makeFoo() return (v, v) // Copy happens here } pairFoo: bl _makeFoo ; Get value (returns in x0, x1) mov x2, x0 ; Copy first field mov x3, x1 ; Copy second field ret ; Done - just register moves 15
• Whole-program visibility over use sites • Often runtime hot/cold evidence (profile-guided) • Rewriting all field accesses safely • ABI/resilience constraints complicate public types 20
• Cold fields: • Just concatenate arrays • Ensure winners occur later • Apply by taking the last occurrence per cold update type Update 1 supplemental: [ ] Result (1+2) supplemental: [ ] Update 2 supplemental: [ ] Final Aggregated Update supplemental: [B, C] Zero Array Allocation Fast Concat Update 3 supplemental: [B, C] 25
update: Update) { // Handle hot fields if update.needsReRender { render() } // Handle cold fields: take last occurrence per type var lastSeen: [ObjectIdentifier: any ColdUpdate] = [:] for coldUpdate in update.cold { lastSeen[ObjectIdentifier(type(of: coldUpdate))] = coldUpdate } // Apply only the last occurrence of each type for coldUpdate in lastSeen.values { coldUpdate.accept(visitor) } } 26