Hi, Just as a little exercise I decided to try out a Mandelbrot test in MonoTouch just to have a look at performance. I took this Objective-C implementation https://github.com/ddeville/Mandelbrot-set-on-iPhone on GitHub as a basis and ported the implementation of the view 1-to-1 to MonoTouch. Because of some differences in API not all of the code is 100% the same, and I'm no CoreGraphics expert, but as far as I know this looks OK. The MonoTouch implementation can be found here http://dl.dropbox.com/u/1135505/MonobrotSet.zip
Now when I run this on my iPhone, the MonoTouch version is 2.8 times slower than the Objective-C version, specifically the part where the Mandelbrot Set is drawn in the bitmap. Objective-C takes ~0.99 seconds, MonoTouch ~2.8 seconds. Can anyone help explain where the overhead is coming from? Is there anything I could have done to make this faster given the reference implementation in Objective-C? I'm not looking for a faster Mandelbrot algorithm but merely trying to explain what is making the big difference. Or did I make a mistake in translating the Objective-C code to MonoTouch? Here's the C# code that does the work, I tried to stay as close as possible to the Objective-C implementation of the view https://github.com/ddeville/Mandelbrot-set-on-iPhone/blob/master/Classes/MandelbrotView.m (link) [Register("MandelbrotView")] public class MandelbrotView: UIView { private const int MANDELBROT_STEPS = 50; public MandelbrotView () { Initialize(); } public MandelbrotView(IntPtr handle): base (handle) { Initialize(); } public override void Draw (System.Drawing.RectangleF rect) { DateTime reference = DateTime.Now; // get an image representation of the bitmap context var image = _bitmapContext.ToImage(); // draw the image in the current context var context = UIGraphics.GetCurrentContext(); context.DrawImage(rect, image); // release the image image.Dispose(); Console.WriteLine("draw rect duration = {0}", (DateTime.Now - reference).TotalMilliseconds / 1000); } private CGBitmapContext _bitmapContext; private void Initialize () { Console.WriteLine("MonoTouch Mandelbrot implementation"); var reference = DateTime.Now; // instantiate the bitmap context _bitmapContext = CreateCustomBitmapContextWithSize(new SizeF(480.0f, 320.0f)); Console.WriteLine("bitmap context creation duration = {0}", (DateTime.Now - reference).TotalMilliseconds / 1000); reference = DateTime.Now; // draw the Mandelbrot Set var center = new PointF(this.Center.Y, this.Center.X); DrawMandelbrot(center, 1); Console.WriteLine("drawing mandelbrot in bitmap duration = {0}", (DateTime.Now - reference).TotalMilliseconds / 1000); } private CGBitmapContext CreateCustomBitmapContextWithSize(SizeF size) { CGBitmapContext context = null ; var bitmapBytesPerRow = (size.Width * 4) ; bitmapBytesPerRow += (16 - bitmapBytesPerRow%16)%16 ; var bitmapByteCount = (bitmapBytesPerRow * size.Height) ; CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB(); var bitmapData = new byte[(int) bitmapByteCount]; context = new CGBitmapContext(bitmapData, (int) size.Width, (int) size.Height, 8, (int) bitmapBytesPerRow, colorSpace, CGBitmapFlags.PremultipliedLast); if (context == null) { bitmapData = null; Console.WriteLine("Context not created!"); return null; } return context; } private void DrawMandelbrot(PointF center, float zoom) { _bitmapContext.SetAllowsAntialiasing(false); _bitmapContext.SetRGBFillColor(0.0f, 0.0f, 0.0f, 1.0f); float re; float im; // mapping the bounding box to pixels // zoom 1 has to be between -2 and 1 and -1 to 1 // any additional zoom divides these by the zoom // loop through every pixel of the frame... for (int i = 0 ; i < 480 ; i++) { for (int j = 0 ; j < 320 ; j++) { re = (((float)i - 1.33f * center.X)/160) ; // -2 to 1 - screen width = 480 im = (((float)j - 1.00f * center.Y)/160) ; // -1 to 1 - screen height = 320 re /= zoom ; im /= zoom ; if (IsInMandelbrotSet(re, im)) { _bitmapContext.FillRect(new RectangleF(i, j, 1.0f, 1.0f)); } } } } private bool IsInMandelbrotSet(float re, float im) { float x = 0 ; float nx ; float y = 0 ; float ny ; bool fl = true; for(int i = 0 ; i < MANDELBROT_STEPS ; i++) { // We calculate the real part of the sequence nx = x*x - y*y + re ; // We calculate the imaginary part of the sequence ny = 2*x*y + im ; // We compute the magnitude at each step // We check if it's greater than 2 if((nx*nx + ny*ny) > 4) { fl = false ; break ; } x = nx ; y = ny ; } return fl ; } } Thanks, Roy -- View this message in context: http://monotouch.2284126.n4.nabble.com/Why-is-the-MonoTouch-version-of-this-Mandelbrot-Set-test-2-8-times-slower-tp4389869p4389869.html Sent from the MonoTouch mailing list archive at Nabble.com. _______________________________________________ MonoTouch mailing list [email protected] http://lists.ximian.com/mailman/listinfo/monotouch
