Swift vs. C# Performance

I am always a sucker for performance. Recently I migrated a .NET GDI+ app to Swift. There were several reasons for it:

  • GDI+ is no longer supported on MacOS with .NET 7.0
  • I thought using the native MacOS graphics libraries would be faster than running .NET on MacOS
  • I just wanted to learn Swift and its Graphics API

To my surprise the C# code runs way faster than Swift. The difference is not because of GDI+ vs Swift’s CoreGraphics but because of the more basic non-graphics operations. Think of the basic statements that come with a programming language. When I profiled the code, I found performance of GDI+ vs CoreGraphics was the same. The part where the performance differed was in executing non-graphics code. I wasn’t using any libraries at all in this code – just using the statements that come with the programming language.

I kept on digging further into the rabbit hole. What do we find? Let’s create a 2D array of bools and initialize it to random values. Below is the code in C# and Swift.

C#

public static int test(int width, int height) {
            var rand = new Random();
            var mask = new bool[height][];
            for (int i = 0; i < mask.Length; i++)
            {
                mask[i] = new bool[width];
            }
            int count = 0;
            for(int row = 0; row < height; row++) {
                for(int col = 0; col < width; col++) {
                    if (rand.Next(0, 2) == 1) {
                        mask[row][col] = true;
                        count++;
                    }
                }
            }
            return count;            
        }

Swift

static func test(_ width: Int, _ height: Int) -> UInt {
        var mask = Array(repeating: Array(repeating: false, count: width), count: height)
        var count: UInt = 0
        for row in 0..<height {            
            for col in 0..<width {
                if (Bool.random()) {
                    mask[row][col] = true
                    count += 1
                }
            }
        }
        return count
    }

What do we find when we run this code? When I did 100 iterations of above code with width = height = 3840 on a M1 Mac mini with 8GB RAM running Mac OS 13.1 (Ventura) here are the runtimes I got:

C# (.NET 6.0): 00:00:20.41 s

Swift (version 5.7.2): 157.7 s

The difference is staggering. C# is almost 8x faster than Swift! Let me know what you think.

For reference below is C# code to do 100 iterations:

Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            int width = Int32.Parse(args[0]);
            int height = Int32.Parse(args[1]);
            int n = Int32.Parse(args[2]);
            for (int i = 0; i < n; i++) {
                Array2D.test(width, height);
            }
            stopWatch.Stop();
            // Get the elapsed time as a TimeSpan value.
            TimeSpan ts = stopWatch.Elapsed;
            Console.WriteLine("completed {0} iterations", n);
            // Format and display the TimeSpan value.
            string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                ts.Hours, ts.Minutes, ts.Seconds,
                ts.Milliseconds / 10);
            Console.WriteLine("RunTime " + elapsedTime);

and corresponding Swift code:

let width = Int(CommandLine.arguments[1])!
        let height = Int(CommandLine.arguments[2])!
        let n = Int(CommandLine.arguments[3])!
        print("running \(n) loops of \(width)x\(height) 2d array test...")
        let clock = SuspendingClock()
        let t1 = clock.now
        for i in 1...n {
            // print("iteration \(i) of \(n)")
            test(width, height)
        }
        let t2 = clock.now
        print("\(t2-t1)")
This entry was posted in Computers, programming, Software and tagged . Bookmark the permalink.

Leave a comment