Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can immutable be a memory hog?

Let's say we have a memory-intensive class like an Image, with chainable methods like Resize() and ConvertTo().

If this class is immutable, won't it take a huge amount of memory when I start doing things like i.Resize(500, 800).Rotate(90).ConvertTo(Gif), compared to a mutable one which modifies itself? How to handle a situation like this in a functional language?

like image 385
ciscoheat Avatar asked Mar 26 '10 23:03

ciscoheat


People also ask

Are immutable objects memory efficient?

If we used an immutable type instead, then different parts of the program could safely share the same values in memory, so less copying and less memory space is required. Immutability can be more efficient than mutability, because immutable types never need to be defensively copied.

What is immutable memory?

An object created and given a value is assigned some space in memory. The variable name bound to the object points to that place in memory and as long as the memory is not changed, it is immutable. “as long as the memory is not changed, it is immutable.”

Are there any downsides to using immutable?

The only real disadvantage of immutable classes is that they require a separate object for each distinct value. Creating these objects can be costly, especially if they are large.

What can be immutable?

In object-oriented and functional programming, an immutable object (unchangeable object) is an object whose state cannot be modified after it is created. This is in contrast to a mutable object (changeable object), which can be modified after it is created.


1 Answers

If this class is immutable, won't it take a huge amount of memory?

Typically your memory requirements for that single object might double, because you might have an "old copy" and a "new copy" live at once. So you can view this phenomenon, over the lifetime of the program, as having one more large object allocated than you might in a typical imperative program. (Objects that aren't being "worked on" just sit there, with the same memory requirements as in any other language.)

How to handle a situation like this in a functional language?

Do absolutely nothing. Or more accurately, allocate new objects in good health. If you are using an implementation designed for functional programming, the allocator and garbage collector are almost certainly tuned for high allocation rates, and everything will be fine. If you have the misfortune to try to run functional code on the JVM, well, performance won't be quite as good as with a bespoke implementation, but for most programs it will still be fine.


Can you provide more detail?

Sure. I'm going to take an exceptionally simple example: 1000x1000 greyscale image with 8 bits per pixel, rotated 180 degrees. Here's what we know:

  • To represent the image in memory requires 1MB.

  • If the image is mutable, it's possible to rotate 180 degrees by doing an update in place. The amount of temporary space needed is enough to hold one pixel. You write a doubly nested loop that amounts to

    for (i in columns) do   for (j in first half of rows) do {      pixel temp := a[i, j];       a[i, j] := a[width-i, height-j];       a[width-i, height-j] := tmp   } 
  • If the image is immutable, it's required to create an entire new image, and temporarily you have to hang onto the old image. The code is something like this:

    new_a = Image.tabulate (width, height) (\ x y -> a[width-x, height-y]) 

    The tabulate function allocates an entire, immutable 2D array and initializes its contents. During this operation, the old image is temporarily occupying memory. But when tabulate completes, the old image a should no longer be used, and its memory is now free (which is to say, eligible for recycling by the garbage collector). The amount of temporary space required, then, is enough to hold one image.

  • While the rotation is going on, there's no need to have copies of objects of other classes; the temporary space is needed only for the image being rotated.

N.B. For other operations such as rescaling or rotating a (non-square) image by 90 degrees, it is quite likely that even when images are mutable, a temporary copy of the entire image is going to be necessary, because the dimensions change. On the other hand, colorspace transformations and other computations which are done pixel by pixel can be done using mutation with a very small temporary space.

like image 167
Norman Ramsey Avatar answered Sep 28 '22 06:09

Norman Ramsey