Does Swift's UnsafeMutablePointer<Float>.allocate(...) actually allocate memory? - swift

I'm trying to understand Swift's unsafe pointer API for the purpose of manipulating audio samples.
The non-mutable pointer variants (UnsafePointer, UnsafeRawPointer, UnsafeBufferPointer) make sense to me, they are all used to reference previously allocated regions of memory on a read-only basis. There is no type method "allocate" for these variants
The mutable variants (UnsafeMutablePointer, UnsafeMutableRawPointer), however, are documented as actually allocating the underlying memory. Example from the documentation for UnsafeMutablePointer (here):
static func allocate(capacity: Int)
Allocates uninitialized memory for the specified number of instances of type Pointee
However, there is no mention that the UnsafeMutablePointer.allocate(size) can fail so it cannot be actually allocating memory. Conversely, if it does allocate actual memory, how can you tell if it failed?
Any insights would be appreciated.

I decided to test this. I ran this program in CodeRunner:
import Foundation
sleep(10)
While the sleep function was executing, CodeRunner reported that this was taking 5.6 MB of RAM on my machine, making our baseline.
I then tried this program:
import Foundation
for _ in 0..<1000000 {
let ptr = UnsafeMutablePointer<Float>.allocate(capacity: 1)
}
sleep(10)
Now, CodeRunner reports 5.8 MB of RAM usage. A little more than before, but certainly not the extra 4 MB that this should have taken up.
Finally, I assigned something to the pointer:
import Foundation
for _ in 0..<1000000 {
let ptr = UnsafeMutablePointer<Float>.allocate(capacity: 1)
ptr.pointee = 0
}
sleep(10)
Suddenly, the program is taking up 21.5 MB of RAM, finally giving us our expected RAM usage increase, although by a larger amount than what I was expecting.
Making a profile in CodeRunner to compile with the optimizations turned on did not seem to make a difference in the behavior I was seeing.
So, surprisingly enough, it does appear that the call to UnsafeMutablePointer.allocate actually does not immediately allocate memory.

Operating systems can cheat a lot when it comes to memory allocations. If you request a block of memory of size N and don't actually put anything in it, the operating system can very well go "sure you can have a block of memory, here you go" and not really do anything with it. It's really more a promise that the memory will be available when used by the program.
Even with a very simple C program like the one below, the macOS's Activity Monitor will report 945 kB first, then 961 kB after calling malloc (which allocates the memory), and finally 257.1 MB after filling the allocated memory with zeroes.
From the point of view of the program, all 256 MB needed for the array of integers is available immediately after calling malloc, but that's actually a lie.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
int count = 64*1024*1024;
printf("Step 1: No memory allocated yet. Check memory usage for baseline, then press enter to continue (1/3)");
getchar();
/* Allocate big block of memory */
int *p = malloc(count*sizeof(int));
if (p == NULL) return 1; // failed to allocate
printf("Step 2: Memory allocated. Check memory usage, then press any key to continue (2/3)");
getchar();
/* Fill with zeroes */
for (int i=0; i < count; i++) {
p[i] = 0;
}
printf("Step 3: Memory filled with zeroes. Check memory usage, then press any key to continue (3/3)");
getchar();
return 0;
}

Related

Questions about the Dart memory policy

Suppose you have the following code.
List<File> files = [file1, file2, file3, file4];
Each file is 10mb in size.
So how much memory will it use? It sounds simple, but it's confusing.
It will use 40mb. Because it had 4 10mb files.
I don't know exactly, but I'll use much less than 40mb.This is because memory is not used as much as the actual size of the file, but as much as the size of a pointer pointing to the memory address of the file.
1 or 2?
The currently accepted answer is incorrect. Dart is always pass-by-value and whether it is or not is irrelevant to this question.
Now for your question. The amount of memory that you're using when working with files depends on what you're doing with them. The example you show is a list of file handles, not the files themselves. It would be inefficient to load the contents of a file into memory just by instantiating a reference to the file with a File object.
So your list is a list of file handles. This makes both of your proposed explanations incorrect since the data is not loaded into memory, though you're on the right track with the second explanation. The contents of the file is not in memory, so it will not use 40 MB of memory for 4 10 MB files. It's also not a pointer to the memory either. A pointer would still indicate that the file data is in memory and you File object just an address for that block. It's more accurate to says that it's a reference to the file given by the OS or a reference to the file's place in storage. The amount of memory that the file handle will take up is going to be relatively small, though I don't know any exact values.
Data will be loaded into memory if you explicitly request that data with a function like readAsBytes. Then the whole file will be loaded into memory and it will likely use the full 10 MB per file. There might be some optimization I don't know about, but it will be closer to the full size of the file. This will of course be in a separate variable and the File objects themselves will take up very little memory.
Dart uses pass-by-value for primitive types like int or String and uses pass-by-reference for more complex data types like List. Here the files are probably an object so it will take on the memory of the pointers.
This is a simple example for pass-by-value.
void main() {
void addOne(int x) {
x += 1;
print("x here is $x");
}
int x = 1;
addOne(x); //Output: "x here is 2"
print(x); //1
}
Here the value "x" is passed by value so, even if the function incremented x, the value in the main function will still remain 1.
example for pass-by-reference:
void main() {
void addList(List<int> x) {
x.add(12);
print("x here is $x");
}
List<int> x = [1, 2, 3, 4, 5];
addList(x); //x here is [1, 2, 3, 4, 5, 12]
print(x); //[1, 2, 3, 4, 5, 12]
}
Here the value of x is passed by reference so it would get updated in the main function as well
Passing the reference means to pass the memory location and not the actual value which is very efficient in case of big list or arrays or even complex objects. It can save much more memory than pass-by-value.
In your case the files variable is a List of File(List<File>) objects. That means that file1, file2, etc are File objects and shall thus be passed-by-reference in dart

