There are currently two main options to create custom code-based modules on Azure IoT Edge:
So now my question is, what would be the benefit of using one over the other when I want to write custom code in .NET Core (C#)?
There is much less boilerplate code required for the Function but how about things like performance?
I don't know. Let's bench! ...on Windows cause that's what i had handy. CPU is Core i7-3770K.
.NET Core Web API (v2.1.3, middleware is whatever dotnet new webapi wires up) —
public class ValuesController : Controller
{
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}
Azure Functions script host (v2.0.11587.0) —
// run.csx
public static IEnumerable<string> Run(HttpRequest req)
{
    return new string[] { "value1", "value2" };
}
// host.json
// Default "consoleLevel" is verbose which blocks on flushing stdout,
// performance suffered unnecessarily so i switched to "error".
{
    "tracing": {
      "consoleLevel": "error",
      "fileLoggingMode": "debugOnly"
    }
}

Results:
// .NET Core Web API
C:\lab\bomb>bombardier-windows-amd64.exe -n 654321 http://127.0.0.1:5000/api/values
Bombarding http://127.0.0.1:5000/api/values with 654321 requests using 125 connections
 654321 / 654321 [===================================] 100.00% 23s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     27744.21    6713.91  124074.44
  Latency        4.45ms   200.44us    46.97ms
  HTTP codes:
    1xx - 0, 2xx - 654321, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:     6.69MB/s
// Functions script host with .csx
C:\lab\bomb>bombardier-windows-amd64.exe -n 654321 http://127.0.0.1:7071/api/HttpTrigger
Bombarding http://127.0.0.1:7071/api/HttpTrigger with 654321 requests using 125 connections
 654321 / 654321 [===================================] 100.00% 5m31s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec      1976.64     181.69    4213.32
  Latency       63.23ms    20.74ms      2.12s
  HTTP codes:
    1xx - 0, 2xx - 654321, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:   492.23KB/s
I did a test run with precompiled functions (.DLL) as well, for the sake of science, both on v2 (.NET Core) and v1 (.NET Full Framework) runtime.
.NET Core Web API (v2.1.3):                             27744 requests/sec
Functions script host (v2.0.11587.0) .csx:               1976 requests/sec
Functions script host (v2.0.11587.0) precompiled DLL:    2062 requests/sec
Functions script host (v1.0.11535.0) precompiled DLL:    4734 requests/sec
YMMV. Things may look different if you actually crunch some IO not just return 16 bytes on the wire from memory. But it is what it is. If you don't need the extra goodies Functions give you, go raw dotnet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With