c# - Performance tips mapping indexers to objects -
given following code able access pixels of image , map them color
struct.
to eye though looks inefficient since every time access indexer reading array 4 times. takes 9 seconds on computer run.
what looking example of how optimise code. i'm guessing can sort of reference array using unsafe code , read in 1 move have yet find decent guide explain how , how apply approach other situations.
while code example on own aid me, explanation of going on , why improve performance more beneficial myself , reading.
public class program { public static void main(string[] args) { image img = new image(10000,10000); stopwatch stopwatch = new stopwatch(); stopwatch.start(); (int y = 0; y < img.height; y++) { (int x = 0; x < img.width; x++) { color color = img[x,y]; } } stopwatch.stop(); console.writeline( string.format("time: {0} ms", stopwatch.elapsedmilliseconds)); console.readkey(); } } // define other methods , classes here public class image { private float[] pixels; public image (int width, int height){ pixels = new float[width * height * 4]; this.width = width; this.height = height; } public int width { get; private set; } public int height { get; private set; } public color this[int x, int y] { { int start = ((y * this.width) + x) * 4; return new color(this.pixels[start], this.pixels[start + 1], this.pixels[start + 2], this.pixels[start + 3]); } set { int start = ((y * this.width) + x) * 4; this.pixels[start] = value.r; this.pixels[start + 1] = value.g; this.pixels[start + 2] = value.b; this.pixels[start + 3] = value.a; } } } public struct color { public color (float r, float g, float b, float a):this(){ this.r = r; this.g = g; this.b = b; this.a = a; } public float r {get;set;} public float g {get;set;} public float b {get;set;} public float {get;set;} }
update
so investigation i've been able perform improvements using unsafe code.
here's 1 approach indexer:
public unsafe class image { private byte* pixels; public image (int width, int height){ fixed(byte* p = &(new byte[width * height * 4])[0]){ this.pixels = p; } this.width = width; this.height = height; } public int width { get; private set; } public int height { get; private set; } public color this[int x, int y] { { return *((color*)(this.pixels + ((y * this.width) + x) * 4)); } set { color* c = (color*)(this.pixels + (((y * this.width) + x) * 4)); c->r = value.r; c->g = value.g; c->b = value.b; c->a = value.a; } } }
this around 50% faster concerned happens pixels
property. ever cleaned garbage collector? should image implementing idisposable
so can set value null?
here's second approach:
public unsafe class image { private byte[] pixels; public image (int width, int height){ pixels = new byte[width * height * 4]; this.width = width; this.height = height; } public int width { get; private set; } public int height { get; private set; } public color this[int x, int y] { { fixed(byte* p = &this.pixels[0]){ return *((color*)(p + ((y * this.width) + x) * 4)); } } set { fixed(byte* p = &this.pixels[0]){ color* c = (color*)(p + (((y * this.width) + x) * 4)); c->r = value.r; c->g = value.g; c->b = value.b; c->a = value.a; } } } }
this 28% faster , far can determine means not have further manage memory.
are there obvious flaws in either approach?
you're working exclusively 32-bit pixels. why use byte[]
@ all, when can use uint[]
instead, , use color.fromargb
?
buffer.blockcopy
can used efficiently copy between byte[]
, uint[]
(and other value type afaict), if you're reading file, that's 1 option. using unsafe code another. in both cases, pay lot of attention bounds checking - you're losing lot of memory safety guarantees.
if you're going bare-bones speed, you're going need lot of unsafe code. that's tricky, make sure need speed - profiling application whole idea.
Comments
Post a Comment