How to allocate less memory to Scala with IntelliJ

I'm trying to crash my program (run in IntelliJ) with an OutOfMemoryException:
def OOMCrasher(acc: String): String = {
OOMCrasher(acc + "ADSJKFAKLWJEFLASDAFSDFASDFASERASDFASEASDFASDFASERESFDHFDYJDHJSDGFAERARDSHFDGJGHYTDJKXJCV")
}
OOMCrasher("")
However, it just runs for a very long time. My suspicions is that it simply takes a very long time to fill up all the gigabytes of memory allocated to the JVM with a string. So I'm looking at how to make IntelliJ allocate less memory to the JVM. Here's what I've tried:
In Run Configurations -> VM options:
--scala.driver.memory 1k || --driver.memory 1k
Both of these cause crashes with:
Unrecognized option: --scala.driver.memory
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
I've also tried to put the options in the Edit Configurations -> Program Arguments. This causes the program to run for a very long time again, not yielding an OutOfMemoryException.
EDIT:
I will accept any answer that successfully explains how to allocate less memory to the program, since that is the main question.
UPDATE:
Changing the function to:
def OOMCrasher(acc: HisList[String]): HisList[String] = {
OOMCrasher(acc.add("Hi again!"))
}
OOMCrasher(Cons("Hi again!", Empty))
where HisList is a simple LinkedList implementation as well as running with -Xmx3m caused the wanted exception.
To functionally reach an OutOfMemoryException is harder than it looks, because recursive functions almost always run first into a StackOverflowException.
But there is a mutable approach that will guarantee an OutOfMemoryException: Doubling a List over and over again. Scala's Lists are not limited by the maximum array size and thus can expand until there is just no more memory left.
Here's an example:
def explodeList[A](list: List[A]): Unit = {
var mlist = list
while(true) {
mlist = mlist ++ mlist
}
}
To answer your actual question, try to fiddle with the JVM option -Xmx___m (e.g. -Xmx256m). This defines the maximum heap size the JVM is allowed to allocate.

Is there a way to accurately measure heap allocations in Unity for unit testing?

Allocating temporary objects on the heap every frame in Unity is costly, and we all do our best to avoid this by caching heap objects and avoiding garbage generating functions. It's not always obvious when something will generate garbage though. For example:
enum MyEnum {
Zero,
One,
Two
}
List<MyEnum> MyList = new List<MyEnum>();
MyList.Contains(MyEnum.Zero); // Generates garbage
MyList.Contains() generates garbage because the default equality comparer for List uses objects which causes boxing of the enum value types.
In order to prevent inadvertent heap allocations like these, I would like to be able to detect them in my unit tests.
I think there are 2 requirements for this:
A function to return the amount of heap allocated memory
A way to prevent garbage collection occurring during the test
I haven't found a clean way to ensure #2. The closest thing I've found for #1 is GC.GetTotalMemory()
[UnityTest]
IEnumerator MyTest()
{
long before = GC.GetTotalMemory(false);
const int numObjects = 1;
for (int i = 0 ; i < numObjects; ++i)
{
System.Version v = new System.Version();
}
long after = GC.GetTotalMemory(false);
Assert.That(before == after);
}
The problem is that GC.GetTotalMemory() returns the same value before and after in this test. I suspect that Unity/Mono only allocates memory from the system heap in chunks, say 4kb, so you need to allocate <= 4kb before Unity/Mono will actually request more memory from the system heap, at which point GC.GetTotalMemory() will return a different value. I confirmed that if I change numObjects to 1000, GC.GetTotalMemory() returns different values for before and after.
So in summary, 1. how can i accurately get amount of heap allocated memory, accurate to the byte and 2. can the garbage collector run during the body of my test, and if so, is there any non-hacky way of disabling GC for the duration of my test
TL;DR
Thanks for your help!
I posted the same question over on Unity answers and got a reply:
https://answers.unity.com/questions/1535588/is-there-a-way-to-accurately-measure-heap-allocati.html
No, basically it's not possible. You could run your unit test a bunch of times in a loop and hope that it generates enough garbage to cause a change in the value returned by GC.GetTotalMemory(), but that's about it.

