1+ // ReSharper disable always SuggestVarOrType_BuiltInTypes
2+ // (var is avoided intentionally in this project so that concrete types are visible at call sites.)
3+ // ReSharper disable always StackAllocInsideLoop
4+
5+ using System . Runtime . CompilerServices ;
6+ using System . Text . Json ;
7+ using Unhinged ;
8+
9+ #pragma warning disable CA2014
10+
11+ /* (MDA2AV)Dev notes:
12+ *
13+ * Wired.IO Platform benchmark using [Unhinged - https://github.com/MDA2AV/Unhinged] epoll engine.
14+ *
15+ * This test was created purely for benchmark/comparison between .NET solutions.
16+ * It should not be considered EVER as a go-to framework to build any kind of webserver!
17+ * For such purpose please use the main Wired.IO framework [Wired.IO - https://github.com/MDA2AV/Wired.IO].
18+ *
19+ * This benchmarks follows the JsonSerialization and PlainText rules imposed by the TechEmpower team.
20+ *
21+ * The Http parsing by the Unhinged engine is still naive(work in progress), yet it's development will not have any impact
22+ * on these benchmarks results as the extra request parsing overhead is much smaller than the read/send syscalls'.
23+ */
24+
25+ namespace Platform ;
26+
27+ [ SkipLocalsInit ]
28+ internal static class Program
29+ {
30+ public static void Main ( string [ ] args )
31+ {
32+ var builder = UnhingedEngine
33+ . CreateBuilder ( )
34+ . SetPort ( 8080 )
35+
36+ . SetNWorkersSolver ( ( ) => Environment . ProcessorCount )
37+
38+ // Accept up to 16384 connections
39+ . SetBacklog ( 16384 )
40+
41+ // Max 512 epoll events per wake (quite overkill)
42+ . SetMaxEventsPerWake ( 512 )
43+
44+ // Max 1024 connection per thread
45+ . SetMaxNumberConnectionsPerWorker ( 1024 )
46+
47+ // 32KB in and 16KB out slabs to handle 16 pipeline depth
48+ . SetSlabSizes ( 32 * 1024 , 16 * 1024 )
49+ . InjectRequestHandler ( RequestHandler ) ;
50+
51+ var engine = builder . Build ( ) ;
52+ engine . Run ( ) ;
53+ }
54+
55+ private const string Json = "/json" ;
56+ private const string PlainText = "/plaintext" ;
57+
58+ private static ValueTask RequestHandler ( Connection connection )
59+ {
60+ // FNV-1a Hashed routes to avoid string allocations
61+ if ( connection . H1HeaderData . Route == Json ) // /json
62+ CommitJsonResponse ( connection ) ;
63+
64+ else if ( connection . H1HeaderData . Route == PlainText ) // /plaintext
65+ CommitPlainTextResponse ( connection ) ;
66+
67+ return ValueTask . CompletedTask ;
68+ }
69+
70+ [ ThreadStatic ] private static Utf8JsonWriter ? t_utf8JsonWriter ;
71+ private static readonly JsonContext SerializerContext = JsonContext . Default ;
72+ private static void CommitJsonResponse ( Connection connection )
73+ {
74+ connection . WriteBuffer . WriteUnmanaged ( "HTTP/1.1 200 OK\r \n "u8 +
75+ "Server: W\r \n "u8 +
76+ "Content-Type: application/json; charset=UTF-8\r \n "u8 +
77+ "Content-Length: 27\r \n "u8 ) ;
78+ connection . WriteBuffer . WriteUnmanaged ( DateHelper . HeaderBytes ) ;
79+
80+ t_utf8JsonWriter ??= new Utf8JsonWriter ( connection . WriteBuffer , new JsonWriterOptions { SkipValidation = true } ) ;
81+ t_utf8JsonWriter . Reset ( connection . WriteBuffer ) ;
82+
83+ // Creating(Allocating) a new JsonMessage every request
84+ var message = new JsonMessage { Message = "Hello, World!" } ;
85+ // Serializing it every request
86+ JsonSerializer . Serialize ( t_utf8JsonWriter , message , SerializerContext . JsonMessage ) ;
87+ }
88+
89+ private static void CommitPlainTextResponse ( Connection connection )
90+ {
91+ connection . WriteBuffer . WriteUnmanaged ( "HTTP/1.1 200 OK\r \n "u8 +
92+ "Server: W\r \n "u8 +
93+ "Content-Type: text/plain\r \n "u8 +
94+ "Content-Length: 13\r \n "u8 ) ;
95+ connection . WriteBuffer . WriteUnmanaged ( DateHelper . HeaderBytes ) ;
96+ connection . WriteBuffer . WriteUnmanaged ( "Hello, World!"u8 ) ;
97+ }
98+ }
0 commit comments