Reputation: 4013
var source = new Bitmap(2000,2000);
var sw = Stopwatch.StartNew();
for (int i = 0; i < 10000; i++)
{
//var copy = new Bitmap(source);
var copy = source.Clone() as Bitmap;
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
The code runs in under 10 ms with my System, and the Ram usage stayes the same. With this timer and Ram usage results there cannot be a copy of the Bitmapdata.
But when I do this.
var copy2 = source.Clone() as Bitmap;
for (int x = 0; x < copy2.Width; x++)
{
for (int y = 0; y < copy2.Height; y++)
{
copy2.SetPixel(x, y, Color.Red);
}
}
// copy2 is Red
// source is NOT!!
How is this possible?
Upvotes: 2
Views: 277
Reputation: 61952
Your source
is copied 10,000 times. The call to Clone()
cannot be optimized away because the compiler does not know what side-effects the method call might have.
Of course, your clones are not kept, so the Garbage Collector may choose to get rid of them very soon (maybe while the loop is still running).
You can also keep the clones. Try this:
var source = new Bitmap(2000, 2000);
var li = new List<Bitmap>();
var sw = Stopwatch.StartNew();
for (int i = 0; i < 10000; i++)
{
li.Add((Bitmap)source.Clone());
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.WriteLine(li.Count);
li[4321].SetPixel(1234, 123, Color.Blue);
Console.WriteLine(li[1234].GetPixel(1234, 123)); // checks if a pixel of another clone also changed to blue
Edit: It does seem like the cloning is "lazy" in some sense. The above code runs very fast and doesn't use much memory. The same thing seems to happen even if source
is a very complex bitmap, so it's not just something that happens when the source
bitmap can be "compressed" very much.
If, after you build up the above list li
, you run the following code:
var randomNumberGenerator = new Random();
for (int x = 0; x < 10000; ++x)
{
for (int i = 0; i < 2000; ++i)
for (int j = 0; j < 2000; ++j)
li[x].SetPixel(i, j, System.Drawing.Color.FromArgb(randomNumberGenerator.Next()));
Console.WriteLine(x);
}
you will see the memory consumption of the application rise slowly but steadily.
Upvotes: 2
Reputation: 19496
The reason your first code snippet is running so quickly is very likely because the optimizer sees that copy
is never used and just cuts it out. If you change your inner loop to:
var copy = source.Clone() as Bitmap;
var copy2 = copy;
...it will likely trick the compiler into actually generating IL code to clone the bitmap and you will see the elapsed time go up.
Upvotes: 1