Danny D
Danny D

Reputation: 875

System.Drawing.Image Caching for better perfomance

I am trying to optimize a graphics process that reads hundreds of images from disk, processes them and produce a single image, the process i am trying to optimize is the reading of images from disk over and over again, one of the option i am considering is reading and caching the images in memory . in the simplest form i want to use a dictionary as follows.

UPDATE:

Is this a good idea ?, most importantly will it work?

public class ImageCache
{
    protected Dictionary<string, System.Drawing.Image> ImageStore = new   Dictionary<string, System.Drawing.Image>(10000);




 public System.Drawing.Image Get(ImageReference imgRef)
 {
      System.Drawing.Image image;

        if (!ImageStore.TryGetValue(imgRef.Key, out image))
           image= CacheImageFromDisk(imageRef);
       return image;
 }

 System.Drawing.Image CacheImageFromDisk(ImageReference imgRef)
    {
      using (var f = new FileStream(imgRef.Path, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            var img=Image.FromStream(f);
            ImageStore.Add(imgRef.Key,img);
            return img;
        }
  }

    ~ImageCache()
    {
       //Dispose each item in ImageStore  and calll GC.Collect()
    }
}

Upvotes: 1

Views: 991

Answers (4)

paparazzo
paparazzo

Reputation: 45096

The concern is memory.
Once you fill up memory then you are back to disk IO.
Do you have enough memory for the single image you are building and all the source files.
If you start paging out the single image you are building to disk then performance might degrade.

For optimization look at why you are going back to files.
Can you stream line the process to use a single source file at a time and be done with it.
Or can you at least deal with a block of source files and be done with them.

A dictionary is a proper way to manage the set.
But an expiration is not a very sophisticated way to manage size.
Need to clear the dictionary based on memory used.
If the app starts paging to disk then that is bad.

As for optimal memory size use performance counters and track page file usage.
But zero is not the target as you will get some paging going on.
My experience is MSSQL will take memory right up the max and hold it there (unless you constrain it). Your app my start paging out at 80%.
There is not a standard %.

Back to can your app not be smarter about when it uses and is done with files?

If you cannot fit all in memory then best bang for the buck is a solid state disk.

Upvotes: 0

techno
techno

Reputation: 6500

I would say that caching the images in the Primary memory is a very bad idea.The memory could get used up and even cause problems to the stability of the whole system.The higher resolution images may be about 20 mb,how many will you cache?

Upvotes: 0

Lukasz Madon
Lukasz Madon

Reputation: 14994

most importantly will it work?

It could.

Is this a good idea?

That depends on how many duplicates/images that you reuse are there. Caching is a trade-off between memory and performance. You have to check wherever it give you a significant speed-up and even more importly if this is the bottleneck of the app(IO tends to be hard to profile).

Upvotes: 0

Felice Pollano
Felice Pollano

Reputation: 33252

It is a good idea in order to me, and at a first glance code seems to work. Consider anyway:

  • Thread safety: if you have more than one thread working on the image, your chache is not thread safe at the moment.
  • Memory consumption: Image are sometimes memory consuming, pay attention that this could harm the process, or even slow down the performance due to memory swapping, in this case you will feel the program slower than having the cache on!

Upvotes: 1

Related Questions