在存放的字节数组图像时内存问题 [英] Memory issue when storing images in byteArray

查看:246
本文介绍了在存放的字节数组图像时内存问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个需要非常快速访问大量图像的应用程序,所以我需要这些图像加载到内存中以某种方式。这样做所使用超过100MB RAM位图,这是完全不可能的,所以我选择读JPG文件到内存,存储他们的字节数组中。然后我去code和他们每个需要把它们写在画布上。此工程pretty好,切割出较慢的磁盘访问,同时也尊重内存限制。

I have an app that needs to access a large number of images very quickly, so I need to load those images into memory in some way. Doing so as bitmaps used over 100MB of RAM, which was completely out of the question, so I opted to read jpg files into memory, storing them inside a byteArray. Then I decode them and write them to the canvas as each is needed. This works pretty well, cutting out the slow disk access, while also respecting memory limits.

但是,内存使用情况似乎关闭给我。我存储450的JPG文件与文件大小约为33KB每个。这总计围绕数据的15MB。但是,应用程序不断在35MB和双方的Eclipse DDMS和Android报道(物理设备)的RAM 40MB之间运行。我试过很多修改JPG格式如何加载和应用程序使用的RAM趋于约为每JPG 60-70kb减少通过,表明每个图像在RAM存储两次。内存使用率不波动,这意味着,有没有参与实际的泄漏。

However, memory usage seems 'off' to me. I'm storing 450 jpgs with a file size of approximately 33kb each. This totals around 15MB of data. However, the app continually runs at between 35MB and 40MB of RAM as reported by both Eclipse DDMS and Android (on a physical device). I've tried modifying how many jpgs are loaded and the RAM used by the app tends to decrease by around 60-70kb per jpg, indicating that each image is stored twice in RAM. Memory usage does not fluctuate which implies that there is not an actual 'leak' involved.

下面是相关装载code:

Here is the relevant loading code:

private byte[][] bitmapArray = new byte[totalFrames][];
for (int x=0; x<totalFrames; x++) {
    File file = null;
    if (cWidth <= cHeight){
            file = new File(directory + "/f"+x+".jpg");
    } else {
            file = new File(directory + "/f"+x+"-land.jpg");
    }
    bitmapArray[x] = getBytesFromFile(file);
    imagesLoaded = x + 1;
}


public byte[] getBytesFromFile(File file) {
    byte[] bytes = null;
    try {

        InputStream is = new FileInputStream(file);
        long length = file.length();

        bytes = new byte[(int) length];

        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
            offset += numRead;
        }

        if (offset < bytes.length) {
            throw new IOException("Could not completely read file " + file.getName());
        }

        is.close();
    } catch (IOException e) {
                  //TODO Write your catch method here
    }
    return bytes;
}

最后,他们被写入到屏幕上,像这样:

Eventually, they get written to screen like so:

SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
    c = holder.lockCanvas();
    if (c != null) {            
        int canvasWidth = c.getWidth();
        int canvasHeight = c.getHeight();
        Rect destinationRect = new Rect();
        destinationRect.set(0, 0, canvasWidth, canvasHeight);
        c.drawBitmap(BitmapFactory.decodeByteArray(bitmapArray[bgcycle], 0, bitmapArray[bgcycle].length), null, destinationRect, null);
    }
} finally {
    if (c != null)
    holder.unlockCanvasAndPost(c);
}

我是正确,有一些重复会在这里呢?或者是有只是多少开销参与这样的ByteArray?

Am I correct that there is some sort of duplication going on here? Or is there just that much overhead involved in storing jpgs in a byteArray like this?

推荐答案

在RAM存储字节是存储在硬盘上的数据完全不同的......还有很多更多的开销吧。的对象,以及引用的字节数组结构中的所有占用更多的内存。是不是真的有一个单一来源的所有额外的内存,但只记得不是把文件加载到RAM通常占用2〜3倍的空间(从经验,我怕我不能在这里引用的任何文档)。

Storing bytes in RAM is very different to storing data on hard drives... There is alot more overhead to it. The references to the objects as well the byte array structures all take up additional memory. There isn't really a single source to all the additional memory but just remember than loading a file into RAM normally takes up 2 ~ 3x more space (from experience, I'm afraid I can't quote any documentation here).

考虑一下:

File F = //Some file here (Less than 2 GB please)
FileInputStream fIn = new FileInputStream(F);
ByteArrayOutputStream bOut = new ByteArrayOutputStream(((int)F.length()) + 1);

int r;
byte[] buf = new byte[32 * 1000];

while((r = fIn.read(buf) != -1){
    bOut.write(buf, 0, r);
}

//Do a memory measurement at this point. You'll see your using nearly 3x the memory in RAM compared to the file.
//If your actually gonna try this, remember to surround with try-catch and close the streams as appropriate.

还记得不使用的内存并不会立即清理。该方法getBytesFromFile()可以返回一个字节数组,这会导致它可能不会立即被垃圾回收内存重复的副本。如果你想成为安全,检查方法getBytesFromFile(文件)不漏应清理的任何引用。因为你只把它的时间是有限的,不会出现内存泄漏。

Also remember that unused memory is not instantly cleared up. The method getBytesFromFile() may be returning a copy of a byte array which causes memory duplication which may not immediately be garbage collected. If you want to be safe, check the method getBytesFromFile(file) is not leaking any references that should be cleaned up. It won't appear as a memory leak as you only call it a finite number of times.

这篇关于在存放的字节数组图像时内存问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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