Object size on heap


(Howard Lovatt) #1

Hi,

Is there a way to find out how big an object is on the heap?

Cheers,

— Howard.

PS I did search swift-users but no luck :frowning:


(Joe Groff) #2

No public API yet. For entertainment purposes, you could use the runtime's swift_class_getInstanceExtents function, passing in the class object for the instance.

-Joe

···

On Mar 19, 2016, at 1:53 PM, Howard Lovatt via swift-users <swift-users@swift.org> wrote:

Hi,

Is there a way to find out how big an object is on the heap?


(Jens Alfke) #3

Yes, the sizeof() <http://swiftdoc.org/v2.2/func/sizeof/> function.

—Jens

···

On Mar 19, 2016, at 4:53 PM, Howard Lovatt via swift-users <swift-users@swift.org> wrote:

Is there a way to find out how big an object is on the heap?


(Brent Royal-Gordon) #4

Is there a way to find out how big an object is on the heap?

Yes, the sizeof() function.

I think he's asking for the size of the object itself. For a reference type, `sizeof()` gives you the size of the reference.

···

--
Brent Royal-Gordon
Architechies


(Howard Lovatt) #5

How do you call swift_class_getInstanceExtents, it doesn't show in Xcode?

  -- Howard.

···

On 22 March 2016 at 06:07, Joe Groff <jgroff@apple.com> wrote:

> On Mar 19, 2016, at 1:53 PM, Howard Lovatt via swift-users < > swift-users@swift.org> wrote:
>
> Hi,
>
> Is there a way to find out how big an object is on the heap?

No public API yet. For entertainment purposes, you could use the runtime's
swift_class_getInstanceExtents function, passing in the class object for
the instance.

-Joe


(Joe Groff) #6

It's not provided as API by default. You can do this as an unsupported hack:

@_silgen_name("swift_class_getInstanceExtents")
func swift_class_getInstanceExtents(theClass: AnyClass)
  -> (negative: UInt, positive: UInt)

-Joe

···

On Mar 21, 2016, at 9:31 PM, Howard Lovatt <howard.lovatt@gmail.com> wrote:

How do you call swift_class_getInstanceExtents, it doesn't show in Xcode?


(Jordan Rose) #7

This has probably gone too far to hide it already, but, um, what do you plan to do with this information?

Jordan

···

On Mar 22, 2016, at 8:47, Joe Groff via swift-users <swift-users@swift.org> wrote:

On Mar 21, 2016, at 9:31 PM, Howard Lovatt <howard.lovatt@gmail.com <mailto:howard.lovatt@gmail.com>> wrote:

How do you call swift_class_getInstanceExtents, it doesn't show in Xcode?

It's not provided as API by default. You can do this as an unsupported hack:

@_silgen_name("swift_class_getInstanceExtents")
func swift_class_getInstanceExtents(theClass: AnyClass)
  -> (negative: UInt, positive: UInt)


(Howard Lovatt) #8

Many thanks

  -- Howard.

···

On 23 March 2016 at 02:47, Joe Groff <jgroff@apple.com> wrote:

On Mar 21, 2016, at 9:31 PM, Howard Lovatt <howard.lovatt@gmail.com> > wrote:

How do you call swift_class_getInstanceExtents, it doesn't show in Xcode?

It's not provided as API by default. You can do this as an unsupported
hack:

@_silgen_name("swift_class_getInstanceExtents")
func swift_class_getInstanceExtents(theClass: AnyClass)
  -> (negative: UInt, positive: UInt)

-Joe


(Howard Lovatt) #9

I am writing custom collection classes and trying to assess which one is
better, both in terms of performance and memory usage. Won't be used in
'real' code, just to guide development.

  -- Howard.

···

On 23 March 2016 at 03:52, Jordan Rose <jordan_rose@apple.com> wrote:

On Mar 22, 2016, at 8:47, Joe Groff via swift-users <swift-users@swift.org> > wrote:

On Mar 21, 2016, at 9:31 PM, Howard Lovatt <howard.lovatt@gmail.com> > wrote:

How do you call swift_class_getInstanceExtents, it doesn't show in Xcode?

It's not provided as API by default. You can do this as an unsupported
hack:

@_silgen_name("swift_class_getInstanceExtents")
func swift_class_getInstanceExtents(theClass: AnyClass)
  -> (negative: UInt, positive: UInt)

