# F# vs C# performance

**URL:** <https://forums.fsharp.org/t/f-vs-c-performance/3605>\
**Category:** General\
**Tags:** beginners\
**Created:** [April 13, 2024, 1:44am UTC](https://forums.fsharp.org/t/f-vs-c-performance/3605 "2024-04-13T01:44:39Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![altbodhi](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/altbodhi/32/1253_2.png) [@altbodhi](https://forums.fsharp.org/u/altbodhi)\
**Post date:** [April 13, 2024, 1:44am UTC](https://forums.fsharp.org/t/f-vs-c-performance/3605/1 "2024-04-13T01:44:39Z")

</div>

I do not understand why F# so slow

```auto
let inline swap<'a> (a: byref<'a>, b: byref<'a>) =
    let t = a
    a <- b
    b <- t

let sort arr =
    let ln = Array.length arr

    for i = 0 to ln - 1 do
        for j = 0 to ln - 2 - i do
            if arr.[j + 1] < arr.[j] then
                swap (&arr.[j + 1], &arr.[j])

let doTest () =
    let max = 100_000
    let value = float (max)

    let arr =
        Array.init max (fun i -> value - float (i))

    sort arr
    printfn "%A" (arr.[0..5])

#time

doTest ()

```

It is very slow (few minutes).  
Analog on C# take above few seconds. Why?  
Original cod here [vostok/example/BubbleSort.mod at master · Vostok-space/vostok (github.com)](https://github.com/Vostok-space/vostok/blob/master/example/BubbleSort.mod)  
(Interesting post about result for it on Oberon(simple language from Nicolaus Wirth) [Восток: Скорость пузырьковой сортировки на Oberon, C++, Go, Rust (vostok-space.blogspot.com)](https://vostok-space.blogspot.com/2016/11/oberon-c-go-rust.html))

```auto
using System.Runtime.CompilerServices;

var m = 100_000;
var a = new double[m];
var s = (double)m;
for (var i = 0; i < m; i++)
{
    a[i] = s;
    s = s - 1;
}

Sort(a);

Console.WriteLine(a[0]);

static void Sort(double[] a)
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    void Swap(ref double x, ref double y)
    {
        var t = x;
        x = y;
        y = t;
    };

    for (var i = 0; i < a.Length; i++)
        for (var j = 0; j < (a.Length - 1 - i); j++)
            if (a[j + 1] < a[j])
                Swap(ref a[j + 1], ref a[j]);
}

```

---

<div class="post-metadata">

**Author:** ![davidbruce](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/davidbruce/32/1286_2.png) [@davidbruce](https://forums.fsharp.org/u/davidbruce)\
**Post date:** [April 13, 2024, 9:52pm UTC](https://forums.fsharp.org/t/f-vs-c-performance/3605/2 "2024-04-13T21:52:02Z")

</div>

I’m new to F# so I can’t really offer an explanation, but the following change on my local machine dramatically improves performance:

```auto
let sort arr =

```

to

```auto
let sort (arr: float array) =

```

Without the type annotation I ended up having to kill FSI after a few minutes. With the annotation I get the following:

```auto
[|1.0; 2.0; 3.0; 4.0; 5.0; 6.0|]
Real: 00:00:08.292, CPU: 00:00:00.201, GC gen0: 0, gen1: 0, gen2: 0

```

I would love to know what’s going on here myself. It must have something to do with the generic function not properly passing by reference or something?

I’m on an M1 Mac with .NET 7.0.100.

---

<div class="post-metadata">

**Author:** ![qnc](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/qnc/32/1382_2.png) [@qnc](https://forums.fsharp.org/u/qnc)\
**Post date:** [June 6, 2024, 3:09am UTC](https://forums.fsharp.org/t/f-vs-c-performance/3605/3 "2024-06-06T03:09:39Z")

</div>

The `arr` parameter in the first version using type inference is constrained to be 'a when 'a: comparison, so the what the fifth line does is to call `LanguagePrimitives.HashCompare.GenericLessThanIntrinsic` which is costly due to boxing. In C# version or non-polymorphic version, there’s no such a problem.

---

<div class="post-metadata">

**Author:** ![qnc](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/qnc/32/1382_2.png) [@qnc](https://forums.fsharp.org/u/qnc)\
**Post date:** [June 8, 2024, 3:15am UTC](https://forums.fsharp.org/t/f-vs-c-performance/3605/4 "2024-06-08T03:15:44Z")

</div>

Update: Mark the function as inline then the compiler will expand the difinition at the callsite according to concrete type of arr’s elements instead of uniformly apply intrinsic function.
