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

Reply via email to