Microchip dsPIC33 C30 function pointer size?

The C30 user manual manual states that pointers near and far are 16bits wide.
How then does this address the full code memory space which is 24bits wide?
I am so confused as I have an assembler function (called from C) returning the program counter (from the stack) where a trap error occurred. I am pretty sure it sets w1 and w0 before returning.
In C, the return value is defined as a function pointer:
void (*errLoc)(void);
and the call is:
errLoc = getErrLoc();
When I now look at errLoc, it is a 16 bit value and I just do not think that is right. Or is it? Can function pointers (or any pointers) not access the full code address space?
All this has to do with a TRAP Adress error I am trying to figure out for the past 48 hours.
I see you are trying to use the dsPIC33Fxxxx/PIC24Hxxxx fault interrupt trap example code.
The problem is that pointer size for dsPIC33 (via the MPLAB X C30 compiler) is 16bit wide, but the program counter is 24bits. Fortunately the getErrLoc() assembly function does return the correct size.
However the example C source code function signature provided is void (*getErrLoc(void))(void) which is incorrect as it will be treating the return values as if it was a 16bit pointer. You want to change the return type of the function signature to be large enough to store the 24bits program counter value below instead. Thus if you choose unsigned long integer as the return type of getErrLoc(), then it will be large enough to store the 24bit program counter into a 32bit unsigned long integer location.
unsigned long getErrLoc(void); // Get Address Error Loc
unsigned long errLoc __attribute__((persistent));
(FYI: Using __attribute__((persistent)) to record trap location on next reboot)

Could this Scala code use less memory?

Consider the following Set benchmark:
import scala.collection.immutable._
object SetTest extends App {
def time[a](f: => a): (a,Double) = {
val start = System.nanoTime()
val result: a = f
val end = System.nanoTime()
(result, 1e-9*(end-start))
}
for (n <- List(1000000,10000000)) {
println("n = %d".format(n))
val (s2,t2) = time((Set() ++ (1 to n)).sum)
println("sum %d, time %g".format(s2,t2))
}
}
Compiling and running produces
tile:scalafab% scala SetTest
n = 1000000
sum 1784293664, time 0.982045
n = 10000000
Exception in thread "Poller SunPKCS11-Darwin" java.lang.OutOfMemoryError: Java heap space
...
I.e., Scala is unable to represent a set of 10 million Ints on a machine with 8 GB of memory. Is this expected behavior? Is there some way to reduce the memory footprint?
Generic immutable sets do take a lot of memory. The default is for only 256M heap, which leaves only 26 bytes per object. The hash trie for immutable sets generally takes one to two hundred bytes per object an extra 60 or so bytes per element. If you add -J-Xmx2G on your command line to increase the heap space to 2G, you should be fine.
(This level of overhead is one reason why there are bitsets, for example.)
I'm not that familiar with Scala, but here's what I think is happening:
First off, the integers are being stored on the heap (as the must be, since the data structure is stored on the heap). So we are talking about available heap memory, not stack memory at all (just to clarify the validity of what I'm about to say next).
The real kicker is that Java's default heap size is pretty small - I believe its only 128 megabytes (this is probably an really old number, but the point is that the number exists, and it's quite small).
So it's not that your program uses too much memory - it's more like Java just doesn't give you enough in the first place. There is a solution, though: the minimum and maximum heap sizes can be set with the -Xms and -Xmx command line options. They can be used like:
java -Xms32m -Xmx128m MyClass (starts MyClass with a minimum heap of 32 megabytes, maximum of 128 megabytes)
java -Xms1g -Xmx3g MyClass (executes MyClass with a minimum heap of 1 gigabytes, maximum of 3 gigabytes)
If you use an IDE, there are probably options in there to change the heap size as well.
This should always overflow. Holding such large values is not required in this case. If you want to sum use an iterator or a range.
val (s2,t2) = time( (1 to n).sum)
The above line completes in a second with no overflow.
You can always increase memory allocation using other answers.