This has probably gone too far to hide it already, but, um, what do you
plan to do with this information?

Jordan


(Jens Alfke) #10

You might consider using heap profiling tools too, like (on Mac OS) the Instruments app or the `heap` command-line tool. If you use these while running a benchmark app using your API, it can show you how much total heap space gets used.

Actual heap usage can differ from the raw “sizeof” a data type, since allocators will often round up block sizes or return a somewhat larger block than necessary. Heap fragmentation can also increase memory usage beyond what you’d expect, and different allocation patterns can affect fragmentation.

—Jens

···

On Mar 22, 2016, at 11:04 PM, Howard Lovatt via swift-users <swift-users@swift.org> wrote:

I am writing custom collection classes and trying to assess which one is better, both in terms of performance and memory usage. Won't be used in 'real' code, just to guide development.


(Howard Lovatt) #11

Thanks, I will give that a try

  -- Howard.

···

On 24 March 2016 at 03:17, Jens Alfke <jens@mooseyard.com> wrote:

On Mar 22, 2016, at 11:04 PM, Howard Lovatt via swift-users < > swift-users@swift.org> wrote:

I am writing custom collection classes and trying to assess which one is
better, both in terms of performance and memory usage. Won't be used in
'real' code, just to guide development.

You might consider using heap profiling tools too, like (on Mac OS) the
Instruments app or the `heap` command-line tool. If you use these while
running a benchmark app using your API, it can show you how much total heap
space gets used.

Actual heap usage can differ from the raw “sizeof” a data type, since
allocators will often round up block sizes or return a somewhat larger
block than necessary. Heap fragmentation can also increase memory usage
beyond what you’d expect, and different allocation patterns can affect
fragmentation.

—Jens


(Kate Stone) #12

I definitely concur that tools like Instruments are the best way to understand the impact of decisions on memory across the board. For fine-grained inquiries about memory use you can also rely on malloc family functions to make inquiries:

let required_size = malloc_size(unsafeAddressOf(object_reference))
let actual_size = malloc_good_size(required_size)

Kate Stone k8stone@apple.com <mailto:k8stone@apple.com>
 Xcode Low Level Tools

···

On Mar 23, 2016, at 3:59 PM, Howard Lovatt via swift-users <swift-users@swift.org> wrote:

Thanks, I will give that a try

  -- Howard.

On 24 March 2016 at 03:17, Jens Alfke <jens@mooseyard.com <mailto:jens@mooseyard.com>> wrote:

On Mar 22, 2016, at 11:04 PM, Howard Lovatt via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

I am writing custom collection classes and trying to assess which one is better, both in terms of performance and memory usage. Won't be used in 'real' code, just to guide development.

You might consider using heap profiling tools too, like (on Mac OS) the Instruments app or the `heap` command-line tool. If you use these while running a benchmark app using your API, it can show you how much total heap space gets used.

Actual heap usage can differ from the raw “sizeof” a data type, since allocators will often round up block sizes or return a somewhat larger block than necessary. Heap fragmentation can also increase memory usage beyond what you’d expect, and different allocation patterns can affect fragmentation.

—Jens

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Howard Lovatt) #13

@Kate,

I don't seem to be able to get `malloc_...` to work. EG:

