swiftheap-memorydynamic-allocationmemory-layout

Get the size (in bytes) of an object on the heap


I'm aware you can use MemoryLayout<T>.size to get the size of a type T.

For example: MemoryLayout<Int32>.size // 4

However, for class instances (objects), MemoryLayout<T>.size returns the size of the reference to the object (8 bytes on 64 bit machines), not the size of the actual objects on the heap.

class ClassA { // Objects should be at least 8 bytes
    let x: Int64 = 0
}

class ClassB  {// Objects should be at least 16 bytes
    let x: Int64 = 0
    let y: Int64 = 0
}

MemoryLayout<ClassA>.size // 8
MemoryLayout<ClassB>.size // 8, as well :(

How can I get the size of the objects themselves?

For those wondering, I have no real need for this, I'm just exploring around Swift and its interoperability with C.


Solution

  • One option on Apple platforms, because Swift classes are currently built on top of Objective-C classes there, would be to use the Obj-C runtime function class_getInstanceSize, which gives you the size in bytes of an instance of the class, including any padding.

    // on a 64-bit machine (1 word == 8 bytes)...
    
    import Foundation
    
    class C {}
    print(class_getInstanceSize(C.self)) // 16 bytes metadata for empty class 
                                         // (isa ptr + ref count)
    
    class C1 {
        var i = 0
        var i1 = 0
        var b = false
    }
    
    print(class_getInstanceSize(C1.self)) // 40 bytes
    // (16 metadata + 24 ivars, 8 for i + 8 for i1 + 1 for b + 7 padding)