Skip to content

Commit 23c3c9a

Browse files
authored
Merge pull request #669 from CypherPotato/main
Fix sisk tests
2 parents 0566d2d + 388c509 commit 23c3c9a

38 files changed

Lines changed: 528 additions & 161 deletions

frameworks/sisk/Program.cs

Lines changed: 95 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,53 @@
1+
using System.Diagnostics;
12
using System.Net.Http.Json;
2-
33
using System.Text.Json;
4-
using sisk;
54
using Npgsql;
5+
using sisk;
66
using Sisk.Cadente.CoreEngine;
77
using Sisk.Core.Http;
8+
using Sisk.Core.Http.FileSystem;
89
using Sisk.Core.Routing;
910

10-
var server = HttpServer.CreateBuilder()
11-
.UseEngine<CadenteHttpServerEngine>()
12-
.UseListeningPort(new ListeningPort(false, "0.0.0.0", 8080))
13-
.UseMinimalConfiguration();
14-
15-
// Pre-load static files with pre-compressed variants
16-
var staticMimeTypes = new Dictionary<string, string>
17-
{
18-
[".css"] = "text/css", [".js"] = "application/javascript", [".html"] = "text/html",
19-
[".woff2"] = "font/woff2", [".svg"] = "image/svg+xml", [".webp"] = "image/webp", [".json"] = "application/json",
20-
};
21-
var staticCache = new Dictionary<string, (byte[] data, byte[]? br, byte[]? gz, string contentType)>();
22-
if (Directory.Exists("/data/static"))
23-
{
24-
foreach (var file in Directory.GetFiles("/data/static"))
25-
{
26-
var name = Path.GetFileName(file);
27-
if (name.EndsWith(".br") || name.EndsWith(".gz")) continue;
28-
var ext = Path.GetExtension(name);
29-
var ct = staticMimeTypes.GetValueOrDefault(ext, "application/octet-stream");
30-
var brPath = file + ".br";
31-
var gzPath = file + ".gz";
32-
staticCache[name] = (
33-
File.ReadAllBytes(file),
34-
File.Exists(brPath) ? File.ReadAllBytes(brPath) : null,
35-
File.Exists(gzPath) ? File.ReadAllBytes(gzPath) : null,
36-
ct
37-
);
38-
}
39-
}
40-
41-
Router router = new Router();
42-
43-
router.MapGet("/static/<filename>", r =>
44-
{
45-
var filename = r.RouteParameters["filename"].ToString();
46-
if (!staticCache.TryGetValue(filename, out var sf))
47-
return new HttpResponse(404);
48-
var ae = r.Headers.AcceptEncoding ?? "";
49-
byte[] body;
50-
string? encoding = null;
51-
if (sf.br != null && ae.Contains("br"))
52-
{
53-
body = sf.br;
54-
encoding = "br";
55-
}
56-
else if (sf.gz != null && ae.Contains("gzip"))
57-
{
58-
body = sf.gz;
59-
encoding = "gzip";
60-
}
61-
else
62-
{
63-
body = sf.data;
64-
}
65-
var resp = new HttpResponse(200);
66-
resp.Content = new ByteArrayContent(body);
67-
resp.Headers.Add("Content-Type", sf.contentType);
68-
if (encoding != null) resp.Headers.Add("Content-Encoding", encoding);
69-
return resp;
70-
});
71-
72-
router.MapGet("/baseline11", r => new HttpResponse(Sum(r)));
73-
router.MapPost("/baseline11", r => new HttpResponse(Sum(r)));
11+
var server = HttpServer.CreateBuilder ()
12+
.UseEngine<CadenteHttpServerEngine> ()
13+
.UseListeningPort ( new ListeningPort ( false, "0.0.0.0", 8080 ) )
14+
.UseMinimalConfiguration ()
15+
.UseConfiguration ( config => {
16+
config.EnableAutomaticResponseCompression = true;
17+
} );
7418

75-
router.MapGet("/baseline2", r => new HttpResponse(Sum(r)));
19+
Router router = new Router ();
7620

77-
router.MapGet("/pipeline", r => new HttpResponse("ok"));
21+
var staticRoute = HttpFileServer.CreateServingRoute ( "/static", new HttpFileServerHandler () {
22+
RootDirectoryPath = "/data/static",
23+
AllowDirectoryListing = false
24+
} );
7825