class TestClass {
    let a = 0
    let b: Int? = nil
}
@_silgen_name("swift_class_getInstanceExtents") func
swift_class_getInstanceExtents(theClass: AnyClass) -> (negative: UInt,
positive: UInt)
print("swift_class_getInstanceExtents =
\(swift_class_getInstanceExtents(TestClass))")
let requiredSize = malloc_size(unsafeAddressOf(TestClass()))
print("malloc_size = \(requiredSize)")
print("malloc_good_size = \(malloc_good_size(requiredSize))")

Prints:

swift_class_getInstanceExtents = (0, 33)
malloc_size = 0
malloc_good_size = 16

The `swift_class_getInstanceExtents` seems correct to me: 16 bytes for
class overhead + 16 bytes for `a` and `b` + 1 byte because `b` is an
optional = 33 bytes.

Not sure what `malloc_...` is giving?

  -- Howard.

···

On 24 March 2016 at 10:39, Kate Stone <k8stone@apple.com> wrote:

I definitely concur that tools like Instruments are the best way to
understand the impact of decisions on memory across the board. For
fine-grained inquiries about memory use you can also rely on malloc family
functions to make inquiries:

let required_size = malloc_size(unsafeAddressOf(*object_reference*))
let actual_size = malloc_good_size(required_size)

Kate Stone k8stone@apple.com
 Xcode Low Level Tools

On Mar 23, 2016, at 3:59 PM, Howard Lovatt via swift-users < > swift-users@swift.org> wrote:

Thanks, I will give that a try

  -- Howard.

On 24 March 2016 at 03:17, Jens Alfke <jens@mooseyard.com> wrote:

On Mar 22, 2016, at 11:04 PM, Howard Lovatt via swift-users < >> swift-users@swift.org> wrote:

I am writing custom collection classes and trying to assess which one is
better, both in terms of performance and memory usage. Won't be used in
'real' code, just to guide development.

You might consider using heap profiling tools too, like (on Mac OS) the
Instruments app or the `heap` command-line tool. If you use these while
running a benchmark app using your API, it can show you how much total heap
space gets used.

Actual heap usage can differ from the raw “sizeof” a data type, since
allocators will often round up block sizes or return a somewhat larger
block than necessary. Heap fragmentation can also increase memory usage
beyond what you’d expect, and different allocation patterns can affect
fragmentation.

—Jens

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Kate Stone) #14

You’re almost certainly seeing side effects of not keeping the instance of TestClass alive long enough for the unsafe pointer to still refer to an allocated malloc block. A quick REPL session illustrates this fact:

  1> class TestClass {
  2. let a = 0
  3. let b: Int? = nil
  4. }
  5> import Foundation
  6> malloc_size(unsafeAddressOf(TestClass()))
$R0: Int = 0
  7> let x = TestClass()
x: TestClass = {
  a = 0
  b = nil
}
  8> malloc_size(unsafeAddressOf(x))
$R1: Int = 48

On line 6 the result of the TestClass() expression is being used only to call unsafeAddressOf, and then it’s being freed before the call to malloc_size. On line 8 the variable x is retaining the instance so the malloc’ed region can be measured.

Of course all of this relies on the implementation assumption that allocated objects go on malloc’s heap and is subject to implementation details about object layout. So while this may be instructive now it’s certainly no guarantee of how things will work in the future.

Kate Stone k8stone@apple.com <mailto:k8stone@apple.com>
 Xcode Low Level Tools

···

On Mar 23, 2016, at 5:13 PM, Howard Lovatt <howard.lovatt@gmail.com> wrote:

@Kate,

I don't seem to be able to get `malloc_...` to work. EG:

class TestClass {
    let a = 0
    let b: Int? = nil
}
@_silgen_name("swift_class_getInstanceExtents") func swift_class_getInstanceExtents(theClass: AnyClass) -> (negative: UInt, positive: UInt)
print("swift_class_getInstanceExtents = \(swift_class_getInstanceExtents(TestClass))")
let requiredSize = malloc_size(unsafeAddressOf(TestClass()))
print("malloc_size = \(requiredSize)")
print("malloc_good_size = \(malloc_good_size(requiredSize))")

Prints:

swift_class_getInstanceExtents = (0, 33)
malloc_size = 0
malloc_good_size = 16

The `swift_class_getInstanceExtents` seems correct to me: 16 bytes for class overhead + 16 bytes for `a` and `b` + 1 byte because `b` is an optional = 33 bytes.

Not sure what `malloc_...` is giving?

  -- Howard.

On 24 March 2016 at 10:39, Kate Stone <k8stone@apple.com <mailto:k8stone@apple.com>> wrote:
I definitely concur that tools like Instruments are the best way to understand the impact of decisions on memory across the board. For fine-grained inquiries about memory use you can also rely on malloc family functions to make inquiries:

let required_size = malloc_size(unsafeAddressOf(object_reference))
let actual_size = malloc_good_size(required_size)

Kate Stone k8stone@apple.com <mailto:k8stone@apple.com>
 Xcode Low Level Tools

On Mar 23, 2016, at 3:59 PM, Howard Lovatt via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

Thanks, I will give that a try

  -- Howard.

On 24 March 2016 at 03:17, Jens Alfke <jens@mooseyard.com <mailto:jens@mooseyard.com>> wrote:

On Mar 22, 2016, at 11:04 PM, Howard Lovatt via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

