6

I'm writing a program that goes into a loop and keeps changing the state of some models (similar to a game). Naturally, many things are mutable. However, I'm also writing some classes that are immutable because they're inherently treated like values (for example: vectors, matrices, etc.)

However, these values change on every loop (maybe 50-100 times a second). Does this mean that on every change, the program would need to allocate a new chunk of memory? If I'm using managed code, does this mean that the memory usage will build up very quickly? How does this impact determinism, performance, and garbage collection in languages such as C# and Java, especially when many garbage collectors have to pause the entire program in order to clear the memory?

  • most garbage collection is geared towards many short lived objects, though spawning thousands in a tight loop will still cause slowdown – ratchet freak Jul 17 '14 at 10:04
  • Allocating memory in a modern VM usually reduces to incrementing a pointer somewhere. You usually don't have to worry about it unless you create/free your objects more often than you use them at all. – Kilian Foth Jul 17 '14 at 10:18
  • 3
    The usual answer would be: [1] Try it and measure. [2] If performance is actually impacted then try fixing it. I guess the obvious answer would be to use mutable objects instead of immutable ones. [3] If the performance is not impacted, then it is not a problem until it is a problem. This is definitely not an algorithmic bug. – InformedA Jul 17 '14 at 10:18
  • In C#, are the objects actual value types or not? IIRC, this will matter quite a bit. – Telastyn Jul 17 '14 at 11:58
  • @KilianFoth: Any realistic assessment of the cost of memory allocation should include the amortized cost of garbage collection. Since the amortized cost-per-allocated-megabyte cost of garbage collection may vary based upon memory usage patterns throughout a program, it can be difficult to accurately measure how it will affect performance in real-world situations. – supercat Jul 21 '14 at 21:17
2

All structs are allocated on stack or is part of memory of containing class. Even if you allocate millions of structures, it is not going to impact memory. On the other hand, passing big struct around by value (not by reference) might impact performance, because it is copied every time.

On the other hand, allocating new class might impact memory consumption, because new class instance = new allocated memory. Also, it might impact performance, because GC needs to keep track of it and dispose it. There are some optimizations like Generational GC, but if you really need performance, it is best to manage the memory yourself.

  • 4
    In .NET, structs may be allocated to the stack. This is not part of the spec, but rather how it was implemented on Windows. There are numerous posts on why you should not make any assumptions in that regard. – Magus Jul 17 '14 at 14:38
  • I was considering using a struct instead of a class, but it needs to store several doubles and so it would be pretty large. AFAIK, structs are recommended to be a maximum of 16 bytes, according to Microsoft guidelines (msdn.microsoft.com/en-us/library/ms229017.aspx) – 9a3eedi Jul 21 '14 at 19:18
2

If you need something which behaves like a group of independent-but-related variables bound together with duct tape (E.g. the coordinates of a vector), use an exposed-field structure. The fields of an exposed-field structure are mutable when the structure is stored in a mutable location, and immutable when the storage location is stored in an immutable location.

Because an open-field structure behaves like a bunch of independent-but-related variables, some people who think everything should behave like an object deride them as "evil". I would posit that although open-field or otherwise-mutable structures are generally not suitable in places requiring something that behaves like an object, they are a perfect fit in places where one will need bunches of variables stuck together with duct tape.

It's possible to use immutable class objects to hold bunches of independent-but-related values. It can even be advantageous in cases where composite values (i.e. particular combination of values) will be passed around much more frequently than they are created. On the other hand, if code which holds a reference to a vector (34,39) wants to hold a reference to a vector whose x component is one larger, it won't be able to simply increment a field (as it could with a structure) but must instead create an entirely new vector object (35,39). The performance cost of doing this won't be a problem if one never has to perform such operations repeatedly within an inner loop. On the other hand, if a program would frequently execute significant loops whose primary purpose involves constructing slightly-modified versions of objects, the time required to construct such objects could become a substantial fraction of overall execution time.

  • I'm not sure I understand how the fields of an exposed-field structure are immutable if stored in an immutable location. Is there an example I can use? – 9a3eedi Jul 22 '14 at 9:31
  • 1
    @9a3eedi: Declare a public-field structure type like struct IntPair { public int V1,V2; public IntPair(v1,v2) { V1=v1; V2=v2; } }. Then declare ordinary and readonly fields of that type and try writing to the members thereof. If foo is a local variable or an ordinary field, you will be allowed to write foo.V1 and foo.V2. If bar is a readonly field or a property of type , and boz()` is a function, you will not be able to write to bar.V1 nor boz().V2. – supercat Jul 22 '14 at 15:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.