I am learning Instruments so I created a simple app that lets the user input a number of Mega Bytes (MB) to be allocated. And I use the "Allocations" tool in Instruments to make sure this exact amount of data is allocated. However, I always see more memory allocated in Instruments than I expect.
I did the following
func allocateMemoryOfSize(numberOfBytes: Int) {
var bytesArray = [Int8]()
for i in 0 ..< numberOfBytes {
bytesArray.append(Int8(i % 7))
}
}
I checked many questions and I found an alternative using:
func allocateMemoryOfSize(numberOfBytes: Int) {
var imageData = UnsafeMutablePointer<Int8>.alloc(numberOfBytes)}
But I still get more memory allocated. Here is the restults in Instruments when I allocate 10 MBs:
Before running the allocateMemoryOfSize function:
During the running of the function: 44.96 MB used
After the running of the function: back to only 20.58 MB
So, the function allocates around 22 MBs not 10 as wanted. What am I doing wrong? or is this extra memory management stuff?
In Swift, memory management is handled by Automatic Reference Counting (ARC). Whenever you create a new instance of a class ARC allocates a chunk of memory to store information about the type of instance and values of stored properties of that instance.
1. Stack is used for static memory allocation, Heap is used for dynamic memory allocation. 2. Variables allocated on the stack are stored directly into memory and access memory very faster and its allocation dealt with compile time.
Stack is used for static memory allocation and Heap for dynamic memory allocation, both stored in the computer's RAM . For reference types, the reference is stored on the stack while the object it refers to is stored on the heap.
In first case when you append bytes to your array internally it uses reallocation when there is no free space. This reallocation usually doubles current array size. Here is how it looks:
You see that allocation was done with some additional space.
If we change you function to preallocate memory:
func allocateMemoryOfSize(numberOfBytes: Int) {
buffer = [UInt8](count: numberOfBytes, repeatedValue: 0)
for i in 0 ..< numberOfBytes {
buffer[i] = UInt8(i % 7)
}
}
We will see this:
Update #1
Allocation with unsafe pointer will work too. Main disadvantage is manual memory management: you have to deallocate it explicitly.
About allocation summary: when you allocate memory some system allocations also happen. In my screenshot you could see that not only 10 megabytes allocated with caller swift.slowAlloc
but also 8 megabytes with caller _dispatch_alloc_try_create_heap
. So you will see on graph that app uses 18 megabytes instead of 10. I don't know why this system allocation also happen because it is iOS internals. I think you need to pay attention only on your allocations. In my example I see that 10 megabytes was requested and given to app.
Swift 3.1:
static var buffer = [UInt8]()
static func allocateMemoryOfSize(numberOfMegaBytes: Int) {
print("Allocating \(numberOfMegaBytes)MB of memory")
let mb = 1048576
let newBuffer = [UInt8](repeating: 0, count: numberOfMegaBytes * mb)
buffer += newBuffer
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With