I am writing custom collection classes and trying to assess which one is better, both in terms of performance and memory usage. Won't be used in 'real' code, just to guide development.

You might consider using heap profiling tools too, like (on Mac OS) the Instruments app or the `heap` command-line tool. If you use these while running a benchmark app using your API, it can show you how much total heap space gets used.

Actual heap usage can differ from the raw “sizeof” a data type, since allocators will often round up block sizes or return a somewhat larger block than necessary. Heap fragmentation can also increase memory usage beyond what you’d expect, and different allocation patterns can affect fragmentation.

—Jens

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users


(Howard Lovatt) #15

Thanks, you are correct. Very helpful.

  -- Howard.

···

On 24 March 2016 at 11:20, Kate Stone <k8stone@apple.com> wrote:

You’re almost certainly seeing side effects of not keeping the instance of
TestClass alive long enough for the unsafe pointer to still refer to an
allocated malloc block. A quick REPL session illustrates this fact:

  1> class TestClass {
  2. let a = 0
  3. let b: Int? = nil
  4. }
  5> import Foundation
  6> malloc_size(unsafeAddressOf(TestClass()))
$R0: Int = 0
  7> let x = TestClass()
x: TestClass = {
  a = 0
  b = nil
}
  8> malloc_size(unsafeAddressOf(x))
$R1: Int = 48

On line 6 the result of the TestClass() expression is being used only to
call unsafeAddressOf, and then it’s being freed before the call to
malloc_size. On line 8 the variable x is retaining the instance so the
malloc’ed region can be measured.

Of course all of this relies on the implementation assumption that
allocated objects go on malloc’s heap and is subject to implementation
details about object layout. So while this may be instructive now it’s
certainly no guarantee of how things will work in the future.

Kate Stone k8stone@apple.com
 Xcode Low Level Tools

On Mar 23, 2016, at 5:13 PM, Howard Lovatt <howard.lovatt@gmail.com> > wrote:

@Kate,

I don't seem to be able to get `malloc_...` to work. EG:

class TestClass {
    let a = 0
    let b: Int? = nil
}
@_silgen_name("swift_class_getInstanceExtents") func
swift_class_getInstanceExtents(theClass: AnyClass) -> (negative: UInt,
positive: UInt)
print("swift_class_getInstanceExtents =
\(swift_class_getInstanceExtents(TestClass))")
let requiredSize = malloc_size(unsafeAddressOf(TestClass()))
print("malloc_size = \(requiredSize)")
print("malloc_good_size = \(malloc_good_size(requiredSize))")

Prints:

swift_class_getInstanceExtents = (0, 33)
malloc_size = 0
malloc_good_size = 16

The `swift_class_getInstanceExtents` seems correct to me: 16 bytes for
class overhead + 16 bytes for `a` and `b` + 1 byte because `b` is an
optional = 33 bytes.

Not sure what `malloc_...` is giving?

  -- Howard.

On 24 March 2016 at 10:39, Kate Stone <k8stone@apple.com> wrote:

I definitely concur that tools like Instruments are the best way to
understand the impact of decisions on memory across the board. For
fine-grained inquiries about memory use you can also rely on malloc family
functions to make inquiries:

let required_size = malloc_size(unsafeAddressOf(*object_reference*))
let actual_size = malloc_good_size(required_size)

Kate Stone k8stone@apple.com
 Xcode Low Level Tools

On Mar 23, 2016, at 3:59 PM, Howard Lovatt via swift-users < >> swift-users@swift.org> wrote:

Thanks, I will give that a try

  -- Howard.

On 24 March 2016 at 03:17, Jens Alfke <jens@mooseyard.com> wrote:

On Mar 22, 2016, at 11:04 PM, Howard Lovatt via swift-users < >>> swift-users@swift.org> wrote:

I am writing custom collection classes and trying to assess which one is
better, both in terms of performance and memory usage. Won't be used in
'real' code, just to guide development.

You might consider using heap profiling tools too, like (on Mac OS) the
Instruments app or the `heap` command-line tool. If you use these while
running a benchmark app using your API, it can show you how much total heap
space gets used.

Actual heap usage can differ from the raw “sizeof” a data type, since
allocators will often round up block sizes or return a somewhat larger
block than necessary. Heap fragmentation can also increase memory usage
beyond what you’d expect, and different allocation patterns can affect
fragmentation.

—Jens

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users