diff --git a/frameworks/CSharp/wiredio/Benchmarks/Benchmarks.csproj b/frameworks/CSharp/wiredio/Benchmarks/Benchmarks.csproj
deleted file mode 100644
index 627c09fb8c8..00000000000
--- a/frameworks/CSharp/wiredio/Benchmarks/Benchmarks.csproj
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- Exe
- net9.0
- 13.0
- enable
- enable
-
- true
- true
-
-
- linux-musl-x64
- true
-
-
-
-
-
-
-
-
diff --git a/frameworks/CSharp/wiredio/Benchmarks/Program.cs b/frameworks/CSharp/wiredio/Benchmarks/Program.cs
deleted file mode 100644
index 8a41b222386..00000000000
--- a/frameworks/CSharp/wiredio/Benchmarks/Program.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System.Net;
-using System.Text.Json;
-using Wired.IO.App;
-using Wired.IO.Http11.Response.Content;
-using Wired.IO.Protocol.Response;
-using StringContent = Wired.IO.Http11.Response.Content.StringContent;
-
-var builder = WiredApp.CreateBuilder();
-
-await builder
- .Endpoint(IPAddress.Any, 8080)
- .MapGet("/plaintext", scope => context =>
- {
- context
- .Respond()
- .Status(ResponseStatus.Ok)
- .Content(new StringContent("Hello, World!"))
- .Type("text/plain");
- })
- .MapGet("/json", scope => context =>
- {
- context
- .Respond()
- .Status(ResponseStatus.Ok)
- .Content(new JsonContent(new
- {
- Message = "Hello, World!"
- }, JsonSerializerOptions.Default))
- .Type("application/json");
- })
- .Build()
- .RunAsync();
\ No newline at end of file
diff --git a/frameworks/CSharp/wiredio/README.md b/frameworks/CSharp/wiredio/README.md
index 4f137ae45c2..7b852008832 100644
--- a/frameworks/CSharp/wiredio/README.md
+++ b/frameworks/CSharp/wiredio/README.md
@@ -10,13 +10,13 @@ See the [Wired.IO Documentation](https://mda2av.github.io/Wired.IO.Docs/) for mo
**Platforms**
-* .NET 8/9
+* .NET 9
**Web Servers**
* [Wired.IO](https://github.com/MDA2AV/Wired.IO)
-## Paths & Source for Tests
+**Engines**
-* [Plaintext](Benchmarks/Program.cs): "/plaintext"
-* [JSON](Benchmarks/Program.cs): "/json"
+* [Wired.IO](https://github.com/MDA2AV/Wired.IO)
+* [Unhinged](https://github.com/MDA2AV/Unhinged)
\ No newline at end of file
diff --git a/frameworks/CSharp/wiredio/benchmark_config.json b/frameworks/CSharp/wiredio/benchmark_config.json
index f136d0588b7..e74c7696415 100644
--- a/frameworks/CSharp/wiredio/benchmark_config.json
+++ b/frameworks/CSharp/wiredio/benchmark_config.json
@@ -1,5 +1,6 @@
{
"framework": "wiredio",
+ "maintainers": ["MDA2AV"],
"tests": [
{
"default": {
@@ -17,8 +18,25 @@
"os": "Linux",
"database_os": "Linux",
"display_name": "Wired.IO",
- "notes": "Only plaintext and JSON benchmarks implemented"
+ "notes": "Only plaintext and JSON benchmarks implemented yet"
+ },
+ "plt": {
+ "plaintext_url": "/plaintext",
+ "json_url": "/json",
+ "port": 8080,
+ "approach": "Realistic",
+ "classification": "Platform",
+ "database": "None",
+ "framework": "Unhinged",
+ "language": "C#",
+ "orm": "None",
+ "platform": ".NET",
+ "webserver": "Unhinged",
+ "os": "Linux",
+ "database_os": "Linux",
+ "display_name": "Wired.IO [Unhinged]",
+ "notes": "Not a framework"
}
}
]
-}
\ No newline at end of file
+}
diff --git a/frameworks/CSharp/wiredio/config.toml b/frameworks/CSharp/wiredio/config.toml
index 55e724fde37..fe292c91330 100644
--- a/frameworks/CSharp/wiredio/config.toml
+++ b/frameworks/CSharp/wiredio/config.toml
@@ -12,3 +12,15 @@ orm = "None"
platform = ".NET"
webserver = "Wired.IO"
versus = "None"
+
+[plt]
+urls.plaintext = "/plaintext"
+urls.json = "/json"
+approach = "Realistic"
+classification = "Platform"
+os = "Linux"
+database_os = "Linux"
+orm = "None"
+platform = ".NET"
+webserver = "Unhinged"
+versus = "None"
\ No newline at end of file
diff --git a/frameworks/CSharp/wiredio/src/Fullstack/Fullstack.csproj b/frameworks/CSharp/wiredio/src/Fullstack/Fullstack.csproj
new file mode 100644
index 00000000000..437ed45a428
--- /dev/null
+++ b/frameworks/CSharp/wiredio/src/Fullstack/Fullstack.csproj
@@ -0,0 +1,26 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ true
+ true
+ true
+ true
+
+
+ linux-musl-x64
+ true
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/CSharp/wiredio/src/Fullstack/Program.cs b/frameworks/CSharp/wiredio/src/Fullstack/Program.cs
new file mode 100644
index 00000000000..9450ba93892
--- /dev/null
+++ b/frameworks/CSharp/wiredio/src/Fullstack/Program.cs
@@ -0,0 +1,59 @@
+using System.IO.Pipelines;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Wired.IO.App;
+
+namespace Fullstack;
+
+internal class Program
+{
+ public static async Task Main(string[] args)
+ {
+ var expressBuilder = WiredApp.CreateExpressBuilder();
+
+ await expressBuilder
+ .Port(8080)
+ .MapGet("/json", scope => async ctx =>
+ {
+ var payload = new JsonMessage { Message = JsonBody };
+ var myHandler = CreateBoundHandler(ctx.Writer, payload);
+
+ ctx
+ .Respond()
+ .Type("application/json"u8)
+ .Content(myHandler, 27);
+
+ })
+ .MapGet("/plaintext", scope => async ctx =>
+ {
+ ctx
+ .Respond()
+ .Type("text/plain"u8)
+ .Content(_plainTextBody);
+ })
+ .Build()
+ .RunAsync();
+ }
+
+ private static ReadOnlySpan _plainTextBody => "Hello, World!"u8;
+ private const string JsonBody = "Hello, World!";
+
+ [ThreadStatic]
+ private static Utf8JsonWriter? t_writer;
+ private static readonly Action StaticHandler = HandleFast;
+ private static Action CreateBoundHandler(PipeWriter writer, JsonMessage message) => () => StaticHandler.Invoke(writer, message);
+ private static void HandleFast(PipeWriter writer, JsonMessage message)
+ {
+ var utf8JsonWriter = t_writer ??= new Utf8JsonWriter(writer, new JsonWriterOptions { SkipValidation = true });
+ utf8JsonWriter.Reset(writer);
+ JsonSerializer.Serialize(utf8JsonWriter, message, SerializerContext.JsonMessage);
+ }
+
+ private static readonly JsonContext SerializerContext = JsonContext.Default;
+}
+
+public struct JsonMessage { public string Message { get; set; } }
+
+[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Serialization | JsonSourceGenerationMode.Metadata)]
+[JsonSerializable(typeof(JsonMessage))]
+public partial class JsonContext : JsonSerializerContext { }
\ No newline at end of file
diff --git a/frameworks/CSharp/wiredio/src/Platform/Platform.csproj b/frameworks/CSharp/wiredio/src/Platform/Platform.csproj
new file mode 100644
index 00000000000..1fd01bf2e63
--- /dev/null
+++ b/frameworks/CSharp/wiredio/src/Platform/Platform.csproj
@@ -0,0 +1,25 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ true
+ true
+ true
+ true
+
+
+ linux-musl-x64
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/CSharp/wiredio/src/Platform/Program.cs b/frameworks/CSharp/wiredio/src/Platform/Program.cs
new file mode 100644
index 00000000000..0b76948f66f
--- /dev/null
+++ b/frameworks/CSharp/wiredio/src/Platform/Program.cs
@@ -0,0 +1,99 @@
+// ReSharper disable always SuggestVarOrType_BuiltInTypes
+// (var is avoided intentionally in this project so that concrete types are visible at call sites.)
+// ReSharper disable always StackAllocInsideLoop
+
+using System.Runtime.CompilerServices;
+using System.Text.Json;
+using Unhinged;
+
+#pragma warning disable CA2014
+
+/* (MDA2AV)Dev notes:
+ *
+ * Wired.IO Platform benchmark using [Unhinged - https://github.com/MDA2AV/Unhinged] epoll engine.
+ *
+ * This test was created purely for benchmark/comparison between .NET solutions.
+ * It should not be considered EVER as a go-to framework to build any kind of webserver!
+ * For such purpose please use the main Wired.IO framework [Wired.IO - https://github.com/MDA2AV/Wired.IO].
+ *
+ * This benchmarks follows the JsonSerialization and PlainText rules imposed by the TechEmpower team.
+ *
+ * The Http parsing by the Unhinged engine is still naive(work in progress), yet it's development will not have any impact
+ * on these benchmarks results as the extra request parsing overhead is much smaller than the read/send syscalls'.
+ */
+
+namespace Platform;
+
+[SkipLocalsInit]
+internal static class Program
+{
+ public static void Main(string[] args)
+ {
+ var builder = UnhingedEngine
+ .CreateBuilder()
+ .SetPort(8080)
+
+
+ // Number of working threads
+ // Reasoning behind Environment.ProcessorCount / 2
+ // It's the number of real cpu cores not cpu threads
+ // This can improve the cache hits on L1/L2 since only one thread
+ // is running per cpu core.
+ .SetNWorkersSolver(() => Environment.ProcessorCount/2)
+
+ // Accept up to 16384 connections
+ .SetBacklog(16384)
+
+ // Max 512 epoll events per wake (quite overkill)
+ .SetMaxEventsPerWake(512)
+
+ // Max 1024 connection per thread
+ .SetMaxNumberConnectionsPerWorker(1024)
+
+ // 32KB in and 16KB out slabs to handle 16 pipeline depth
+ .SetSlabSizes(32 * 1024, 16 * 1024)
+ .InjectRequestHandler(RequestHandler);
+
+ var engine = builder.Build();
+ engine.Run();
+ }
+
+ private static void RequestHandler(Connection connection)
+ {
+ // FNV-1a Hashed routes to avoid string allocations
+ if(connection.HashedRoute == 291830056) // /json
+ CommitJsonResponse(connection);
+
+ else if (connection.HashedRoute == 3454831873) // /plaintext
+ CommitPlainTextResponse(connection);
+ }
+
+ [ThreadStatic] private static Utf8JsonWriter? t_utf8JsonWriter;
+ private static readonly JsonContext SerializerContext = JsonContext.Default;
+ private static void CommitJsonResponse(Connection connection)
+ {
+ connection.WriteBuffer.WriteUnmanaged("HTTP/1.1 200 OK\r\n"u8 +
+ "Server: W\r\n"u8 +
+ "Content-Type: application/json; charset=UTF-8\r\n"u8 +
+ "Content-Length: 27\r\n"u8);
+ connection.WriteBuffer.WriteUnmanaged(DateHelper.HeaderBytes);
+
+ t_utf8JsonWriter ??= new Utf8JsonWriter(connection.WriteBuffer, new JsonWriterOptions { SkipValidation = true });
+ t_utf8JsonWriter.Reset(connection.WriteBuffer);
+
+ // Creating(Allocating) a new JsonMessage every request
+ var message = new JsonMessage { Message = "Hello, World!" };
+ // Serializing it every request
+ JsonSerializer.Serialize(t_utf8JsonWriter, message, SerializerContext.JsonMessage);
+ }
+
+ private static void CommitPlainTextResponse(Connection connection)
+ {
+ connection.WriteBuffer.WriteUnmanaged("HTTP/1.1 200 OK\r\n"u8 +
+ "Server: W\r\n"u8 +
+ "Content-Type: text/plain\r\n"u8 +
+ "Content-Length: 13\r\n"u8);
+ connection.WriteBuffer.WriteUnmanaged(DateHelper.HeaderBytes);
+ connection.WriteBuffer.WriteUnmanaged("Hello, World!"u8);
+ }
+}
\ No newline at end of file
diff --git a/frameworks/CSharp/wiredio/wiredio-plt.dockerfile b/frameworks/CSharp/wiredio/wiredio-plt.dockerfile
new file mode 100644
index 00000000000..9bd497eec84
--- /dev/null
+++ b/frameworks/CSharp/wiredio/wiredio-plt.dockerfile
@@ -0,0 +1,22 @@
+# Build
+FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
+RUN apk add --no-cache clang build-base zlib-dev linux-headers
+WORKDIR /src
+COPY src/Platform/ ./Platform/
+WORKDIR /src/Platform
+RUN dotnet publish -c Release \
+ -r linux-musl-x64 \
+ --self-contained true \
+ -p:PublishAot=true \
+ -p:OptimizationPreference=Speed \
+ -p:GarbageCollectionAdaptationMode=0 \
+ -o /app/out
+
+# Runtime (musl)
+FROM mcr.microsoft.com/dotnet/runtime-deps:9.0-alpine
+ENV URLS=http://+:8080
+WORKDIR /app
+COPY --from=build /app/out ./
+RUN chmod +x ./Platform
+EXPOSE 8080
+ENTRYPOINT ["./Platform"]
diff --git a/frameworks/CSharp/wiredio/wiredio.dockerfile b/frameworks/CSharp/wiredio/wiredio.dockerfile
index 8c473477a61..2c6d853b0a2 100644
--- a/frameworks/CSharp/wiredio/wiredio.dockerfile
+++ b/frameworks/CSharp/wiredio/wiredio.dockerfile
@@ -1,24 +1,22 @@
+# Build
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
-WORKDIR /source
+RUN apk add --no-cache clang build-base zlib-dev linux-headers
+WORKDIR /src
+COPY src/Fullstack/ ./Fullstack/
+WORKDIR /src/Fullstack
+RUN dotnet publish -c Release \
+ -r linux-musl-x64 \
+ --self-contained true \
+ -p:PublishAot=true \
+ -p:OptimizationPreference=Speed \
+ -p:GarbageCollectionAdaptationMode=0 \
+ -o /app/out
-# copy csproj and restore as distinct layers
-COPY Benchmarks/*.csproj .
-RUN dotnet restore -r linux-musl-x64
-
-# copy and publish app and libraries
-COPY Benchmarks/ .
-RUN dotnet publish -c release -o /app -r linux-musl-x64 --no-restore --self-contained
-
-# final stage/image
+# Runtime (musl)
FROM mcr.microsoft.com/dotnet/runtime-deps:9.0-alpine
-
-ENV DOTNET_GCDynamicAdaptationMode=0
-ENV DOTNET_ReadyToRun=0
-ENV DOTNET_HillClimbing_Disable=1
-
+ENV URLS=http://+:8080
WORKDIR /app
-COPY --from=build /app .
-
-ENTRYPOINT ["./Benchmarks"]
-
+COPY --from=build /app/out ./
+RUN chmod +x ./Fullstack
EXPOSE 8080
+ENTRYPOINT ["./Fullstack"]