79-
router.MapPost("/upload", r =>
80-
{
81-
var buffer = new byte[8192];
26+
router.SetRoute ( staticRoute );
8227

83-
var body = r.GetRequestStream();
28+
router.MapGet ( "/baseline11", r => new HttpResponse ( Sum ( r ) ) );
29+
router.MapPost ( "/baseline11", r => new HttpResponse ( Sum ( r ) ) );
8430

85-
var read = 0;
31+
router.MapGet ( "/baseline2", r => new HttpResponse ( Sum ( r ) ) );
8632

87-
long total = 0;
33+
router.MapGet ( "/pipeline", r => new HttpResponse ( "ok" ) );
8834

89-
while ((read = body.Read(buffer, 0, buffer.Length)) > 0)
90-
{
91-
total += read;
92-
}
35+
router.MapPost ( "/upload", r => {
36+
var body = r.GetBodyContents ();
37+
return new HttpResponse ( body.Length.ToString () );
38+
} );
9339

94-
return new HttpResponse(total.ToString());
95-
});
40+
var datasetItems = LoadItems ();
9641

97-
var datasetItems = LoadItems();
98-
99-
router.MapGet("/json/<count>", r =>
100-
{
101-
int count = Math.Clamp(int.Parse(r.RouteParameters["count"].ToString()), 0, datasetItems!.Count);
42+
router.MapGet ( "/json/<count>", r => {
43+
int count = Math.Clamp ( int.Parse ( r.RouteParameters [ "count" ].GetString () ), 0, datasetItems!.Count );
10244
int m = 1;
103-
if (r.Query.TryGetValue("m", out var mStr)) { int.TryParse(mStr, out m); if (m == 0) m = 1; }
104-
var processed = new ProcessedItem[count];
105-
106-
for (int i = 0; i < count; i++)
107-
{
108-
var d = datasetItems[i];
109-
processed[i] = new ProcessedItem
110-
{
45+
if (r.Query.TryGetValue ( "m", out var mStr )) { int.TryParse ( mStr, out m ); if (m == 0) m = 1; }
46+
var processed = new ProcessedItem [ count ];
47+
48+
for (int i = 0; i < count; i++) {
49+
var d = datasetItems [ i ];
50+
processed [ i ] = new ProcessedItem {
11151
Id = d.Id,
11252
Name = d.Name,
11353
Category = d.Category,
@@ -120,99 +60,93 @@
12060
};
12161
}
12262

123-
return new HttpResponse
124-
{
125-
Content = JsonContent.Create(new ListWithCount<ProcessedItem>(processed.ToList()))
63+
return new HttpResponse {
64+
Content = JsonContent.Create ( new ListWithCount<ProcessedItem> ( processed.ToList () ) )
12665
};
127-
});
128-
129-
var pgDataSource = OpenPgPool();
130-
131-
router.MapGet("/async-db", async (HttpRequest request) =>
132-
{
133-
var min = request.Query.TryGetValue("min", out var vmin) ? vmin.GetInteger() : 10;
134-
var max = request.Query.TryGetValue("max", out var vmax) ? vmax.GetInteger() : 50;
135-
var limit = request.Query.TryGetValue("limit", out var vlim) ? Math.Clamp(vlim.GetInteger(), 1, 50) : 50;
136-
137-
await using var cmd = pgDataSource.CreateCommand(
138-
"SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE price BETWEEN $1 AND $2 LIMIT $3");
139-
cmd.Parameters.AddWithValue(min);
140-
cmd.Parameters.AddWithValue(max);
141-
cmd.Parameters.AddWithValue(limit);
142-
await using var reader = await cmd.ExecuteReaderAsync();
143-
144-
var items = new List<object>();
145-
146-
while (await reader.ReadAsync())
147-
{
148-
items.Add(new
149-
{
150-
id = reader.GetInt32(0),
151-
name = reader.GetString(1),
152-
category = reader.GetString(2),
153-
price = reader.GetInt32(3),
154-
quantity = reader.GetInt32(4),
155-
active = reader.GetBoolean(5),
156-
tags = JsonSerializer.Deserialize<List<string>>(reader.GetString(6)),
157-
rating = new { score = reader.GetInt32(7), count = reader.GetInt32(8) },
158-
});
66+
} );
67+
68+
var pgDataSource = OpenPgPool ();
69+
70+
router.MapGet ( "/async-db", async ( HttpRequest request ) => {
71+
var min = request.Query.TryGetValue ( "min", out var vmin ) ? vmin.GetInteger () : 10;
72+
var max = request.Query.TryGetValue ( "max", out var vmax ) ? vmax.GetInteger () : 50;
73+
var limit = request.Query.TryGetValue ( "limit", out var vlim ) ? Math.Clamp ( vlim.GetInteger (), 1, 50 ) : 50;
74+
75+
Debug.Assert ( pgDataSource != null, "PostgreSQL data source is not available. Please set the DATABASE_URL environment variable." );
76+
77+
await using var cmd = pgDataSource.CreateCommand (
78+
"SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE price BETWEEN $1 AND $2 LIMIT $3" );
79+
80+
cmd.Parameters.AddWithValue ( min );
81+
cmd.Parameters.AddWithValue ( max );
82+
cmd.Parameters.AddWithValue ( limit );
83+
await using var reader = await cmd.ExecuteReaderAsync ();
84+
85+
var items = new List<object> ();
86+
87+
while (await reader.ReadAsync ()) {
88+
items.Add ( new {
89+
id = reader.GetInt32 ( 0 ),
90+
name = reader.GetString ( 1 ),
91+
category = reader.GetString ( 2 ),
92+
price = reader.GetInt32 ( 3 ),
93+
quantity = reader.GetInt32 ( 4 ),
94+
active = reader.GetBoolean ( 5 ),
95+
tags = JsonSerializer.Deserialize<List<string>> ( reader.GetString ( 6 ) ),
96+
rating = new { score = reader.GetInt32 ( 7 ), count = reader.GetInt32 ( 8 ) },
97+
} );
15998
}
16099

161-
return new HttpResponse
162-
{
163-
Content = JsonContent.Create(new ListWithCount<object>(items))
100+
return new HttpResponse {
101+
Content = JsonContent.Create ( new ListWithCount<object> ( items ) )
164102
};
165-
});
103+
} );
166104

167-
await server.UseRouter(router).Build().StartAsync();
105+
await server.UseRouter ( router ).Build ().StartAsync ();
168106

169107
return;
170108

171-
static string Sum(HttpRequest request)
172-
{
173-
var a = request.Query["a"].MaybeNullOrEmpty()?.GetInteger() ?? 0;
174-
var b = request.Query["b"].MaybeNullOrEmpty()?.GetInteger() ?? 0;
109+
static string Sum ( HttpRequest request ) {
110+
var a = request.Query [ "a" ].MaybeNullOrEmpty ()?.GetInteger () ?? 0;
111+
var b = request.Query [ "b" ].MaybeNullOrEmpty ()?.GetInteger () ?? 0;
175112

176113
var c = 0;
177114

178-
if (request.Method == HttpMethod.Post)
179-
{
180-
c = int.Parse(request.Body);
115+
if (request.Method == HttpMethod.Post) {
116+
c = int.Parse ( request.Body );
181117
}
182118

183-
return (a + b + c).ToString();
119+
return (a + b + c).ToString ();
184120
}
185121

186-
static List<DatasetItem>? LoadItems()
187-
{
188-
var jsonOptions = new JsonSerializerOptions
189-
{
122+
static List<DatasetItem>? LoadItems () {
123+
var jsonOptions = new JsonSerializerOptions {
190124
PropertyNameCaseInsensitive = true,
191125
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
192126
};
193127

194-
var datasetPath = Environment.GetEnvironmentVariable("DATASET_PATH") ?? "/data/dataset.json";
128+
var datasetPath = Environment.GetEnvironmentVariable ( "DATASET_PATH" ) ?? "/data/dataset.json";
195129

196-
if (File.Exists(datasetPath))
197-
{
198-
return JsonSerializer.Deserialize<List<DatasetItem>>(File.ReadAllText(datasetPath), jsonOptions);
130+
if (File.Exists ( datasetPath )) {
131+
return JsonSerializer.Deserialize<List<DatasetItem>> ( File.ReadAllText ( datasetPath ), jsonOptions );
199132
}
200133

201134
return null;
202135
}
203136

204-
static NpgsqlDataSource? OpenPgPool()
205-
{
206-
var dbUrl = Environment.GetEnvironmentVariable("DATABASE_URL");
207-
if (string.IsNullOrEmpty(dbUrl)) return null;
208-
try
209-
{
210-
var uri = new Uri(dbUrl);
211-
var userInfo = uri.UserInfo.Split(':');
212-
var connStr = $"Host={uri.Host};Port={uri.Port};Username={userInfo[0]};Password={userInfo[1]};Database={uri.AbsolutePath.TrimStart('/')};Maximum Pool Size=256;Minimum Pool Size=64;Multiplexing=true;No Reset On Close=true;Max Auto Prepare=4;Auto Prepare Min Usages=1";
213-
var builder = new NpgsqlDataSourceBuilder(connStr);
214-
return builder.Build();
137+
static NpgsqlDataSource? OpenPgPool () {
138+
var dbUrl = Environment.GetEnvironmentVariable ( "DATABASE_URL" );
139+
if (string.IsNullOrEmpty ( dbUrl ))
140+
return null;
141+
try {
142+
var uri = new Uri ( dbUrl );
143+
var userInfo = uri.UserInfo.Split ( ':' );
144+
var connStr = $"Host={uri.Host};Port={uri.Port};Username={userInfo [ 0 ]};Password={userInfo [ 1 ]};Database={uri.AbsolutePath.TrimStart ( '/' )};Maximum Pool Size=256;Minimum Pool Size=64;Multiplexing=true;No Reset On Close=true;Max Auto Prepare=4;Auto Prepare Min Usages=1";
145+
var builder = new NpgsqlDataSourceBuilder ( connStr );
146+
return builder.Build ();
147+
}
148+
catch {
149+
return null;
215150
}
216-
catch { return null; }
217151
}
218152

frameworks/sisk/sisk.sln

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Microsoft Visual Studio Solution File, Format Version 12.00
2+
# Visual Studio Version 17
3+
VisualStudioVersion = 17.5.2.0
4+
MinimumVisualStudioVersion = 10.0.40219.1
5+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sisk", "sisk.csproj", "{C0CA2CFC-1FB1-7DB1-1D65-1867C8466439}"
6+
EndProject
7+
Global
8+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9+
Debug|Any CPU = Debug|Any CPU
10+
Release|Any CPU = Release|Any CPU
11+
EndGlobalSection
12+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
13+
{C0CA2CFC-1FB1-7DB1-1D65-1867C8466439}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14+
{C0CA2CFC-1FB1-7DB1-1D65-1867C8466439}.Debug|Any CPU.Build.0 = Debug|Any CPU
15+
{C0CA2CFC-1FB1-7DB1-1D65-1867C8466439}.Release|Any CPU.ActiveCfg = Release|Any CPU
16+
{C0CA2CFC-1FB1-7DB1-1D65-1867C8466439}.Release|Any CPU.Build.0 = Release|Any CPU
17+
EndGlobalSection
18+
GlobalSection(SolutionProperties) = preSolution
19+
HideSolutionNode = FALSE
20+
EndGlobalSection
21+
GlobalSection(ExtensibilityGlobals) = postSolution
22+
SolutionGuid = {0131EE85-9736-4BCD-950D-D09A342D540E}
23+
EndGlobalSection
24+
EndGlobal

site/data/api-16-1024.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,32 @@
874874
"tpl_static": 0,
875875
"tpl_async_db": 163326
876876
},
877+
{
878+
"framework": "sisk",
879+
"language": "C#",
880+
"rps": 82086,
881+
"avg_latency": "12.18ms",
882+
"p99_latency": "54.00ms",
883+
"cpu": "1477.1%",
884+
"memory": "240MiB",
885+
"connections": 1024,
886+
"threads": 64,
887+
"duration": "5s",
888+
"pipeline": 1,
889+
"bandwidth": "414.81MB/s",
890+
"input_bw": "4.62MB/s",
891+
"reconnects": 246252,
892+
"status_2xx": 1231297,
893+
"status_3xx": 0,
894+
"status_4xx": 0,
895+
"status_5xx": 0,
896+
"tpl_baseline": 461622,
897+
"tpl_json": 461667,
898+
"tpl_db": 0,
899+
"tpl_upload": 0,
900+
"tpl_static": 0,
901+
"tpl_async_db": 308008
902+
},
877903
{
878904
"framework": "SlimeWeb",
879905
"language": "Python",

site/data/api-4-256.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,32 @@
874874
"tpl_static": 0,
875875
"tpl_async_db": 65218
876876
},
877+
{
878+
"framework": "sisk",
879+
"language": "C#",
880+
"rps": 33914,
881+
"avg_latency": "6.92ms",
882+
"p99_latency": "28.00ms",
883+
"cpu": "333.9%",
884+
"memory": "154MiB",
885+
"connections": 256,
886+
"threads": 64,
887+
"duration": "5s",
888+
"pipeline": 1,
889+
"bandwidth": "171.31MB/s",
890+
"input_bw": "1.91MB/s",
891+
"reconnects": 101709,
892+
"status_2xx": 508720,
893+
"status_3xx": 0,
894+
"status_4xx": 0,
895+
"status_5xx": 0,
896+
"tpl_baseline": 190879,
897+
"tpl_json": 190927,
898+
"tpl_db": 0,
899+
"tpl_upload": 0,
900+
"tpl_static": 0,
901+
"tpl_async_db": 126914
902+
},
877903
{
878904
"framework": "SlimeWeb",
879905
"language": "Python",

0 commit comments

Comments
 (0)