不可改变是记忆猪吗? [英] Can immutable be a memory hog?

查看:111
本文介绍了不可改变是记忆猪吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有一个像 Image 这样的内存密集型类,带有可链式方法,如 Resize()的ConvertTo()

如果这个类是不可变的,当我开始执行像 i.Resize(500,800)时,它不会占用大量内存).Rotate(90).ConvertTo(Gif),相比于一个可修改的自身?如何在函数式语言中处理这种情况?

解决方案


如果这个类是不可变的,它不会占用大量的内存吗?


通常,您对该单个对象的内存需求可能加倍,因为你可能会同时存在旧版本和新版本。因此,您可以在程序的整个生命周期中查看这种现象,因为已经分配了一个比您在典型命令程序中分配的大对象。 (不在正在工作的对象只是坐在那里,与其他语言中的内存要求相同。)


在功能语言中处理这样的情况?


绝对没有任何问题。身体健康的新对象。
如果您正在使用专为函数式编程设计的实现,则分配器和垃圾回收器几乎可以在高分配率下进行调整,并且一切都会好起来的。如果你不幸尝试在JVM上运行功能代码,那么性能不会像定制的实现那么好,但是对于大多数程序来说它仍然可以。







您可以提供更多详细信息吗?

不确定。我将举一个非常简单的例子:1000x1000灰度图像,每像素8位,旋转180度。以下是我们知道的内容:


  • 要在内存中表示图片需要1MB。


  • 如果图像是可变的,则可以通过进行更新来旋转180度。所需的临时空间量足以容纳一个像素。你写一个双重嵌套的循环,对于(i在列中)做
    (j在上半部分)时,相当于

      )行{b $ b像素temp:= a [i,j]; 
    a [i,j]:= a [width-i,height-j];
    a [width-i,height-j]:= tmp
    }


  • 如果图像不可变,则需要创建一个完整的新图像,并且暂时必须挂在旧图像上。代码是这样的:

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

    tabulate 函数分配一个完整的,不可变的二维数组并初始化其内容。在此操作过程中,旧图像占用内存暂时。但是,当 tabulate 完成时,旧映像 a 不应再使用,并且其内存现在是空闲的说,有资格由垃圾收集器回收)。然后,所需的临时空间量足以容纳一张图片。


  • 旋转过程中,不需要复制对象的副本其他班级;只需要临时空间就可以旋转图片。

  • 对于其他操作,例如将(非方形)图像重新缩放或旋转90度,很可能即使图像是可变的,整个图像的临时副本也是必要的,因为尺寸会发生变化。另一方面,逐个像素完成的色彩空间转换和其他计算可以使用具有非常小的临时空间的突变来完成。


    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?

    解决方案

    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.

    这篇关于不可改变是记忆猪吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