diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 46e7a2410e9..309873abc8c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -155,7 +155,7 @@ jobs: # run-ci.py runs the diffing to see if github actions needs to test this framework. Ideally/eventually, # we'd like to try and do the diffing before github_actions_clean & setup. # This will run the tests exactly as you would in your own vm: - docker network create tfb > /dev/null 2>&1 && docker run --network=tfb -e USER_ID=$(id -u) -e CI=true -v /var/run/docker.sock:/var/run/docker.sock --mount type=bind,source=`pwd`,target=/FrameworkBenchmarks techempower/tfb --mode verify --test-dir $RUN_TESTS --results-environment Github-Actions; + docker network create tfb > /dev/null 2>&1 && docker run --network=tfb -e USER_ID=$(id -u) -e CI=true -v /var/run/docker.sock:/var/run/docker.sock --mount type=bind,source=`pwd`,target=/FrameworkBenchmarks techempower/tfb --mode verify --force-rm --test-dir $RUN_TESTS --results-environment Github-Actions; dependabot: needs: verify runs-on: ubuntu-latest diff --git a/Dockerfile b/Dockerfile index 0e60a78d94c..c02bb66c087 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,10 +4,11 @@ ARG DEBIAN_FRONTEND=noninteractive # WARNING: DON'T PUT A SPACE AFTER ANY BACKSLASH OR APT WILL BREAK # One -q produces output suitable for logging (mostly hides # progress indicators) -RUN apt-get -yqq update && \ - apt-get -yqq install \ +RUN apt-get install \ + --no-install-recommends \ -o Dpkg::Options::="--force-confdef" \ -o Dpkg::Options::="--force-confold" \ + -qqUy \ cloc \ curl \ gcc \ diff --git a/entrypoint.sh b/entrypoint.sh index 71ad543e960..eb22e6e75d7 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -4,4 +4,4 @@ set -eo pipefail -u chown -LR "$USER_ID" /var/run # Drop permissions of user to match those of the host system -gosu "$USER_ID" python3 "${FWROOT}/toolset/run-tests.py" "$@" +exec gosu "$USER_ID" python3 "${FWROOT}/toolset/run-tests.py" "$@" diff --git a/frameworks/C++/ffead-cpp/benchmark_config.json b/frameworks/C++/ffead-cpp/benchmark_config.json index 6ab98997f9d..0a61221fc46 100644 --- a/frameworks/C++/ffead-cpp/benchmark_config.json +++ b/frameworks/C++/ffead-cpp/benchmark_config.json @@ -198,7 +198,7 @@ "display_name": "ffead-cpp [pg-raw-async-prof-pool-m]", "notes": "async memory profiled", "versus": "", - "tags": [] + "tags": ["broken"] }, "postgresql-raw-async-clibpqb-profiled": { "db_url": "/t4/d", @@ -301,7 +301,7 @@ "display_name": "ffead-cpp [pg-raw-async-qw-prof-pool-m]", "notes": "async memory profiled", "versus": "", - "tags": [] + "tags": ["broken"] } }] } diff --git a/frameworks/C/h2o/CMakeLists.txt b/frameworks/C/h2o/CMakeLists.txt index 5126e991a82..d5062f2b26d 100644 --- a/frameworks/C/h2o/CMakeLists.txt +++ b/frameworks/C/h2o/CMakeLists.txt @@ -19,9 +19,8 @@ find_path(PQ_INCLUDE postgresql/libpq-fe.h REQUIRED) find_path(YAJL_INCLUDE yajl/yajl_gen.h REQUIRED) find_program(BPFTOOL_BIN bpftool REQUIRED) find_program(CLANG_BIN clang REQUIRED) -include_directories(src ${CMAKE_BINARY_DIR}/generated-headers ${BPF_INCLUDE} ${H2O_INCLUDE}) -include_directories(${MUSTACHE_C_INCLUDE} ${NUMA_INCLUDE} ${OPENSSL_INCLUDE} ${PQ_INCLUDE}) -include_directories(${YAJL_INCLUDE}) +include_directories(src ${CMAKE_BINARY_DIR} ${BPF_INCLUDE} ${H2O_INCLUDE} ${MUSTACHE_C_INCLUDE}) +include_directories(${NUMA_INCLUDE} ${OPENSSL_INCLUDE} ${PQ_INCLUDE} ${YAJL_INCLUDE}) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) add_compile_definitions(H2O_USE_LIBUV=0) @@ -32,7 +31,7 @@ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_FORTIFY_SOURCE=2") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3") add_custom_command( - OUTPUT ${CMAKE_BINARY_DIR}/generated-headers/socket_load_balancer.h + OUTPUT ${CMAKE_BINARY_DIR}/socket_load_balancer.h COMMAND ${CLANG_BIN} -c -DNDEBUG @@ -47,12 +46,12 @@ add_custom_command( ${WARNING_OPTIONS} ${CMAKE_CURRENT_SOURCE_DIR}/src/bpf/socket_load_balancer.c COMMAND ${BPFTOOL_BIN} gen skeleton ${CMAKE_BINARY_DIR}/socket_load_balancer.o > - ${CMAKE_BINARY_DIR}/generated-headers/socket_load_balancer.h + ${CMAKE_BINARY_DIR}/socket_load_balancer.h DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/bpf/socket_load_balancer.c VERBATIM) add_custom_target( generated_headers - DEPENDS ${CMAKE_BINARY_DIR}/generated-headers/socket_load_balancer.h) + DEPENDS ${CMAKE_BINARY_DIR}/socket_load_balancer.h) file(GLOB_RECURSE HANDLER_SOURCES "src/handlers/*.c") file(GLOB SOURCES "src/*.c") add_executable(${PROJECT_NAME} ${HANDLER_SOURCES} ${SOURCES}) diff --git a/frameworks/C/h2o/h2o.dockerfile b/frameworks/C/h2o/h2o.dockerfile index a86e36a7ebc..d6713a3e688 100644 --- a/frameworks/C/h2o/h2o.dockerfile +++ b/frameworks/C/h2o/h2o.dockerfile @@ -2,7 +2,7 @@ ARG UBUNTU_VERSION=25.10 ARG H2O_APP_PREFIX=/opt/h2o-app -FROM "ubuntu:${UBUNTU_VERSION}" AS compile +FROM "buildpack-deps:${UBUNTU_VERSION}" AS compile RUN echo "[timing] Installing system packages: $(date)" ARG DEBIAN_FRONTEND=noninteractive @@ -24,15 +24,12 @@ RUN apt-get install \ libnuma-dev \ libpq-dev \ libssl-dev \ - libstdc++-15-dev \ libtool \ liburing-dev \ libuv1-dev \ - libwslay-dev \ libyajl-dev \ libz-dev \ make \ - ninja-build \ pkg-config \ ruby \ systemtap-sdt-dev @@ -47,7 +44,6 @@ RUN curl -LSs "https://github.com/h2o/h2o/archive/${H2O_VERSION}.tar.gz" | \ -B build \ -DCMAKE_C_FLAGS="-flto=auto -march=native -mtune=native" \ -DWITH_MRUBY=on \ - -G Ninja \ -S . && \ cmake --build build -j && \ cmake --install build @@ -72,7 +68,6 @@ RUN cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_FLAGS="-march=native -mtune=native" \ -DCMAKE_INSTALL_PREFIX="${H2O_APP_PREFIX}" \ - -G Ninja \ -S .. && \ cmake --build . -j && \ cmake --install . diff --git a/frameworks/C/h2o/src/event_loop.c b/frameworks/C/h2o/src/event_loop.c index 6e95bea496e..df4d37de8de 100644 --- a/frameworks/C/h2o/src/event_loop.c +++ b/frameworks/C/h2o/src/event_loop.c @@ -32,16 +32,13 @@ #include #include #include -#include #include #include "error.h" #include "event_loop.h" #include "global_data.h" #include "thread.h" -#include "utility.h" -#define CONN_NUM_SAMPLE_PERIOD 2500 #define DEFAULT_TCP_FASTOPEN_QUEUE_LEN 4096 static void accept_connection(h2o_socket_t *listener, const char *err); @@ -80,7 +77,6 @@ static void accept_connection(h2o_socket_t *listener, const char *err) if (!sock) break; - ctx->event_loop.accepted_conn_num++; ctx->event_loop.conn_num++; sock->on_close.cb = on_close_connection; sock->on_close.data = &ctx->event_loop.conn_num; @@ -299,36 +295,11 @@ static void start_accept_polling(bool is_main_thread, void event_loop(struct thread_context_t *ctx) { - uint64_t last_sample = 0; - while (!ctx->shutdown || ctx->event_loop.conn_num) { h2o_evloop_run(ctx->event_loop.h2o_ctx.loop, INT32_MAX); process_messages(&ctx->global_thread_data->h2o_receiver, &ctx->event_loop.local_messages); - - const uint64_t now = h2o_now(ctx->event_loop.h2o_ctx.loop); - - if (now - last_sample > CONN_NUM_SAMPLE_PERIOD || last_sample > now) { - const size_t i = ctx->event_loop.conn_num_sample_idx; - - ctx->event_loop.conn_num_sample[i] = ctx->event_loop.conn_num; - ctx->event_loop.conn_num_sample_idx = - (i + 1) % ARRAY_SIZE(ctx->event_loop.conn_num_sample); - last_sample = now; - } } - - flockfile(stdout); - printf("Thread %ld statistics:\nAccepted connections: %zu\nConnection number samples: %zu", - syscall(SYS_gettid), - ctx->event_loop.accepted_conn_num, - *ctx->event_loop.conn_num_sample); - - for (size_t i = 1; i < ARRAY_SIZE(ctx->event_loop.conn_num_sample); i++) - printf(",%zu", ctx->event_loop.conn_num_sample[i]); - - putc_unlocked('\n', stdout); - funlockfile(stdout); } void free_event_loop(event_loop_t *event_loop, h2o_multithread_receiver_t *h2o_receiver) diff --git a/frameworks/C/h2o/src/event_loop.h b/frameworks/C/h2o/src/event_loop.h index 41a1f3b920f..cff091154c7 100644 --- a/frameworks/C/h2o/src/event_loop.h +++ b/frameworks/C/h2o/src/event_loop.h @@ -27,8 +27,6 @@ #include "global_data.h" -#define CONN_NUM_SAMPLES 512 - typedef enum { SHUTDOWN, TASK @@ -43,9 +41,6 @@ typedef struct { h2o_accept_ctx_t h2o_accept_ctx; h2o_context_t h2o_ctx; h2o_linklist_t local_messages; - size_t accepted_conn_num; - size_t conn_num_sample[CONN_NUM_SAMPLES]; - size_t conn_num_sample_idx; } event_loop_t; typedef struct { diff --git a/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/AkazawaYun.Benchmark.Platform.csproj b/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/AkazawaYun.Benchmark.Platform.csproj index 64baee178a5..b2312be1bbb 100644 --- a/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/AkazawaYun.Benchmark.Platform.csproj +++ b/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/AkazawaYun.Benchmark.Platform.csproj @@ -15,7 +15,7 @@ - + diff --git a/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/MyBenchmarkReceptor.cs b/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/MyBenchmarkReceptor.cs index e6ed8e9c5b7..ca9bb7c1362 100644 --- a/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/MyBenchmarkReceptor.cs +++ b/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/MyBenchmarkReceptor.cs @@ -1,12 +1,10 @@ using AkazawaYun.PRO7; -using System.Text; namespace AkazawaYun.Benchmark.Platform; -class MyBenchmarkReceptor : akzWebReceptorBenchmark +class MyBenchmarkReceptor : akaWebReceptorBenchmark { readonly JsonModel JsonModel; - readonly ReadOnlyMemory JsonContentLength; public MyBenchmarkReceptor() @@ -15,8 +13,6 @@ public MyBenchmarkReceptor() { message = "Hello, World!" }; - akzJson.Text2Json(JsonModel, out ReadOnlyMemory json); - JsonContentLength = Encoding.UTF8.GetBytes($"{json.Length}\r\n\r\n"); } @@ -26,9 +22,8 @@ public override ValueTask SendPlaintext(IHttpContext http) } public override async ValueTask SendJson(IHttpContext http) { - await http.Slient.Send(DataJson_OnlyHeaderExceptContentLength); - await http.Slient.Send(JsonContentLength); - akzJson.Text2Json(JsonModel, out ReadOnlyMemory json); + await http.Slient.Send(DataJson_OnlyHeader); + akaJson.Text2Json(JsonModel, out ReadOnlyMemory json); await http.Slient.Send(json); } public override ValueTask SendDb(IHttpContext http) diff --git a/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/Program.cs b/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/Program.cs index 44dd91c0a3a..9be953769c4 100644 --- a/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/Program.cs +++ b/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.Platform/Program.cs @@ -4,34 +4,17 @@ namespace AkazawaYun.Benchmark.Platform; class Program { - static readonly akzWebBuilder builder; - const int port = 8080; + static readonly akaWebBuilder builder; static Program() { - akzLog.War("AkazawaYun.PRO 压力测试特供版 ver2025.11.3, 只支持 /plaintext 和 /json"); - akzJson.Config(null, AotJsonContext.Default); - builder = akzWebBuilder.Shared.SetPort(port).SetDev(true) - .Add(() => null) - .Add(() => new MyBenchmarkReceptor()) - .Add(() => new(port) - { - LogLevel = 0 - }).Build(); + akaLog.War("AkazawaYun.PRO 平台压力测试特供版 ver2025.11.3, 只支持 /plaintext 和 /json"); + akaJson.Config(AotJsonContext.Default); + builder = akaWebBuilder.Shared.Build(new MyBenchmarkReceptor()); } static async Task Main() { await builder.Launch(); - - akzLog.Inf("[API SELF-TEST]"); - string url = $"http://localhost:{port}/plaintext"; - akzLog.Inf(" REQ URL :" + url); - string res = await akzHttpClient.Shared.Get(url).FetchString(); - akzLog.Inf(" RES LEN :" + res.Length); - akzLog.Inf(" RES BODY:" + res); - akzLog.Inf("[OK, I WORK FINE]"); - - akzLog.Default = akzLog.Output.NoneButWar; await Task.Delay(-1); } } diff --git a/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.WebApi/AkazawaYun.Benchmark.WebApi.csproj b/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.WebApi/AkazawaYun.Benchmark.WebApi.csproj index 469e112ef00..452b23e493c 100644 --- a/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.WebApi/AkazawaYun.Benchmark.WebApi.csproj +++ b/frameworks/CSharp/akazawayun.pro/src/AkazawaYun.Benchmark.WebApi/AkazawaYun.Benchmark.WebApi.csproj @@ -15,7 +15,7 @@ - + diff --git a/frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile b/frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile index ad6c396e22b..9f3e85a6439 100644 --- a/frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile +++ b/frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build RUN apt-get update RUN apt-get -yqq install clang zlib1g-dev RUN apt-get update @@ -8,7 +8,7 @@ COPY src . RUN dotnet publish -c Release -o out /p:Database=mysql # Construct the actual image that will run -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0.1 AS runtime RUN apt-get update # The following installs standard versions unixodbc and pgsqlodbc @@ -51,6 +51,8 @@ RUN cp /usr/lib/x86_64-linux-gnu/libodbc* /app #TODOLOCAL #RUN cp /usr/lib/aarch64-linux-gnu/libodbc* /app +#TEST: ./tfb --test appmpower-odbc-my --type db + EXPOSE 8080 ENTRYPOINT ["./appMpower"] \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile b/frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile index 1cf7855dd7f..56dfaba77bb 100644 --- a/frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile +++ b/frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build RUN apt-get update RUN apt-get -yqq install clang zlib1g-dev @@ -7,7 +7,7 @@ COPY src . RUN dotnet publish -c Release -o out /p:Database=postgresql # Construct the actual image that will run -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0.1 AS runtime RUN apt-get update RUN apt-get install -y unixodbc-dev unixodbc odbc-postgresql @@ -32,6 +32,8 @@ RUN cp /usr/lib/x86_64-linux-gnu/libodbc* /app #TODOLOCAL #RUN cp /usr/lib/aarch64-linux-gnu/libodbc* /app +#TEST: ./tfb --test appmpower-odbc-pg --type db + EXPOSE 8080 ENTRYPOINT ["./appMpower"] \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/appmpower.dockerfile b/frameworks/CSharp/appmpower/appmpower.dockerfile index 6621b6b6deb..abdc5cfcb7c 100644 --- a/frameworks/CSharp/appmpower/appmpower.dockerfile +++ b/frameworks/CSharp/appmpower/appmpower.dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build RUN apt-get update RUN apt-get -yqq install clang zlib1g-dev @@ -8,7 +8,7 @@ COPY src . RUN dotnet publish -c Release -o out # Construct the actual image that will run -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0.1 AS runtime # Full PGO ENV DOTNET_TieredPGO 1 ENV DOTNET_TC_QuickJitForLoops 1 @@ -18,6 +18,8 @@ ENV ASPNETCORE_URLS http://+:8080 WORKDIR /app COPY --from=build /app/out ./ +#TEST: ./tfb --test appmpower --type json + EXPOSE 8080 ENTRYPOINT ["./appMpower"] \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs index 6c20aded37a..bdeb98565a5 100644 --- a/frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs @@ -1,9 +1,9 @@ using System.Runtime.InteropServices; -using System.Text; -using System.Text.Json; -using appMpower.Orm.Data; -using appMpower.Orm.Objects; -using appMpower.Orm.Serializers; +using System.Text; +using System.Text.Json; +using appMpower.Orm.Data; +using appMpower.Orm.Objects; +using appMpower.Orm.Serializers; namespace appMpower.Orm; @@ -11,7 +11,7 @@ public static class NativeMethods { private static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions { - Indented = false, + Indented = false, SkipValidation = true }; @@ -24,17 +24,17 @@ public static class NativeMethods [UnmanagedCallersOnly(EntryPoint = "Dbms")] public static void Dbms(int dbms) { - Constants.Dbms = (Dbms)dbms; + Constants.Dbms = (Dbms)dbms; DbProviderFactory.SetConnectionString(); } [UnmanagedCallersOnly(EntryPoint = "DbProvider")] public static void DbProvider(int dbProvider) { - Constants.DbProvider = (DbProvider)dbProvider; + Constants.DbProvider = (DbProvider)dbProvider; DbProviderFactory.SetConnectionString(); } - + [UnmanagedCallersOnly(EntryPoint = "FreeHandlePointer")] public static void FreeHandlePointer(IntPtr handlePointer) { @@ -48,25 +48,22 @@ public static unsafe IntPtr Db(int* length, IntPtr* handlePointer) var world = RawDb.LoadSingleQueryRow().GetAwaiter().GetResult(); var memoryStream = new MemoryStream(); - using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions); + using (var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions)) + { + _worldSerializer.Serialize(utf8JsonWriter, world); + } - _worldSerializer.Serialize(utf8JsonWriter, world); + // Flush everything to the MemoryStream + memoryStream.Flush(); + byte[] buffer = memoryStream.GetBuffer(); + int len = (int)memoryStream.Position; // or (int)memoryStream.Length; - *length = (int)utf8JsonWriter.BytesCommitted; - byte[] byteArray = memoryStream.ToArray(); + *length = len; - GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned); - // return the managed and byteArrayPointer pointer - IntPtr byteArrayPointer = handle.AddrOfPinnedObject(); + GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); *handlePointer = GCHandle.ToIntPtr(handle); - return byteArrayPointer; - /* - fixed(byte* b = memoryStream.ToArray()) - { - return b; - } - */ + return handle.AddrOfPinnedObject(); } /* @@ -90,7 +87,7 @@ public static unsafe IntPtr Fortunes(int* length, IntPtr* handlePointer) [UnmanagedCallersOnly(EntryPoint = "Fortunes")] public static unsafe IntPtr Fortunes(int* length, IntPtr* handlePointer) { - List fortunes = RawDb.LoadFortunesRows().GetAwaiter().GetResult(); + List fortunes = RawDb.LoadFortunesRows().GetAwaiter().GetResult(); int totalSize = 0; @@ -122,7 +119,7 @@ public static unsafe IntPtr Fortunes(int* length, IntPtr* handlePointer) } byte[] byteArray = buffer.ToArray(); - *length = byteArray.Length; + *length = byteArray.Length; /* var memoryStream = new MemoryStream(); @@ -151,7 +148,7 @@ public static unsafe IntPtr Query(int queries, int* length, IntPtr* handlePointe _worldsSerializer.Serialize(utf8JsonWriter, worlds); - *length = (int)utf8JsonWriter.BytesCommitted; + *length = (int)utf8JsonWriter.BytesCommitted; byte[] byteArray = memoryStream.ToArray(); GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned); @@ -171,7 +168,7 @@ public static unsafe IntPtr Updates(int count, int* length, IntPtr* handlePointe _worldsSerializer.Serialize(utf8JsonWriter, worlds); - *length = (int)utf8JsonWriter.BytesCommitted; + *length = (int)utf8JsonWriter.BytesCommitted; byte[] byteArray = memoryStream.ToArray(); GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned); @@ -191,7 +188,7 @@ public static unsafe IntPtr DbById(int id, int* length, IntPtr* handlePointer) _worldSerializer.Serialize(utf8JsonWriter, world); - *length = (int)utf8JsonWriter.BytesCommitted; + *length = (int)utf8JsonWriter.BytesCommitted; byte[] byteArray = memoryStream.ToArray(); GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned); diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/appMpower.Orm.csproj b/frameworks/CSharp/appmpower/src/appMpower.Orm/appMpower.Orm.csproj index 23a9b6c47cb..19ac29572de 100644 --- a/frameworks/CSharp/appmpower/src/appMpower.Orm/appMpower.Orm.csproj +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/appMpower.Orm.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable true @@ -41,7 +41,7 @@ - + diff --git a/frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj b/frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj index 5db0aac55f8..dbb2d8436c4 100644 --- a/frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj +++ b/frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 Exe true @@ -11,13 +11,12 @@ - - diff --git a/frameworks/CSharp/aspnetcore-mono/benchmark_config.json b/frameworks/CSharp/aspnetcore-mono/benchmark_config.json index e52c7d74b55..74fd85c0b83 100644 --- a/frameworks/CSharp/aspnetcore-mono/benchmark_config.json +++ b/frameworks/CSharp/aspnetcore-mono/benchmark_config.json @@ -40,6 +40,7 @@ "database_os": "Linux", "display_name": "ASP.NET Core [Platform, Mono, Pg]", "notes": "", + "tags": ["broken"], "versus": "aspcore-ado-pg" }, "mw": { @@ -123,4 +124,4 @@ "versus": "aspcore-mono-pg" } }] -} \ No newline at end of file +} diff --git a/frameworks/CSharp/aspnetcore/appsettings.postgresql.json b/frameworks/CSharp/aspnetcore/appsettings.postgresql.json index 423af4d19b0..897abdcd96f 100644 --- a/frameworks/CSharp/aspnetcore/appsettings.postgresql.json +++ b/frameworks/CSharp/aspnetcore/appsettings.postgresql.json @@ -1,4 +1,4 @@ { - "ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=512;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4", + "ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=18;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000;", "Database": "postgresql" } diff --git a/frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile b/frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile index a7396e3b919..3859225dd2a 100644 --- a/frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile +++ b/frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile @@ -1,11 +1,11 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build RUN apt-get update RUN apt-get -yqq install clang zlib1g-dev WORKDIR /app COPY src/Platform . RUN dotnet publish -c Release -o out /p:DatabaseProvider=Npgsql /p:PublishAot=true /p:OptimizationPreference=Speed /p:GarbageCollectionAdaptationMode=0 -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime ENV URLS=http://+:8080 WORKDIR /app diff --git a/frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile b/frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile index 24893c9717a..96bfb5e1ab4 100644 --- a/frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile +++ b/frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/Minimal . RUN dotnet publish -c Release -o out -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime ENV URLS http://+:8080 ENV DOTNET_GCDynamicAdaptationMode=0 ENV DOTNET_ReadyToRun=0 diff --git a/frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile b/frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile index 6922a53bf2a..4382f7b4b3b 100644 --- a/frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile +++ b/frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/Mvc . RUN dotnet publish -c Release -o out -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime ENV URLS http://+:8080 ENV DOTNET_GCDynamicAdaptationMode=0 ENV DOTNET_ReadyToRun=0 diff --git a/frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile b/frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile index ecc0a8331c3..19ff86e3dc9 100644 --- a/frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile +++ b/frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/Platform . RUN dotnet publish -c Release -o out /p:DatabaseProvider=MySqlConnector -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime ENV URLS http://+:8080 ENV DOTNET_GCDynamicAdaptationMode=0 ENV DOTNET_ReadyToRun=0 diff --git a/frameworks/CSharp/aspnetcore/aspnetcore.dockerfile b/frameworks/CSharp/aspnetcore/aspnetcore.dockerfile index 64510ffe786..4aa5b466752 100644 --- a/frameworks/CSharp/aspnetcore/aspnetcore.dockerfile +++ b/frameworks/CSharp/aspnetcore/aspnetcore.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/Platform . RUN dotnet publish -c Release -o out /p:DatabaseProvider=Npgsql -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime ENV URLS=http://+:8080 ENV DOTNET_GCDynamicAdaptationMode=0 ENV DOTNET_ReadyToRun=0 diff --git a/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs b/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs index ce23c943abe..09ea9e26ce6 100644 --- a/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs +++ b/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs @@ -63,6 +63,9 @@ public async Task LoadMultipleUpdatesRows(string? parameter) var parameters = new Dictionary(); + var ids = new int[count]; + var numbers = new int[count]; + await using var db = _dbProviderFactory.CreateConnection(); db!.ConnectionString = _connectionString; @@ -72,18 +75,33 @@ public async Task LoadMultipleUpdatesRows(string? parameter) for (var i = 0; i < count; i++) { results[i] = await ReadSingleRow(db); + ids[i] = results[i].Id; } + Array.Sort(ids); + + // Ensure unique ids by incrementing duplicates + for (var i = 1; i < count; i++) + if (ids[i] == ids[i - 1]) + ids[i] = (ids[i] % 10000) + 1; for (var i = 0; i < count; i++) { var randomNumber = Random.Shared.Next(1, 10001); - parameters[$"@Rn_{i}"] = randomNumber; - parameters[$"@Id_{i}"] = results[i].Id; + if (results[i].RandomNumber == randomNumber) + { + randomNumber = (randomNumber % 10000) + 1; + } results[i].RandomNumber = randomNumber; + numbers[i] = randomNumber; } - await db.ExecuteAsync(BatchUpdateString.Query(count), parameters); + var update = "UPDATE world w SET randomnumber = u.new_val FROM (SELECT unnest(@ids) as id, unnest(@newValues) as new_val) u WHERE w.id = u.id"; + + parameters["ids"] = ids; + parameters["newValues"] = numbers; + + await db.ExecuteAsync(update, parameters); return results; } diff --git a/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj b/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj index 12f3446d8b7..256a58e1de0 100644 --- a/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj +++ b/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable latest @@ -9,9 +9,9 @@ - - - + + + diff --git a/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj b/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj index 68c70002683..4cdddc7c2d6 100644 --- a/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj +++ b/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable latest @@ -9,8 +9,8 @@ - - + + diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Data/Random.cs b/frameworks/CSharp/aspnetcore/src/Platform/Data/Random.cs deleted file mode 100644 index a989eb9de2a..00000000000 --- a/frameworks/CSharp/aspnetcore/src/Platform/Data/Random.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Runtime.CompilerServices; -using System.Threading; - -namespace PlatformBenchmarks; - -public sealed class ConcurrentRandom -{ - private static int nextSeed = 0; - - // Random isn't thread safe - [ThreadStatic] - private static Random _random; - - private static Random Random => _random ?? CreateRandom(); - - [MethodImpl(MethodImplOptions.NoInlining)] - private static Random CreateRandom() - { - _random = new Random(Interlocked.Increment(ref nextSeed)); - return _random; - } - - public int Next(int minValue, int maxValue) - { - return Random.Next(minValue, maxValue); - } -} diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbMySqlConnector.cs b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbMySqlConnector.cs index 340fa1236b2..5c7779b70f0 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbMySqlConnector.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbMySqlConnector.cs @@ -17,16 +17,14 @@ namespace PlatformBenchmarks; // If you are changing RawDbMySqlConnector.cs, also consider changing RawDbNpgsql.cs. public sealed class RawDb { - private readonly ConcurrentRandom _random; private readonly string _connectionString; private readonly MemoryCache _cache = new(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(60) }); private readonly MySqlDataSource _dataSource; - public RawDb(ConcurrentRandom random, AppSettings appSettings) + public RawDb(AppSettings appSettings) { - _random = random; _connectionString = appSettings.ConnectionString; _dataSource = new MySqlDataSource(appSettings.ConnectionString); } @@ -46,10 +44,10 @@ public Task LoadCachedQueries(int count) var result = new CachedWorld[count]; var cacheKeys = _cacheKeys; var cache = _cache; - var random = _random; + for (var i = 0; i < result.Length; i++) { - var id = random.Next(1, 10001); + var id = Random.Shared.Next(1, 10001); var key = cacheKeys[id]; if (cache.TryGetValue(key, out var cached)) { @@ -80,7 +78,7 @@ static async Task LoadUncachedQueries(int id, int i, int count, R { result[i] = await rawdb._cache.GetOrCreateAsync(key, create); - id = rawdb._random.Next(1, 10001); + id = Random.Shared.Next(1, 10001); idParameter.Value = id; key = cacheKeys[id]; } @@ -117,24 +115,18 @@ public async Task LoadMultipleQueriesRows(int count) using var connection = await _dataSource.OpenConnectionAsync(); - using var batch = new MySqlBatch(connection); - - for (var i = 0; i < count; i++) + // It is not acceptable to execute multiple SELECTs within a single complex query. + // It is not acceptable to retrieve all required rows using a SELECT ... WHERE id IN (...) clause. + // Pipelining of network traffic between the application and database is permitted. + + var (queryCmd, queryParameter) = await CreateReadCommandAsync(connection); + using (queryCmd) { - batch.BatchCommands.Add(new MySqlBatchCommand() + for (var i = 0; i < results.Length; i++) { - CommandText = "SELECT id, randomnumber FROM world WHERE id = @id", - Parameters = { new MySqlParameter("@id", _random.Next(1, 10001)) } - }); - } - - using var reader = await batch.ExecuteReaderAsync(); - - for (var i = 0; i < count; i++) - { - await reader.ReadAsync(); - results[i] = new World { Id = reader.GetInt32(0), RandomNumber = reader.GetInt32(1) }; - await reader.NextResultAsync(); + queryParameter.Value = Random.Shared.Next(1, 10001); + results[i] = await ReadSingleRow(queryCmd); + } } return results; @@ -144,23 +136,34 @@ public async Task LoadMultipleUpdatesRows(int count) { var results = new World[count]; + var ids = new int[count]; + for (var i = 0; i < count; i++) + { + ids[i] = Random.Shared.Next(1, 10001); + } + Array.Sort(ids); + using var connection = await _dataSource.OpenConnectionAsync(); + // Each row must be selected randomly using one query in the same fashion as the single database query test + // Use of IN clauses or similar means to consolidate multiple queries into one operation is not permitted. + // Similarly, use of a batch or multiple SELECTs within a single statement are not permitted var (queryCmd, queryParameter) = await CreateReadCommandAsync(connection); using (queryCmd) { for (var i = 0; i < results.Length; i++) { + queryParameter.Value = ids[i]; results[i] = await ReadSingleRow(queryCmd); - queryParameter.Value = _random.Next(1, 10001); } } + // MySql doesn't have the unnest function like PostgreSQL, so we have to do a batch update instead using (var updateCmd = new MySqlCommand(BatchUpdateString.Query(count), connection)) { for (var i = 0; i < results.Length; i++) { - var randomNumber = _random.Next(1, 10001); + var randomNumber = Random.Shared.Next(1, 10001); updateCmd.Parameters.AddWithValue($"@Id_{i}", results[i].Id); updateCmd.Parameters.AddWithValue($"@Random_{i}", randomNumber); @@ -204,7 +207,7 @@ public async Task> LoadFortunesRows() private async Task<(MySqlCommand readCmd, MySqlParameter idParameter)> CreateReadCommandAsync(MySqlConnection connection) { var cmd = new MySqlCommand("SELECT id, randomnumber FROM world WHERE id = @Id", connection); - var parameter = new MySqlParameter("@Id", _random.Next(1, 10001)); + var parameter = new MySqlParameter("@Id", Random.Shared.Next(1, 10001)); cmd.Parameters.Add(parameter); diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs index 60aeb9bd9a2..e8e05ab34e9 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs @@ -10,21 +10,20 @@ using System.Threading.Tasks; using Microsoft.Extensions.Caching.Memory; using Npgsql; +using NpgsqlTypes; namespace PlatformBenchmarks; public sealed class RawDb { - private readonly ConcurrentRandom _random; private readonly MemoryCache _cache = new(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(60) }); private readonly NpgsqlDataSource _dataSource; - public RawDb(ConcurrentRandom random, AppSettings appSettings) + public RawDb(AppSettings appSettings) { - _random = random; - _dataSource = NpgsqlDataSource.Create(appSettings.ConnectionString); + _dataSource = new NpgsqlSlimDataSourceBuilder(appSettings.ConnectionString).EnableArrays().Build(); } public async Task LoadSingleQueryRow() @@ -42,10 +41,10 @@ public Task LoadCachedQueries(int count) var result = new CachedWorld[count]; var cacheKeys = _cacheKeys; var cache = _cache; - var random = _random; + for (var i = 0; i < result.Length; i++) { - var id = random.Next(1, 10001); + var id = Random.Shared.Next(1, 10001); var key = cacheKeys[id]; if (cache.TryGetValue(key, out var cached)) { @@ -76,7 +75,7 @@ static async Task LoadUncachedQueries(int id, int i, int count, R { result[i] = await rawdb._cache.GetOrCreateAsync(key, create); - id = rawdb._random.Next(1, 10001); + id = Random.Shared.Next(1, 10001); idParameter.TypedValue = id; key = cacheKeys[id]; } @@ -109,30 +108,18 @@ public async Task LoadMultipleQueriesRows(int count) using var connection = await _dataSource.OpenConnectionAsync(); - using var batch = new NpgsqlBatch(connection) - { - // Inserts a PG Sync message between each statement in the batch, required for compliance with - // TechEmpower general test requirement 7 - // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview - EnableErrorBarriers = true - }; - - for (var i = 0; i < count; i++) + // It is not acceptable to execute multiple SELECTs within a single complex query. + // It is not acceptable to retrieve all required rows using a SELECT ... WHERE id IN (...) clause. + // Pipelining of network traffic between the application and database is permitted. + + var (queryCmd, queryParameter) = CreateReadCommand(connection); + using (queryCmd) { - batch.BatchCommands.Add(new() + for (var i = 0; i < results.Length; i++) { - CommandText = "SELECT id, randomnumber FROM world WHERE id = $1", - Parameters = { new NpgsqlParameter { TypedValue = _random.Next(1, 10001) } } - }); - } - - using var reader = await batch.ExecuteReaderAsync(); - - for (var i = 0; i < count; i++) - { - await reader.ReadAsync(); - results[i] = new World { Id = reader.GetInt32(0), RandomNumber = reader.GetInt32(1) }; - await reader.NextResultAsync(); + queryParameter.TypedValue = Random.Shared.Next(1, 10001); + results[i] = await ReadSingleRow(queryCmd); + } } return results; @@ -142,34 +129,55 @@ public async Task LoadMultipleUpdatesRows(int count) { var results = new World[count]; - using var connection = CreateConnection(); - await connection.OpenAsync(); + var ids = new int[count]; + var numbers = new int[count]; + + for (var i = 0; i < count; i++) + { + ids[i] = Random.Shared.Next(1, 10001); + } + Array.Sort(ids); + + // Ensure unique ids by incrementing duplicates + for (var i = 1; i < count; i++) + if (ids[i] == ids[i - 1]) + ids[i] = (ids[i] % 10000) + 1; + + using var connection = await _dataSource.OpenConnectionAsync(); + // Each row must be selected randomly using one query in the same fashion as the single database query test + // Use of IN clauses or similar means to consolidate multiple queries into one operation is not permitted. + // Similarly, use of a batch or multiple SELECTs within a single statement are not permitted var (queryCmd, queryParameter) = CreateReadCommand(connection); using (queryCmd) { for (var i = 0; i < results.Length; i++) { + queryParameter.TypedValue = ids[i]; results[i] = await ReadSingleRow(queryCmd); - queryParameter.TypedValue = _random.Next(1, 10001); } } - using (var updateCmd = new NpgsqlCommand(BatchUpdateString.Query(count), connection)) + for (var i = 0; i < count; i++) { - for (var i = 0; i < results.Length; i++) + var randomNumber = Random.Shared.Next(1, 10001); + if (results[i].RandomNumber == randomNumber) { - var randomNumber = _random.Next(1, 10001); - - updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = results[i].Id }); - updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = randomNumber }); - - results[i].RandomNumber = randomNumber; + randomNumber = (randomNumber % 10000) + 1; } - await updateCmd.ExecuteNonQueryAsync(); + results[i].RandomNumber = randomNumber; + numbers[i] = randomNumber; } + var update = "UPDATE world w SET randomnumber = u.new_val FROM (SELECT unnest($1) as id, unnest($2) as new_val) u WHERE w.id = u.id"; + + using var updateCmd = new NpgsqlCommand(update, connection); + updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = ids, NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Integer }); + updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = numbers, NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Integer }); + + await updateCmd.ExecuteNonQueryAsync(); + return results; } @@ -203,7 +211,7 @@ public async Task> LoadFortunesRows() private (NpgsqlCommand readCmd, NpgsqlParameter idParameter) CreateReadCommand(NpgsqlConnection connection) { var cmd = new NpgsqlCommand("SELECT id, randomnumber FROM world WHERE id = $1", connection); - var parameter = new NpgsqlParameter { TypedValue = _random.Next(1, 10001) }; + var parameter = new NpgsqlParameter { TypedValue = Random.Shared.Next(1, 10001) }; cmd.Parameters.Add(parameter); diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj index 7db51dc3ec7..46911b46548 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj +++ b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 true true preview @@ -18,10 +18,10 @@ - - - - + + + + diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Program.cs b/frameworks/CSharp/aspnetcore/src/Platform/Program.cs index 28fc5d757dd..7877351f2da 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Program.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/Program.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; namespace PlatformBenchmarks; @@ -42,7 +43,7 @@ public static async Task Main(string[] args) await host.RunAsync(); } - public static IWebHost BuildWebHost(string[] args) + public static IHost BuildWebHost(string[] args) { Console.WriteLine($"BuildWebHost()"); Console.WriteLine($"Args: {string.Join(' ', args)}"); @@ -59,30 +60,34 @@ public static IWebHost BuildWebHost(string[] args) var appSettings = config.Get(); Console.WriteLine($"ConnectionString: {appSettings.ConnectionString}"); - BenchmarkApplication.RawDb = new RawDb(new ConcurrentRandom(), appSettings); + BenchmarkApplication.RawDb = new RawDb(appSettings); - var hostBuilder = new WebHostBuilder() - .UseBenchmarksConfiguration(config) - .UseKestrel((context, options) => + var hostBuilder = Host.CreateDefaultBuilder(args) + .ConfigureWebHost(webHostBuilder => { - var endPoint = context.Configuration.CreateIPEndPoint(); - - options.Listen(endPoint, builder => + webHostBuilder + .UseBenchmarksConfiguration(config) + .UseKestrel((context, options) => + { + var endPoint = context.Configuration.CreateIPEndPoint(); + + options.Listen(endPoint, builder => + { + builder.UseHttpApplication(); + }); + }) + .UseStartup(); + + webHostBuilder.UseSockets(options => { - builder.UseHttpApplication(); - }); - }) - .UseStartup(); - - hostBuilder.UseSockets(options => - { - options.WaitForDataBeforeAllocatingBuffer = false; + options.WaitForDataBeforeAllocatingBuffer = false; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - options.UnsafePreferInlineScheduling = true; - } - }); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + options.UnsafePreferInlineScheduling = true; + } + }); + }); var host = hostBuilder.Build(); diff --git a/frameworks/CSharp/embedio/Benchmarks/Benchmarks.csproj b/frameworks/CSharp/embedio/Benchmarks/Benchmarks.csproj index 19e73c8b7c4..0015577d97e 100644 --- a/frameworks/CSharp/embedio/Benchmarks/Benchmarks.csproj +++ b/frameworks/CSharp/embedio/Benchmarks/Benchmarks.csproj @@ -1,23 +1,23 @@  - + - - net5.0 - 9.0 - + + net9.0 + 13.0 + EmbedIO Benchmarks Test suite to be executed with TechEmpower FrameworkBenchmarks. - - Benchmarks.Program + + Benchmarks.Program Exe - + true false - + - + - + - - \ No newline at end of file + + diff --git a/frameworks/CSharp/embedio/Benchmarks/Program.cs b/frameworks/CSharp/embedio/Benchmarks/Program.cs index db1f8734c3e..f554daee530 100644 --- a/frameworks/CSharp/embedio/Benchmarks/Program.cs +++ b/frameworks/CSharp/embedio/Benchmarks/Program.cs @@ -1,10 +1,12 @@ -using EmbedIO; -using Swan.Logging; -using System; +using System; using System.Text; using System.Threading; using System.Threading.Tasks; +using EmbedIO; + +using Swan.Logging; + namespace Benchmarks { @@ -21,7 +23,7 @@ public class JsonResult public static class Program { - private static readonly ManualResetEvent _WaitEvent = new ManualResetEvent(false); + private static readonly ManualResetEvent WaitEvent = new(false); public static async Task Main(string[] args) { @@ -60,12 +62,12 @@ public static async Task Main(string[] args) { AppDomain.CurrentDomain.ProcessExit += (_, __) => { - _WaitEvent.Set(); + WaitEvent.Set(); }; await server.RunAsync(); - _WaitEvent.WaitOne(); + WaitEvent.WaitOne(); return 0; } diff --git a/frameworks/CSharp/embedio/README.md b/frameworks/CSharp/embedio/README.md index f04d7d2ecd9..afa7412870f 100644 --- a/frameworks/CSharp/embedio/README.md +++ b/frameworks/CSharp/embedio/README.md @@ -6,17 +6,17 @@ See the [project website](https://github.com/unosquare/embedio) for more informa **Language** -* C# 9.0 +* C# 13.0 **Platforms** -* .NET 5 +* .NET 9 **Web Servers** * [EmbedIO](https://github.com/unosquare/embedio) -## Paths & Source for Tests +## Paths \& Source for Tests * [Plaintext](Benchmarks/Program.cs): "/plaintext" * [JSON](Benchmarks/Program.cs): "/json" diff --git a/frameworks/CSharp/embedio/embedio.dockerfile b/frameworks/CSharp/embedio/embedio.dockerfile index 675c16d8841..35e05ff1fc4 100644 --- a/frameworks/CSharp/embedio/embedio.dockerfile +++ b/frameworks/CSharp/embedio/embedio.dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build WORKDIR /source # copy csproj and restore as distinct layers @@ -7,10 +7,10 @@ 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 +RUN dotnet publish -c release -o /app -r linux-musl-x64 --no-restore --self-contained # final stage/image -FROM mcr.microsoft.com/dotnet/runtime-deps:5.0-alpine +FROM mcr.microsoft.com/dotnet/runtime-deps:9.0-alpine WORKDIR /app COPY --from=build /app . diff --git a/frameworks/CSharp/genhttp/Benchmarks/Benchmarks.csproj b/frameworks/CSharp/genhttp/Benchmarks/Benchmarks.csproj index 529f7add6ca..3a3b23ee153 100644 --- a/frameworks/CSharp/genhttp/Benchmarks/Benchmarks.csproj +++ b/frameworks/CSharp/genhttp/Benchmarks/Benchmarks.csproj @@ -2,14 +2,16 @@ - net9.0 - 13.0 + net10.0 + 14.0 true Exe GenHTTP Benchmarks Test suite to be executed with TechEmpower FrameworkBenchmarks. + $(DefineConstants);$(GENHTTP_ENGINE_NAME) + true true @@ -26,12 +28,19 @@ - - + + + - - + + + + + + + + diff --git a/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/DatabaseContextAssemblyAttributes.cs b/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/DatabaseContextAssemblyAttributes.cs new file mode 100644 index 00000000000..37f08394aae --- /dev/null +++ b/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/DatabaseContextAssemblyAttributes.cs @@ -0,0 +1,9 @@ +// +using Benchmarks; +using Benchmarks.Model; +using Microsoft.EntityFrameworkCore.Infrastructure; + +#pragma warning disable 219, 612, 618 +#nullable disable + +[assembly: DbContextModel(typeof(DatabaseContext), typeof(DatabaseContextModel))] diff --git a/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/DatabaseContextModel.cs b/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/DatabaseContextModel.cs new file mode 100644 index 00000000000..1f4a1357bcc --- /dev/null +++ b/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/DatabaseContextModel.cs @@ -0,0 +1,48 @@ +// +using Benchmarks.Model; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; + +#pragma warning disable 219, 612, 618 +#nullable disable + +namespace Benchmarks +{ + [DbContext(typeof(DatabaseContext))] + public partial class DatabaseContextModel : RuntimeModel + { + private static readonly bool _useOldBehavior31751 = + System.AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue31751", out var enabled31751) && enabled31751; + + static DatabaseContextModel() + { + var model = new DatabaseContextModel(); + + if (_useOldBehavior31751) + { + model.Initialize(); + } + else + { + var thread = new System.Threading.Thread(RunInitialization, 10 * 1024 * 1024); + thread.Start(); + thread.Join(); + + void RunInitialization() + { + model.Initialize(); + } + } + + model.Customize(); + _instance = (DatabaseContextModel)model.FinalizeModel(); + } + + private static DatabaseContextModel _instance; + public static IModel Instance => _instance; + + partial void Initialize(); + + partial void Customize(); + } +} diff --git a/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/DatabaseContextModelBuilder.cs b/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/DatabaseContextModelBuilder.cs new file mode 100644 index 00000000000..763158097cb --- /dev/null +++ b/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/DatabaseContextModelBuilder.cs @@ -0,0 +1,32 @@ +// +using System; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#pragma warning disable 219, 612, 618 +#nullable disable + +namespace Benchmarks +{ + public partial class DatabaseContextModel + { + private DatabaseContextModel() + : base(skipDetectChanges: false, modelId: new Guid("e6a922c5-5e25-4191-8617-6c6410b754cc"), entityTypeCount: 2) + { + } + + partial void Initialize() + { + var fortune = FortuneEntityType.Create(this); + var world = WorldEntityType.Create(this); + + FortuneEntityType.CreateAnnotations(fortune); + WorldEntityType.CreateAnnotations(world); + + AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + AddAnnotation("ProductVersion", "10.0.0"); + AddAnnotation("Relational:MaxIdentifierLength", 63); + } + } +} diff --git a/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/FortuneEntityType.cs b/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/FortuneEntityType.cs new file mode 100644 index 00000000000..e89e9901b1a --- /dev/null +++ b/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/FortuneEntityType.cs @@ -0,0 +1,68 @@ +// +using System; +using System.Reflection; +using Benchmarks.Model; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#pragma warning disable 219, 612, 618 +#nullable disable + +namespace Benchmarks +{ + [EntityFrameworkInternal] + public partial class FortuneEntityType + { + public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) + { + var runtimeEntityType = model.AddEntityType( + "Benchmarks.Model.Fortune", + typeof(Fortune), + baseEntityType, + propertyCount: 2, + keyCount: 1); + + var id = runtimeEntityType.AddProperty( + "Id", + typeof(int), + propertyInfo: typeof(Fortune).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly), + fieldInfo: typeof(Fortune).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly), + valueGenerated: ValueGenerated.OnAdd, + afterSaveBehavior: PropertySaveBehavior.Throw, + sentinel: 0); + id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + id.AddAnnotation("Relational:ColumnName", "id"); + + var message = runtimeEntityType.AddProperty( + "Message", + typeof(string), + propertyInfo: typeof(Fortune).GetProperty("Message", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly), + fieldInfo: typeof(Fortune).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly), + nullable: true, + maxLength: 2048); + message.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None); + message.AddAnnotation("Relational:ColumnName", "message"); + + var key = runtimeEntityType.AddKey( + new[] { id }); + runtimeEntityType.SetPrimaryKey(key); + + return runtimeEntityType; + } + + public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) + { + runtimeEntityType.AddAnnotation("Relational:FunctionName", null); + runtimeEntityType.AddAnnotation("Relational:Schema", null); + runtimeEntityType.AddAnnotation("Relational:SqlQuery", null); + runtimeEntityType.AddAnnotation("Relational:TableName", "fortune"); + runtimeEntityType.AddAnnotation("Relational:ViewName", null); + runtimeEntityType.AddAnnotation("Relational:ViewSchema", null); + + Customize(runtimeEntityType); + } + + static partial void Customize(RuntimeEntityType runtimeEntityType); + } +} diff --git a/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/WorldEntityType.cs b/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/WorldEntityType.cs new file mode 100644 index 00000000000..470b07a82b8 --- /dev/null +++ b/frameworks/CSharp/genhttp/Benchmarks/Model/CompiledModel/WorldEntityType.cs @@ -0,0 +1,67 @@ +// +using System; +using System.Reflection; +using Benchmarks.Model; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#pragma warning disable 219, 612, 618 +#nullable disable + +namespace Benchmarks +{ + [EntityFrameworkInternal] + public partial class WorldEntityType + { + public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) + { + var runtimeEntityType = model.AddEntityType( + "Benchmarks.Model.World", + typeof(World), + baseEntityType, + propertyCount: 2, + keyCount: 1); + + var id = runtimeEntityType.AddProperty( + "Id", + typeof(int), + propertyInfo: typeof(World).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly), + fieldInfo: typeof(World).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly), + valueGenerated: ValueGenerated.OnAdd, + afterSaveBehavior: PropertySaveBehavior.Throw, + sentinel: 0); + id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + id.AddAnnotation("Relational:ColumnName", "id"); + + var randomNumber = runtimeEntityType.AddProperty( + "RandomNumber", + typeof(int), + propertyInfo: typeof(World).GetProperty("RandomNumber", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly), + fieldInfo: typeof(World).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly), + sentinel: 0); + randomNumber.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None); + randomNumber.AddAnnotation("Relational:ColumnName", "randomnumber"); + + var key = runtimeEntityType.AddKey( + new[] { id }); + runtimeEntityType.SetPrimaryKey(key); + + return runtimeEntityType; + } + + public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) + { + runtimeEntityType.AddAnnotation("Relational:FunctionName", null); + runtimeEntityType.AddAnnotation("Relational:Schema", null); + runtimeEntityType.AddAnnotation("Relational:SqlQuery", null); + runtimeEntityType.AddAnnotation("Relational:TableName", "world"); + runtimeEntityType.AddAnnotation("Relational:ViewName", null); + runtimeEntityType.AddAnnotation("Relational:ViewSchema", null); + + Customize(runtimeEntityType); + } + + static partial void Customize(RuntimeEntityType runtimeEntityType); + } +} diff --git a/frameworks/CSharp/genhttp/Benchmarks/Model/Database.cs b/frameworks/CSharp/genhttp/Benchmarks/Model/Database.cs new file mode 100644 index 00000000000..c49a8e9d1a4 --- /dev/null +++ b/frameworks/CSharp/genhttp/Benchmarks/Model/Database.cs @@ -0,0 +1,15 @@ +namespace Benchmarks.Model; + +public static class Database +{ + public static readonly DatabaseContextPool NoTrackingPool; + + public static readonly DatabaseContextPool TrackingPool; + + static Database() + { + NoTrackingPool = new DatabaseContextPool(factory: DatabaseContext.CreateNoTracking, maxSize: 512); + TrackingPool = new DatabaseContextPool(factory: DatabaseContext.CreateTracking, maxSize: 512); + } + +} diff --git a/frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContext.cs b/frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContext.cs index f27f1d8e245..bedd6a38454 100644 --- a/frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContext.cs +++ b/frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContext.cs @@ -1,43 +1,48 @@ using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace Benchmarks.Model; public sealed class DatabaseContext : DbContext { - private static DbContextOptions _options; + private static readonly Lazy> TrackingOptions = new(() => CreateOptions(true), LazyThreadSafetyMode.ExecutionAndPublication); - private static DbContextOptions _noTrackingOptions; + private static readonly Lazy> NoTrackingOptions = new(() => CreateOptions(false), LazyThreadSafetyMode.ExecutionAndPublication); - #region Factory + public static DatabaseContext CreateTracking() => new(TrackingOptions.Value, true); - public static DatabaseContext Create() => new(_options ??= GetOptions(true)); + public static DatabaseContext CreateNoTracking() => new(NoTrackingOptions.Value, false); - public static DatabaseContext CreateNoTracking() => new(_noTrackingOptions ??= GetOptions(false)); - - private static DbContextOptions GetOptions(bool tracking) + private static DbContextOptions CreateOptions(bool tracking) { - var optionsBuilder = new DbContextOptionsBuilder(); + var services = new ServiceCollection(); + + services.AddEntityFrameworkNpgsql(); + + var provider = services.BuildServiceProvider(); - optionsBuilder.UseNpgsql("Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=512;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4"); + var builder = new DbContextOptionsBuilder(); + + builder.UseInternalServiceProvider(provider) + .UseNpgsql("Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=512;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true") + .EnableThreadSafetyChecks(false) + .UseModel(DatabaseContextModel.Instance); if (!tracking) { - optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); + builder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); } - return optionsBuilder.Options; + return builder.Options; } - private DatabaseContext(DbContextOptions options) : base(options) { } - - #endregion - - #region Entities + internal DatabaseContext(DbContextOptions options, bool tracking = false) : base(options) + { + ChangeTracker.AutoDetectChangesEnabled = tracking; + } public DbSet World { get; set; } public DbSet Fortune { get; set; } - #endregion - } diff --git a/frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContextFactory.cs b/frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContextFactory.cs new file mode 100644 index 00000000000..8c6c62c83ac --- /dev/null +++ b/frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContextFactory.cs @@ -0,0 +1,18 @@ +namespace Benchmarks.Model; + +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; + +public class DatabaseContextFactory : IDesignTimeDbContextFactory +{ + + public DatabaseContext CreateDbContext(string[] args) + { + var options = new DbContextOptionsBuilder() + .UseNpgsql("Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable") + .Options; + + return new DatabaseContext(options); + } + +} diff --git a/frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContextPool.cs b/frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContextPool.cs new file mode 100644 index 00000000000..aaec09ccf53 --- /dev/null +++ b/frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContextPool.cs @@ -0,0 +1,46 @@ +namespace Benchmarks.Model; + +using System.Collections.Concurrent; + +using Microsoft.EntityFrameworkCore; + +public sealed class DatabaseContextPool where TContext : DbContext +{ + private readonly ConcurrentBag _pool = new(); + + private readonly Func _factory; + + private readonly int _maxSize; + + public DatabaseContextPool(Func factory, int maxSize) + { + _factory = factory; + _maxSize = maxSize; + } + + public TContext Rent() + { + if (_pool.TryTake(out var ctx)) + { + ctx.ChangeTracker.Clear(); + return ctx; + } + + return _factory(); + } + + public void Return(TContext context) + { + if (_pool.Count >= _maxSize) + { + context.Dispose(); + return; + } + + + context.ChangeTracker.Clear(); + + _pool.Add(context); + } + +} diff --git a/frameworks/CSharp/genhttp/Benchmarks/Program.cs b/frameworks/CSharp/genhttp/Benchmarks/Program.cs index dd55ad6b782..91323662c2d 100644 --- a/frameworks/CSharp/genhttp/Benchmarks/Program.cs +++ b/frameworks/CSharp/genhttp/Benchmarks/Program.cs @@ -1,7 +1,11 @@ using Benchmarks.Tests; using Benchmarks.Utilities; +#if INTERNAL using GenHTTP.Engine.Internal; +#else +using GenHTTP.Engine.Kestrel; +#endif using GenHTTP.Modules.IO; using GenHTTP.Modules.Layouting; diff --git a/frameworks/CSharp/genhttp/Benchmarks/Tests/CacheResource.cs b/frameworks/CSharp/genhttp/Benchmarks/Tests/CacheResource.cs index e0e4bc50d91..5a899bcadfd 100644 --- a/frameworks/CSharp/genhttp/Benchmarks/Tests/CacheResource.cs +++ b/frameworks/CSharp/genhttp/Benchmarks/Tests/CacheResource.cs @@ -37,29 +37,36 @@ public async ValueTask> GetWorlds(string queries) var result = new List(count); - await using var context = DatabaseContext.CreateNoTracking(); + var context = Database.NoTrackingPool.Rent(); - for (var i = 0; i < count; i++) + try { - var id = Random.Next(1, 10001); + for (var i = 0; i < count; i++) + { + var id = Random.Next(1, 10001); - var key = CacheKeys[id]; + var key = CacheKeys[id]; - var data = Cache.Get(key); + var data = Cache.Get(key); - if (data != null) - { - result.Add(data); - } - else - { - var resolved = await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false); + if (data != null) + { + result.Add(data); + } + else + { + var resolved = await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false); - Cache.Set(key, resolved); + Cache.Set(key, resolved); - result.Add(resolved); + result.Add(resolved); + } } } + finally + { + Database.NoTrackingPool.Return(context); + } return result; } diff --git a/frameworks/CSharp/genhttp/Benchmarks/Tests/DbResource.cs b/frameworks/CSharp/genhttp/Benchmarks/Tests/DbResource.cs index ac33808fdfd..3363db1180d 100644 --- a/frameworks/CSharp/genhttp/Benchmarks/Tests/DbResource.cs +++ b/frameworks/CSharp/genhttp/Benchmarks/Tests/DbResource.cs @@ -13,9 +13,16 @@ public async ValueTask GetRandomWorld() { var id = Random.Next(1, 10001); - await using var context = DatabaseContext.CreateNoTracking(); + var context = Database.NoTrackingPool.Rent(); - return await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false); + try + { + return await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false); + } + finally + { + Database.NoTrackingPool.Return(context); + } } } diff --git a/frameworks/CSharp/genhttp/Benchmarks/Tests/FortuneHandler.cs b/frameworks/CSharp/genhttp/Benchmarks/Tests/FortuneHandler.cs index c7a488f5e78..5f4f6d8860c 100644 --- a/frameworks/CSharp/genhttp/Benchmarks/Tests/FortuneHandler.cs +++ b/frameworks/CSharp/genhttp/Benchmarks/Tests/FortuneHandler.cs @@ -48,36 +48,43 @@ public async ValueTask HandleAsync(IRequest request) private static async ValueTask> GetFortunes() { - await using var context = DatabaseContext.CreateNoTracking(); + var context = Database.NoTrackingPool.Rent(); - var fortunes = await context.Fortune.ToListAsync().ConfigureAwait(false); + try + { + var fortunes = await context.Fortune.ToListAsync().ConfigureAwait(false); - var result = new List(fortunes.Count + 1); + var result = new List(fortunes.Count + 1); + + foreach (var fortune in fortunes) + { + result.Add(Value.FromDictionary(new Dictionary() + { + ["id"] = fortune.Id, + ["message"] = HttpUtility.HtmlEncode(fortune.Message) + })); + } - foreach (var fortune in fortunes) - { result.Add(Value.FromDictionary(new Dictionary() { - ["id"] = fortune.Id, - ["message"] = HttpUtility.HtmlEncode(fortune.Message) + ["id"] = 0, + ["message"] = "Additional fortune added at request time." })); - } - - result.Add(Value.FromDictionary(new Dictionary() - { - ["id"] = 0, - ["message"] = "Additional fortune added at request time." - })); - result.Sort((one, two) => - { - var firstMessage = one.Fields["message"].AsString; - var secondMessage = two.Fields["message"].AsString; + result.Sort((one, two) => + { + var firstMessage = one.Fields["message"].AsString; + var secondMessage = two.Fields["message"].AsString; - return string.Compare(firstMessage, secondMessage, StringComparison.Ordinal); - }); + return string.Compare(firstMessage, secondMessage, StringComparison.Ordinal); + }); - return result; + return result; + } + finally + { + Database.NoTrackingPool.Return(context); + } } #endregion diff --git a/frameworks/CSharp/genhttp/Benchmarks/Tests/JsonHandler.cs b/frameworks/CSharp/genhttp/Benchmarks/Tests/JsonHandler.cs index 4944c669198..7fb89b926d7 100644 --- a/frameworks/CSharp/genhttp/Benchmarks/Tests/JsonHandler.cs +++ b/frameworks/CSharp/genhttp/Benchmarks/Tests/JsonHandler.cs @@ -1,10 +1,8 @@ -using System.Text.Json; +using Benchmarks.Utilities; using GenHTTP.Api.Content; using GenHTTP.Api.Protocol; -using GenHTTP.Modules.Conversion.Serializers.Json; - namespace Benchmarks.Tests; public sealed class JsonResult @@ -15,9 +13,7 @@ public sealed class JsonResult public sealed class JsonHandler : IHandler { - private static readonly FlexibleContentType _ContentType = new(ContentType.ApplicationJson, "utf-8"); - - private static readonly JsonSerializerOptions _Options = new(); + private static readonly FlexibleContentType ContentType = new(GenHTTP.Api.Protocol.ContentType.ApplicationJson, "utf-8"); public ValueTask PrepareAsync() => new(); @@ -29,8 +25,8 @@ public ValueTask HandleAsync(IRequest request) }; var response = request.Respond() - .Content(new JsonContent(result, _Options)) - .Type(_ContentType) + .Content(new FixedLengthJsonContent(result)) + .Type(ContentType) .Build(); return new(response); diff --git a/frameworks/CSharp/genhttp/Benchmarks/Tests/QueryResource.cs b/frameworks/CSharp/genhttp/Benchmarks/Tests/QueryResource.cs index 592d9083242..e9a0877f542 100644 --- a/frameworks/CSharp/genhttp/Benchmarks/Tests/QueryResource.cs +++ b/frameworks/CSharp/genhttp/Benchmarks/Tests/QueryResource.cs @@ -29,16 +29,23 @@ public async ValueTask> GetWorlds(string queries) var result = new List(count); - using var context = DatabaseContext.CreateNoTracking(); + var context = Database.NoTrackingPool.Rent(); - for (var _ = 0; _ < count; _++) + try { - var id = Random.Next(1, 10001); + for (var _ = 0; _ < count; _++) + { + var id = Random.Next(1, 10001); - result.Add(await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false)); + result.Add(await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false)); + } + } + finally + { + Database.NoTrackingPool.Return(context); } return result; } -} \ No newline at end of file +} diff --git a/frameworks/CSharp/genhttp/Benchmarks/Tests/UpdateResource.cs b/frameworks/CSharp/genhttp/Benchmarks/Tests/UpdateResource.cs index 9b2ce8e270c..826c30a7bd3 100644 --- a/frameworks/CSharp/genhttp/Benchmarks/Tests/UpdateResource.cs +++ b/frameworks/CSharp/genhttp/Benchmarks/Tests/UpdateResource.cs @@ -31,7 +31,9 @@ public async ValueTask> UpdateWorlds(string queries) var ids = Enumerable.Range(1, 10000).Select(x => Random.Next(1, 10001)).Distinct().Take(count).ToArray(); - using (var context = DatabaseContext.Create()) + var context = Database.TrackingPool.Rent(); + + try { foreach (var id in ids) { @@ -58,7 +60,11 @@ public async ValueTask> UpdateWorlds(string queries) await context.SaveChangesAsync(); } } + finally + { + Database.TrackingPool.Return(context); + } return result; } -} \ No newline at end of file +} diff --git a/frameworks/CSharp/genhttp/Benchmarks/Utilities/FixedLengthJsonContent.cs b/frameworks/CSharp/genhttp/Benchmarks/Utilities/FixedLengthJsonContent.cs new file mode 100644 index 00000000000..7ef372c65f0 --- /dev/null +++ b/frameworks/CSharp/genhttp/Benchmarks/Utilities/FixedLengthJsonContent.cs @@ -0,0 +1,31 @@ +using System.Text.Json; + +using GenHTTP.Api.Protocol; + +using Benchmarks.Tests; + +namespace Benchmarks.Utilities; + +public sealed class FixedLengthJsonContent : IResponseContent +{ + private readonly MemoryStream _buffer = new(); + + public ulong? Length => (ulong)_buffer.Length; + + public FixedLengthJsonContent(JsonResult result) + { + JsonSerializer.SerializeAsync(_buffer, result); + } + + public ValueTask CalculateChecksumAsync() => throw new NotImplementedException(); + + public ValueTask WriteAsync(Stream target, uint bufferSize) + { + _buffer.Seek(0, SeekOrigin.Begin); + + _buffer.CopyTo(target); + + return ValueTask.CompletedTask; + } + +} diff --git a/frameworks/CSharp/genhttp/benchmark_config.json b/frameworks/CSharp/genhttp/benchmark_config.json index bf1780e753a..f2376bf64fc 100644 --- a/frameworks/CSharp/genhttp/benchmark_config.json +++ b/frameworks/CSharp/genhttp/benchmark_config.json @@ -1,5 +1,6 @@ { - "framework": "genhttp", + "framework": "genhttp", + "maintainers": ["Kaliumhexacyanoferrat"], "tests": [{ "default": { "plaintext_url": "/plaintext", @@ -17,11 +18,33 @@ "language": "C#", "orm": "Raw", "platform": ".NET", - "webserver": "Kestrel", + "webserver": "GenHTTP", "os": "Linux", "database_os": "Linux", - "display_name": "GenHTTP", + "display_name": "genhttp [internal]", "notes": "" + }, + "kestrel": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries/", + "update_url": "/updates/", + "fortune_url": "/fortunes", + "cached_query_url": "/cached-worlds/", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "Postgres", + "framework": "GenHTTP", + "language": "C#", + "orm": "Raw", + "platform": ".NET", + "webserver": "Kestrel", + "os": "Linux", + "database_os": "Linux", + "display_name": "genhttp [kestrel]", + "notes": "" } }] } diff --git a/frameworks/CSharp/genhttp/config.toml b/frameworks/CSharp/genhttp/config.toml index f984318f53b..538213c05b4 100644 --- a/frameworks/CSharp/genhttp/config.toml +++ b/frameworks/CSharp/genhttp/config.toml @@ -16,5 +16,23 @@ database_os = "Linux" os = "Linux" orm = "Raw" platform = ".NET" +webserver = "GenHTTP" +versus = "None" + +[kestrel] +urls.plaintext = "/plaintext" +urls.json = "/json" +urls.db = "/db" +urls.query = "/queries/" +urls.update = "/updates/" +urls.fortune = "/fortunes" +urls.cached_query = "/cached-worlds/" +approach = "Realistic" +classification = "Fullstack" +database = "Postgres" +database_os = "Linux" +os = "Linux" +orm = "Raw" +platform = ".NET" webserver = "Kestrel" versus = "None" diff --git a/frameworks/CSharp/genhttp/genhttp-kestrel.dockerfile b/frameworks/CSharp/genhttp/genhttp-kestrel.dockerfile new file mode 100644 index 00000000000..e345a538f34 --- /dev/null +++ b/frameworks/CSharp/genhttp/genhttp-kestrel.dockerfile @@ -0,0 +1,33 @@ +FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build +WORKDIR /source + +ENV GENHTTP_ENGINE_NAME=KESTREL +ENV GENHTTP_ENGINE_PACKAGE=GenHTTP.Core.Kestrel + +# 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 +FROM mcr.microsoft.com/dotnet/runtime-deps:10.0-alpine + +ENV DOTNET_GCDynamicAdaptationMode=0 \ + DOTNET_EnableDiagnostics=0 \ + COMPlus_EnableDiagnostics=0 \ + COMPlus_DbgEnableMiniDump=0 \ + COMPlus_DbgEnableMiniDumpCollection=0 \ + COMPlus_DbgMiniDumpType=0 \ + DOTNET_TieredPGO=0 \ + DOTNET_TC_QuickJitForLoops=1 \ + DOTNET_TC_QuickJit=1 + +WORKDIR /app +COPY --from=build /app . + +ENTRYPOINT ["./Benchmarks"] + +EXPOSE 8080 diff --git a/frameworks/CSharp/genhttp/genhttp.dockerfile b/frameworks/CSharp/genhttp/genhttp.dockerfile index 8c473477a61..9414123202e 100644 --- a/frameworks/CSharp/genhttp/genhttp.dockerfile +++ b/frameworks/CSharp/genhttp/genhttp.dockerfile @@ -1,6 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build WORKDIR /source +ENV GENHTTP_ENGINE_NAME=INTERNAL +ENV GENHTTP_ENGINE_PACKAGE=GenHTTP.Core + # copy csproj and restore as distinct layers COPY Benchmarks/*.csproj . RUN dotnet restore -r linux-musl-x64 @@ -10,11 +13,17 @@ COPY Benchmarks/ . RUN dotnet publish -c release -o /app -r linux-musl-x64 --no-restore --self-contained # final stage/image -FROM mcr.microsoft.com/dotnet/runtime-deps:9.0-alpine +FROM mcr.microsoft.com/dotnet/runtime-deps:10.0-alpine -ENV DOTNET_GCDynamicAdaptationMode=0 -ENV DOTNET_ReadyToRun=0 -ENV DOTNET_HillClimbing_Disable=1 +ENV DOTNET_GCDynamicAdaptationMode=0 \ + DOTNET_EnableDiagnostics=0 \ + COMPlus_EnableDiagnostics=0 \ + COMPlus_DbgEnableMiniDump=0 \ + COMPlus_DbgEnableMiniDumpCollection=0 \ + COMPlus_DbgMiniDumpType=0 \ + DOTNET_TieredPGO=0 \ + DOTNET_TC_QuickJitForLoops=1 \ + DOTNET_TC_QuickJit=1 WORKDIR /app COPY --from=build /app . diff --git a/frameworks/CSharp/netcoreserver/Benchmarks/Benchmarks.csproj b/frameworks/CSharp/netcoreserver/Benchmarks/Benchmarks.csproj index 6d372b01ee3..8315e4a6e83 100644 --- a/frameworks/CSharp/netcoreserver/Benchmarks/Benchmarks.csproj +++ b/frameworks/CSharp/netcoreserver/Benchmarks/Benchmarks.csproj @@ -1,24 +1,24 @@  - + - - net5.0 - 9.0 - + + net9.0 + 13.0 + EmbedIO Benchmarks Test suite to be executed with TechEmpower FrameworkBenchmarks. - - Benchmarks.Program + + Benchmarks.Program Exe - + true false - + - + - - + + - - \ No newline at end of file + + diff --git a/frameworks/CSharp/netcoreserver/Benchmarks/HttpBenchmarkSession.cs b/frameworks/CSharp/netcoreserver/Benchmarks/HttpBenchmarkSession.cs index 25e58bd5aa1..bb99ce8f2c1 100644 --- a/frameworks/CSharp/netcoreserver/Benchmarks/HttpBenchmarkSession.cs +++ b/frameworks/CSharp/netcoreserver/Benchmarks/HttpBenchmarkSession.cs @@ -27,7 +27,7 @@ protected override void OnReceivedRequest(HttpRequest request) } else { - SendResponseAsync(Response.MakeErrorResponse("Not found", 404)); + SendResponseAsync(Response.MakeErrorResponse(404, "Not found")); } } diff --git a/frameworks/CSharp/netcoreserver/Benchmarks/Program.cs b/frameworks/CSharp/netcoreserver/Benchmarks/Program.cs index 411569ffb2f..3a821463b10 100644 --- a/frameworks/CSharp/netcoreserver/Benchmarks/Program.cs +++ b/frameworks/CSharp/netcoreserver/Benchmarks/Program.cs @@ -8,7 +8,7 @@ namespace Benchmarks public static class Program { - private static readonly ManualResetEvent _WaitEvent = new ManualResetEvent(false); + private static readonly ManualResetEvent WaitEvent = new(false); public static int Main(string[] args) { @@ -18,12 +18,12 @@ public static int Main(string[] args) { AppDomain.CurrentDomain.ProcessExit += (_, __) => { - _WaitEvent.Set(); + WaitEvent.Set(); }; server.Start(); - _WaitEvent.WaitOne(); + WaitEvent.WaitOne(); return 0; } diff --git a/frameworks/CSharp/netcoreserver/README.md b/frameworks/CSharp/netcoreserver/README.md index 985758c2bc9..31c1e995dcd 100644 --- a/frameworks/CSharp/netcoreserver/README.md +++ b/frameworks/CSharp/netcoreserver/README.md @@ -6,17 +6,17 @@ See the [project website](https://github.com/chronoxor/NetCoreServer) for more i **Language** -* C# 9.0 +* C# 13.0 **Platforms** -* .NET 5 +* .NET 9 **Web Servers** * [NetCoreServer](https://github.com/chronoxor/NetCoreServer) -## Paths & Source for Tests +## Paths \& Source for Tests * [Plaintext](Benchmarks/HttpBenchmarkSession.cs): "/plaintext" * [JSON](Benchmarks/HttpBenchmarkSession.cs): "/json" diff --git a/frameworks/CSharp/netcoreserver/netcoreserver.dockerfile b/frameworks/CSharp/netcoreserver/netcoreserver.dockerfile index 675c16d8841..35e05ff1fc4 100644 --- a/frameworks/CSharp/netcoreserver/netcoreserver.dockerfile +++ b/frameworks/CSharp/netcoreserver/netcoreserver.dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build WORKDIR /source # copy csproj and restore as distinct layers @@ -7,10 +7,10 @@ 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 +RUN dotnet publish -c release -o /app -r linux-musl-x64 --no-restore --self-contained # final stage/image -FROM mcr.microsoft.com/dotnet/runtime-deps:5.0-alpine +FROM mcr.microsoft.com/dotnet/runtime-deps:9.0-alpine WORKDIR /app COPY --from=build /app . diff --git a/frameworks/CSharp/revenj/benchmark_config.json b/frameworks/CSharp/revenj/benchmark_config.json index 8472ef41d12..402a5129f93 100644 --- a/frameworks/CSharp/revenj/benchmark_config.json +++ b/frameworks/CSharp/revenj/benchmark_config.json @@ -22,6 +22,7 @@ "os": "Linux", "display_name": "Revenj", "notes": "", + "tags": ["broken"], "versus": "Revenj" } }] diff --git a/frameworks/CSharp/sisk/.dockerignore b/frameworks/CSharp/sisk/.dockerignore new file mode 100644 index 00000000000..36094dc1468 --- /dev/null +++ b/frameworks/CSharp/sisk/.dockerignore @@ -0,0 +1,2 @@ +**/[b|B]in/ +**/[O|o]bj/ \ No newline at end of file diff --git a/frameworks/CSharp/sisk/sisk-cadente.dockerfile b/frameworks/CSharp/sisk/sisk-cadente.dockerfile index 34092a0e15c..1db042daef7 100644 --- a/frameworks/CSharp/sisk/sisk-cadente.dockerfile +++ b/frameworks/CSharp/sisk/sisk-cadente.dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build WORKDIR /source # copy csproj and restore as distinct layers @@ -7,17 +7,18 @@ RUN dotnet restore -r linux-musl-x64 # copy and publish app and libraries COPY sisk-cadente/ . -RUN dotnet publish -c release -o /app +RUN dotnet publish -c release -o /app -r linux-musl-x64 --no-restore --self-contained + +# final stage/image +FROM mcr.microsoft.com/dotnet/runtime-deps:10.0-alpine ENV DOTNET_GCDynamicAdaptationMode=0 ENV DOTNET_ReadyToRun=0 ENV DOTNET_HillClimbing_Disable=1 -# final stage/image -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime WORKDIR /app COPY --from=build /app . -ENTRYPOINT ["dotnet", "./sisk.dll"] +ENTRYPOINT ["./sisk"] EXPOSE 8080 \ No newline at end of file diff --git a/frameworks/CSharp/sisk/sisk-cadente/Program.cs b/frameworks/CSharp/sisk/sisk-cadente/Program.cs index 267877ee584..f198260cbde 100644 --- a/frameworks/CSharp/sisk/sisk-cadente/Program.cs +++ b/frameworks/CSharp/sisk/sisk-cadente/Program.cs @@ -1,44 +1,50 @@ -using System.Net; +using System.Buffers.Text; +using System.Net; using System.Text; using System.Text.Json; using Sisk.Cadente; -HttpHost.QueueSize = 4096; - -var host = new HttpHost ( new IPEndPoint ( IPAddress.Any, 8080 ) ); -host.ContextCreated += Host_ContextCreated; +using var host = new HttpHost ( new IPEndPoint ( IPAddress.Any, 8080 ) ); +host.Handler = new DefaultHandler(); host.Start (); Thread.Sleep ( Timeout.Infinite ); -void Host_ContextCreated ( HttpHost sender, HttpHostContext session ) { - var request = session.Request; - - if (request.Path == "/plaintext") { - SerializePlainTextResponse ( session.Response ); - } - else if (request.Path == "/json") { - SerializeJsonResponse ( session.Response ); - } - else { - session.Response.StatusCode = 404; - } -} - -static void SerializePlainTextResponse ( HttpHostContext.HttpResponse response ) { - - var messageBytes = Encoding.UTF8.GetBytes ( "Hello, World!" ); - response.Headers.Add ( new HttpHeader ( "Content-Type", "text/plain; charset=UTF-8" ) ); - response.ResponseStream = new MemoryStream ( messageBytes ); -} +class DefaultHandler : HttpHostHandler +{ + public override async Task OnContextCreatedAsync(HttpHost host, HttpHostContext context) + { + var request = context.Request; + var response = context.Response; + + if (request.Path == "/plaintext") + { + var contentBytes = Encoding.UTF8.GetBytes("Hello, World!"); + + await SerializeResponseAsync(response, contentBytes, "text/plain; charset=utf-8"); + } + else if (request.Path == "/json") + { + var contentBytes = JsonSerializer.SerializeToUtf8Bytes(new + { + message = "Hello, World!" + }); + + await SerializeResponseAsync(response, contentBytes, "application/json; charset=utf-8"); + } + else + { + response.StatusCode = 404; + } + } -static void SerializeJsonResponse ( HttpHostContext.HttpResponse response ) { + static async ValueTask SerializeResponseAsync(HttpHostContext.HttpResponse response, Memory content, string contentType) + { + response.Headers.Add(new HttpHeader("Content-Type", contentType)); + response.Headers.Add(new HttpHeader("Content-Length", content.Length.ToString())); - var contentBytes = JsonSerializer.SerializeToUtf8Bytes ( new { - message = "Hello, World!" - } ); - - response.Headers.Add ( new HttpHeader ( "Content-Type", "application/json" ) ); - response.ResponseStream = new MemoryStream ( contentBytes ); + using var responseStream = await response.GetResponseStreamAsync(); + await responseStream.WriteAsync(content); + } } \ No newline at end of file diff --git a/frameworks/CSharp/sisk/sisk-cadente/sisk.csproj b/frameworks/CSharp/sisk/sisk-cadente/sisk.csproj index c72c3f1faee..01c1524d5b6 100644 --- a/frameworks/CSharp/sisk/sisk-cadente/sisk.csproj +++ b/frameworks/CSharp/sisk/sisk-cadente/sisk.csproj @@ -9,7 +9,7 @@ - + \ No newline at end of file diff --git a/frameworks/CSharp/sisk/sisk.dockerfile b/frameworks/CSharp/sisk/sisk.dockerfile index 2a23e04743f..1c6d9d3f3e2 100644 --- a/frameworks/CSharp/sisk/sisk.dockerfile +++ b/frameworks/CSharp/sisk/sisk.dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build WORKDIR /source # copy csproj and restore as distinct layers @@ -7,13 +7,18 @@ RUN dotnet restore -r linux-musl-x64 # copy and publish app and libraries COPY sisk/ . -RUN dotnet publish -c release -o /app -r linux-musl-x64 +RUN dotnet publish -c release -o /app -r linux-musl-x64 --no-restore --self-contained # final stage/image -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime +FROM mcr.microsoft.com/dotnet/runtime-deps:10.0-alpine + +ENV DOTNET_GCDynamicAdaptationMode=0 +ENV DOTNET_ReadyToRun=0 +ENV DOTNET_HillClimbing_Disable=1 + WORKDIR /app COPY --from=build /app . -ENTRYPOINT ["dotnet", "./sisk.dll"] +ENTRYPOINT ["./sisk"] EXPOSE 8080 \ No newline at end of file diff --git a/frameworks/CSharp/sisk/sisk/sisk.csproj b/frameworks/CSharp/sisk/sisk/sisk.csproj index e767d50ede0..17f488a6242 100644 --- a/frameworks/CSharp/sisk/sisk/sisk.csproj +++ b/frameworks/CSharp/sisk/sisk/sisk.csproj @@ -9,7 +9,7 @@ - + diff --git a/frameworks/CSharp/touchsocket/Benchmarks.sln b/frameworks/CSharp/touchsocket/Benchmarks.sln index 6f164942105..8d41045e044 100644 --- a/frameworks/CSharp/touchsocket/Benchmarks.sln +++ b/frameworks/CSharp/touchsocket/Benchmarks.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 -VisualStudioVersion = 18.0.11109.219 d18.0-oob +VisualStudioVersion = 18.0.11109.219 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TouchSocketWebApi", "src\TouchSocketWebApi\TouchSocketWebApi.csproj", "{6BD9363A-D77F-5D90-8444-2BC37495C920}" EndProject @@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TouchSocketHttp31", "src\To EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TouchSocketWebApi31", "src\TouchSocketWebApi31\TouchSocketWebApi31.csproj", "{6B6A57CE-1F69-FA6E-7458-0A4B6AB60683}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TouchSocketHttpPlatform", "src\TouchSocketHttpPlatform\TouchSocketHttpPlatform.csproj", "{BC320C24-941D-2109-FBC8-92780569BBA4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +35,10 @@ Global {6B6A57CE-1F69-FA6E-7458-0A4B6AB60683}.Debug|Any CPU.Build.0 = Debug|Any CPU {6B6A57CE-1F69-FA6E-7458-0A4B6AB60683}.Release|Any CPU.ActiveCfg = Release|Any CPU {6B6A57CE-1F69-FA6E-7458-0A4B6AB60683}.Release|Any CPU.Build.0 = Release|Any CPU + {BC320C24-941D-2109-FBC8-92780569BBA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC320C24-941D-2109-FBC8-92780569BBA4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC320C24-941D-2109-FBC8-92780569BBA4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC320C24-941D-2109-FBC8-92780569BBA4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/frameworks/CSharp/touchsocket/README.md b/frameworks/CSharp/touchsocket/README.md index 22524d6f70a..8a520d40eec 100644 --- a/frameworks/CSharp/touchsocket/README.md +++ b/frameworks/CSharp/touchsocket/README.md @@ -2,9 +2,40 @@ See [touchsocket](https://touchsocket.net/) for more information. +## Variants Included + +* `touchsocket.webapi` (`TouchSocketWebApi`) – WebApi style. +* `touchsocket.webapi31` (`TouchSocketWebApi31`) – WebApi targeting .NET 8. +* `touchsocket.http` (`TouchSocketHttp`) – Minimal HTTP implementation. +* `touchsocket.http31` (`TouchSocketHttp31`) – Minimal HTTP targeting .NET 8. +* `touchsocket.httpplatform` (`TouchSocketHttpPlatform`) – High-performance custom pipeline-based HTTP server focusing on low-level parsing and zero-allocation response writing. + ## Infrastructure Software Versions -**Language** +**Language / Runtime** + +* C# / .NET (8.0 & 9.0 depending on variant) + +## Endpoints + +All variants implement: + +* `/plaintext` – Returns a plain text "Hello, World!" response. +* `/json` – Returns a JSON object `{"message": "Hello, World!"}`. + +The `httpplatform` variant manually parses request lines and headers via `System.IO.Pipelines` for maximum throughput. + +## Dockerfiles + +Each variant has a dedicated Dockerfile named: + +* `touchsocket.dockerfile` (webapi) +* `touchsocket-webapi31.dockerfile` +* `touchsocket-http.dockerfile` +* `touchsocket-http31.dockerfile` +* `touchsocket-httpplatform.dockerfile` + +## Notes -* C# 8.0 +The `httpplatform` variant is intended for benchmarking raw server performance. It omits higher-level abstractions to reduce overhead. diff --git a/frameworks/CSharp/touchsocket/benchmark_config.json b/frameworks/CSharp/touchsocket/benchmark_config.json index 8aa1e953f59..2a6d6c27e98 100644 --- a/frameworks/CSharp/touchsocket/benchmark_config.json +++ b/frameworks/CSharp/touchsocket/benchmark_config.json @@ -55,7 +55,7 @@ "webserver": "touchsocket", "os": "Linux", "database_os": "Linux", - "display_name": "touchsocket.http31", + "display_name": "touchsocket.http [v3.1]", "notes": "", "versus": "aspnetcore" }, @@ -74,9 +74,28 @@ "webserver": "touchsocket", "os": "Linux", "database_os": "Linux", - "display_name": "touchsocket.webapi31", + "display_name": "touchsocket.webapi [v3.1]", "notes": "", "versus": "aspnetcore-mvc" + }, + "httpplatform": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "Postgres", + "framework": "touchsocket.httpplatform", + "language": "C#", + "orm": "Micro", + "platform": ".NET", + "flavor": "CoreCLR", + "webserver": "touchsocket", + "os": "Linux", + "database_os": "Linux", + "display_name": "touchsocket.http [Platform]", + "notes": "High-performance custom pipeline-based implementation variant.", + "versus": "aspnetcore" } } ] diff --git a/frameworks/CSharp/touchsocket/config.toml b/frameworks/CSharp/touchsocket/config.toml index 9af10d4a486..0d06cb4e331 100644 --- a/frameworks/CSharp/touchsocket/config.toml +++ b/frameworks/CSharp/touchsocket/config.toml @@ -52,3 +52,16 @@ orm = "Raw" platform = ".NET" webserver = "touchsocket.webapi31" versus = "aspcore-mvc" + +[httpplatform] +urls.plaintext = "/plaintext" +urls.json = "/json" +approach = "Realistic" +classification = "Micro" +database = "Postgres" +database_os = "Linux" +os = "Linux" +orm = "Raw" +platform = ".NET" +webserver = "touchsocket.httpplatform" +versus = "aspcore" diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketHttp/Program.cs b/frameworks/CSharp/touchsocket/src/TouchSocketHttp/Program.cs index 125284cd970..de84e8b6028 100644 --- a/frameworks/CSharp/touchsocket/src/TouchSocketHttp/Program.cs +++ b/frameworks/CSharp/touchsocket/src/TouchSocketHttp/Program.cs @@ -1,7 +1,8 @@ +using System.Buffers; +using System.IO.Pipelines; using System.Text; using TouchSocket.Core; using TouchSocket.Http; -using TouchSocket.Sockets; using HttpContent = TouchSocket.Http.HttpContent; namespace TouchSocketHttp; @@ -10,12 +11,34 @@ public class Program { private static async Task Main(string[] args) { - var port = 8080; - var service = new MyHttpService(); + int port = 8080; + MyHttpService service = new MyHttpService(); await service.SetupAsync(new TouchSocketConfig() .SetListenIPHosts(port) .SetMaxCount(1000000) + .SetTransportOption(options => + { + options.BufferOnDemand = false; + + options.ReceivePipeOptions = new PipeOptions( + pool: MemoryPool.Shared, + readerScheduler: PipeScheduler.ThreadPool, + writerScheduler: PipeScheduler.ThreadPool, + pauseWriterThreshold: 1024 * 1024, + resumeWriterThreshold: 1024 * 512, + minimumSegmentSize: -1, + useSynchronizationContext: false); + + options.SendPipeOptions = new PipeOptions( + pool: MemoryPool.Shared, + readerScheduler: PipeScheduler.ThreadPool, + writerScheduler: PipeScheduler.ThreadPool, + pauseWriterThreshold: 64 * 1024, + resumeWriterThreshold: 32 * 1024, + minimumSegmentSize: -1, + useSynchronizationContext: false); + }) .ConfigureContainer(a => { a.AddConsoleLogger(); @@ -45,8 +68,8 @@ internal sealed class MyHttpSessionClient : HttpSessionClient protected override async Task OnReceivedHttpRequest(HttpContext httpContext) { - var request = httpContext.Request; - var response = httpContext.Response; + HttpRequest request = httpContext.Request; + HttpResponse response = httpContext.Response; switch (request.RelativeURL) { diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketHttp/TouchSocketHttp.csproj b/frameworks/CSharp/touchsocket/src/TouchSocketHttp/TouchSocketHttp.csproj index 74caaf7a658..c694366fc8d 100644 --- a/frameworks/CSharp/touchsocket/src/TouchSocketHttp/TouchSocketHttp.csproj +++ b/frameworks/CSharp/touchsocket/src/TouchSocketHttp/TouchSocketHttp.csproj @@ -1,18 +1,14 @@ - + - net9.0 + net10.0 enable Exe enable - true - dotnet-TouchSocketWebApi-987c185f-10b1-452b-beb6-47d798a5a131 - - - + diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketHttp31/TouchSocketHttp31.csproj b/frameworks/CSharp/touchsocket/src/TouchSocketHttp31/TouchSocketHttp31.csproj index 8f8a2d69035..9b0d67f1fad 100644 --- a/frameworks/CSharp/touchsocket/src/TouchSocketHttp31/TouchSocketHttp31.csproj +++ b/frameworks/CSharp/touchsocket/src/TouchSocketHttp31/TouchSocketHttp31.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable Exe enable diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/DateHeader.cs b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/DateHeader.cs new file mode 100644 index 00000000000..9f0049fc54d --- /dev/null +++ b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/DateHeader.cs @@ -0,0 +1,73 @@ +// ------------------------------------------------------------------------------ +// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 +// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 +// CSDN博客:https://blog.csdn.net/qq_40374647 +// 哔哩哔哩视频:https://space.bilibili.com/94253567 +// Gitee源代码仓库:https://gitee.com/RRQM_Home +// Github源代码仓库:https://github.com/RRQM +// API首页:https://touchsocket.net/ +// 交流QQ群:234762506 +// 感谢您的下载和使用 +// ------------------------------------------------------------------------------ + +using System.Buffers.Text; +using System.Diagnostics; +using TouchSocket.Core; +using TouchSocket.Sockets; + +namespace TouchSocketHttpPlatform; + +internal static class DateHeader +{ + private const int dateTimeRLength = 29; + private const int prefixLength = 6; // "Date: ".Length is 6 in bytes for ASCII + private const int suffixIndex = dateTimeRLength + prefixLength; + + // Wed, 14 Mar 2018 14:20:00 GMT + private const int suffixLength = 2; // crlf + private static readonly Timer s_timer = new((s) => + { + SetDateValues(DateTimeOffset.UtcNow); + }, null, 1000, 1000); + + private static byte[] s_headerBytesMaster = new byte[prefixLength + dateTimeRLength + 2 * suffixLength]; + private static byte[] s_headerBytesScratch = new byte[prefixLength + dateTimeRLength + 2 * suffixLength]; + + static DateHeader() + { + var utf8 = "Date: "u8; + + utf8.CopyTo(s_headerBytesMaster); + utf8.CopyTo(s_headerBytesScratch); + s_headerBytesMaster[suffixIndex] = (byte)'\r'; + s_headerBytesMaster[suffixIndex + 1] = (byte)'\n'; + s_headerBytesMaster[suffixIndex + 2] = (byte)'\r'; + s_headerBytesMaster[suffixIndex + 3] = (byte)'\n'; + s_headerBytesScratch[suffixIndex] = (byte)'\r'; + s_headerBytesScratch[suffixIndex + 1] = (byte)'\n'; + s_headerBytesScratch[suffixIndex + 2] = (byte)'\r'; + s_headerBytesScratch[suffixIndex + 3] = (byte)'\n'; + + SetDateValues(DateTimeOffset.UtcNow); + SyncDateTimer(); + } + + public static ReadOnlySpan HeaderBytes => s_headerBytesMaster; + + public static void SyncDateTimer() + { + s_timer.Change(1000, 1000); + } + private static void SetDateValues(DateTimeOffset value) + { + lock (s_headerBytesScratch) + { + if (!Utf8Formatter.TryFormat(value, s_headerBytesScratch.AsSpan(prefixLength), out var written, 'R')) + { + throw new Exception("date time format failed"); + } + Debug.Assert(written == dateTimeRLength); + (s_headerBytesScratch, s_headerBytesMaster) = (s_headerBytesMaster, s_headerBytesScratch); + } + } +} diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/MyServer.cs b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/MyServer.cs new file mode 100644 index 00000000000..714b8ff367b --- /dev/null +++ b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/MyServer.cs @@ -0,0 +1,24 @@ +// ------------------------------------------------------------------------------ +// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 +// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 +// CSDN博客:https://blog.csdn.net/qq_40374647 +// 哔哩哔哩视频:https://space.bilibili.com/94253567 +// Gitee源代码仓库:https://gitee.com/RRQM_Home +// Github源代码仓库:https://github.com/RRQM +// API首页:https://touchsocket.net/ +// 交流QQ群:234762506 +// 感谢您的下载和使用 +// ------------------------------------------------------------------------------ + +using TouchSocket.Sockets; + +namespace TouchSocketHttpPlatform; + +internal sealed class MyServer : TcpService +{ + /// + protected override MyTcpSessionClientBase NewClient() + { + return new MyTcpSessionClientBase(); + } +} diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/MyTcpSessionClientBase.cs b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/MyTcpSessionClientBase.cs new file mode 100644 index 00000000000..788205e483c --- /dev/null +++ b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/MyTcpSessionClientBase.cs @@ -0,0 +1,266 @@ +// ------------------------------------------------------------------------------ +// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 +// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 +// CSDN博客:https://blog.csdn.net/qq_40374647 +// 哔哩哔哩视频:https://space.bilibili.com/94253567 +// Gitee源代码仓库:https://gitee.com/RRQM_Home +// Github源代码仓库:https://github.com/RRQM +// API首页:https://touchsocket.net/ +// 交流QQ群:234762506 +// 感谢您的下载和使用 +// ------------------------------------------------------------------------------ + +using System.Buffers; +using System.IO.Pipelines; +using System.Runtime.CompilerServices; +using TouchSocket.Sockets; + +namespace TouchSocketHttpPlatform; + +/// +/// 路由类型 +/// +internal enum RouteType +{ + /// + /// 未知路由 + /// + Unknown, + + /// + /// 纯文本路由 + /// + Plaintext, + + /// + /// JSON路由 + /// + Json +} + +internal sealed class MyTcpSessionClientBase : TcpSessionClient +{ + #region Paths + private static ReadOnlySpan Json => "/json"u8; + private static ReadOnlySpan Plaintext => "/plaintext"u8; + #endregion + + private static ReadOnlySpan PlainTextBody => "Hello, World!"u8; + private static ReadOnlySpan JsonBody => "{\"message\":\"Hello, World!\"}"u8; + + private static ReadOnlySpan PlaintextPreamble => + "HTTP/1.1 200 OK\r\n"u8 + + "Server: T\r\n"u8 + + "Content-Type: text/plain\r\n"u8 + + "Content-Length: 13\r\n"u8; + + private static ReadOnlySpan JsonPreamble => + "HTTP/1.1 200 OK\r\n"u8 + + "Server: T\r\n"u8 + + "Content-Type: application/json\r\n"u8 + + "Content-Length: 27\r\n"u8; + + protected override async Task ReceiveLoopAsync(ITransport transport) + { + var pipeReader = transport.Reader; + var pipeWriter = transport.Writer; + + while (true) + { + ValueTask readTask = pipeReader.ReadAsync(); + ReadResult readResult; + + if (readTask.IsCompleted) + { + readResult = readTask.Result; + } + else + { + readResult = await readTask.ConfigureAwait(false); + } + + var bufferSequence = readResult.Buffer; + + var totalConsumed = ProcessRequests(bufferSequence, pipeWriter, out var responseCount); + + if (responseCount > 0) + { + ValueTask flushTask = pipeWriter.FlushAsync(); + + if (!flushTask.IsCompleted) + { + await flushTask.ConfigureAwait(false); + } + } + + if (totalConsumed > 0) + { + pipeReader.AdvanceTo(bufferSequence.GetPosition(totalConsumed)); + } + else + { + pipeReader.AdvanceTo(bufferSequence.Start, bufferSequence.End); + } + + if (readResult.IsCompleted) + { + break; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + private static long ProcessRequests(ReadOnlySequence buffer, PipeWriter writer, out int responseCount) + { + var seqReader = new SequenceReader(buffer); + var totalConsumed = 0L; + responseCount = 0; + + while (!seqReader.End) + { + var startConsumed = seqReader.Consumed; + + if (!TryReadLine(ref seqReader, out var requestLineLength)) + { + break; + } + + var requestLineConsumed = requestLineLength + 2; + + var headersStartConsumed = seqReader.Consumed; + bool headersComplete = false; + + while (!seqReader.End) + { + if (!TryReadLine(ref seqReader, out var headerLength)) + { + var rewind = seqReader.Consumed - headersStartConsumed; + if (rewind > 0) + { + seqReader.Rewind(rewind); + } + headersComplete = false; + break; + } + + if (headerLength == 0) + { + headersComplete = true; + break; + } + } + + if (!headersComplete) + { + break; + } + + var routeType = ParseUrlFast(buffer.Slice(startConsumed), requestLineConsumed); + + var consumed = seqReader.Consumed - startConsumed; + totalConsumed += consumed; + + WriteResponseSync(writer, routeType); + responseCount++; + } + + return totalConsumed; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + private static void WriteResponseSync(PipeWriter writer, RouteType routeType) + { + if (routeType == RouteType.Plaintext) + { + writer.Write(PlaintextPreamble); + writer.Write(DateHeader.HeaderBytes); + writer.Write(PlainTextBody); + } + else if (routeType == RouteType.Json) + { + writer.Write(JsonPreamble); + writer.Write(DateHeader.HeaderBytes); + writer.Write(JsonBody); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + private static bool TryReadLine(ref SequenceReader reader, out long length) + { + if (reader.TryAdvanceTo((byte)'\r', advancePastDelimiter: false)) + { + var start = reader.Consumed; + + if (!reader.TryPeek(1, out var next)) + { + length = 0; + return false; + } + + if (next == '\n') + { + var lineLength = reader.Consumed; + reader.Advance(2); + length = lineLength - start; + return true; + } + + reader.Advance(1); + return TryReadLine(ref reader, out length); + } + + length = 0; + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + private static RouteType ParseUrlFast(ReadOnlySequence sequence, long requestLineLength) + { + var reader = new SequenceReader(sequence); + + if (!reader.TryAdvanceTo((byte)' ', advancePastDelimiter: true)) + { + return RouteType.Unknown; + } + + var urlStart = reader.Consumed; + + if (!reader.TryAdvanceTo((byte)' ', advancePastDelimiter: false)) + { + return RouteType.Unknown; + } + + var urlLength = reader.Consumed - urlStart; + + if (urlLength == Plaintext.Length) + { + var urlSlice = sequence.Slice(urlStart, urlLength); + + if (urlSlice.IsSingleSegment) + { + return urlSlice.FirstSpan.SequenceEqual(Plaintext) ? RouteType.Plaintext : RouteType.Unknown; + } + + Span tmp = stackalloc byte[(int)urlLength]; + urlSlice.CopyTo(tmp); + return tmp.SequenceEqual(Plaintext) ? RouteType.Plaintext : RouteType.Unknown; + } + + if (urlLength == Json.Length) + { + var urlSlice = sequence.Slice(urlStart, urlLength); + + if (urlSlice.IsSingleSegment) + { + return urlSlice.FirstSpan.SequenceEqual(Json) ? RouteType.Json : RouteType.Unknown; + } + + Span tmp = stackalloc byte[(int)urlLength]; + urlSlice.CopyTo(tmp); + return tmp.SequenceEqual(Json) ? RouteType.Json : RouteType.Unknown; + } + + return RouteType.Unknown; + } +} + diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/NuGet.Config b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/NuGet.Config new file mode 100644 index 00000000000..f05d5867888 --- /dev/null +++ b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/NuGet.Config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/Program.cs b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/Program.cs new file mode 100644 index 00000000000..7957bcd8c22 --- /dev/null +++ b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/Program.cs @@ -0,0 +1,63 @@ +// ------------------------------------------------------------------------------ +// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 +// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 +// CSDN博客:https://blog.csdn.net/qq_40374647 +// 哔哩哔哩视频:https://space.bilibili.com/94253567 +// Gitee源代码仓库:https://gitee.com/RRQM_Home +// Github源代码仓库:https://github.com/RRQM +// API首页:https://touchsocket.net/ +// 交流QQ群:234762506 +// 感谢您的下载和使用 +// ------------------------------------------------------------------------------ + +using System.Buffers; +using System.IO.Pipelines; +using TouchSocket.Core; +using TouchSocket.Sockets; + +namespace TouchSocketHttpPlatform; + +internal class Program +{ + private static async Task Main(string[] args) + { + MyServer server = new MyServer(); + await server.SetupAsync(new TouchSocketConfig() + .SetListenIPHosts(8080) + .SetMaxCount(1000000) + .SetTransportOption(options => + { + options.BufferOnDemand = false; + + options.ReceivePipeOptions = new PipeOptions( + pool: MemoryPool.Shared, + readerScheduler: PipeScheduler.ThreadPool, + writerScheduler: PipeScheduler.ThreadPool, + pauseWriterThreshold: 1024 * 1024, + resumeWriterThreshold: 1024 * 512, + minimumSegmentSize: -1, + useSynchronizationContext: false); + + options.SendPipeOptions = new PipeOptions( + pool: MemoryPool.Shared, + readerScheduler: PipeScheduler.ThreadPool, + writerScheduler: PipeScheduler.ThreadPool, + pauseWriterThreshold: 64 * 1024, + resumeWriterThreshold: 32 * 1024, + minimumSegmentSize: -1, + useSynchronizationContext: false); + }) + .ConfigureContainer(a => + { + a.AddConsoleLogger(); + })); + + await server.StartAsync(); + Console.WriteLine("HTTP服务器已启动,端口: 8080"); + + while (true) + { + Console.ReadLine(); + } + } +} diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/TouchSocketHttpPlatform.csproj b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/TouchSocketHttpPlatform.csproj new file mode 100644 index 00000000000..25feeea4984 --- /dev/null +++ b/frameworks/CSharp/touchsocket/src/TouchSocketHttpPlatform/TouchSocketHttpPlatform.csproj @@ -0,0 +1,13 @@ + + + + Exe + net10.0 + enable + enable + + + + + + diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketWebApi/Program.cs b/frameworks/CSharp/touchsocket/src/TouchSocketWebApi/Program.cs index 26cdfb935fd..1dc198dc165 100644 --- a/frameworks/CSharp/touchsocket/src/TouchSocketWebApi/Program.cs +++ b/frameworks/CSharp/touchsocket/src/TouchSocketWebApi/Program.cs @@ -1,9 +1,10 @@ +using System.Buffers; +using System.IO.Pipelines; using System.Text; using System.Text.Json.Serialization; using TouchSocket.Core; using TouchSocket.Http; using TouchSocket.Rpc; -using TouchSocket.Sockets; using TouchSocket.WebApi; using HttpContent = TouchSocket.Http.HttpContent; @@ -19,6 +20,28 @@ public static void Main(string[] args) { config.SetListenIPHosts(8080) .SetMaxCount(1000000) + .SetTransportOption(options => + { + options.BufferOnDemand = false; + + options.ReceivePipeOptions = new PipeOptions( + pool: MemoryPool.Shared, + readerScheduler: PipeScheduler.ThreadPool, + writerScheduler: PipeScheduler.ThreadPool, + pauseWriterThreshold: 1024 * 1024, + resumeWriterThreshold: 1024 * 512, + minimumSegmentSize: -1, + useSynchronizationContext: false); + + options.SendPipeOptions = new PipeOptions( + pool: MemoryPool.Shared, + readerScheduler: PipeScheduler.ThreadPool, + writerScheduler: PipeScheduler.ThreadPool, + pauseWriterThreshold: 64 * 1024, + resumeWriterThreshold: 32 * 1024, + minimumSegmentSize: -1, + useSynchronizationContext: false); + }) .ConfigureContainer(a => { a.AddConsoleLogger(); @@ -45,7 +68,7 @@ public static void Main(string[] args) }); }); - var host = builder.Build(); + IHost host = builder.Build(); host.Run(); } } @@ -60,7 +83,7 @@ public partial class ApiServer : SingletonRpcServer [WebApi(Method = HttpMethodType.Get)] public async Task Plaintext(IWebApiCallContext callContext) { - var response = callContext.HttpContext.Response; + HttpResponse response = callContext.HttpContext.Response; response.SetStatus(200, "ok"); response.Content = m_contentPlaintext; await response.AnswerAsync().ConfigureAwait(false); diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketWebApi/TouchSocketWebApi.csproj b/frameworks/CSharp/touchsocket/src/TouchSocketWebApi/TouchSocketWebApi.csproj index 1319cf14650..3b3d56852ce 100644 --- a/frameworks/CSharp/touchsocket/src/TouchSocketWebApi/TouchSocketWebApi.csproj +++ b/frameworks/CSharp/touchsocket/src/TouchSocketWebApi/TouchSocketWebApi.csproj @@ -1,16 +1,15 @@ - net9.0 + net10.0 enable enable - true dotnet-WorkerService1-19b37b17-6043-4334-ad9a-9e0e3c670da3 - - - + + + diff --git a/frameworks/CSharp/touchsocket/src/TouchSocketWebApi31/TouchSocketWebApi31.csproj b/frameworks/CSharp/touchsocket/src/TouchSocketWebApi31/TouchSocketWebApi31.csproj index d385bc8caed..3dafc4791f5 100644 --- a/frameworks/CSharp/touchsocket/src/TouchSocketWebApi31/TouchSocketWebApi31.csproj +++ b/frameworks/CSharp/touchsocket/src/TouchSocketWebApi31/TouchSocketWebApi31.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable true @@ -11,7 +11,7 @@ - + diff --git a/frameworks/CSharp/touchsocket/touchsocket-http.dockerfile b/frameworks/CSharp/touchsocket/touchsocket-http.dockerfile index 28def83f5e4..037e5d84bec 100644 --- a/frameworks/CSharp/touchsocket/touchsocket-http.dockerfile +++ b/frameworks/CSharp/touchsocket/touchsocket-http.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/TouchSocketHttp . RUN dotnet publish -c Release -o out -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime WORKDIR /app COPY --from=build /app/out ./ diff --git a/frameworks/CSharp/touchsocket/touchsocket-http31.dockerfile b/frameworks/CSharp/touchsocket/touchsocket-http31.dockerfile index b7437e1068b..1b84cee0dab 100644 --- a/frameworks/CSharp/touchsocket/touchsocket-http31.dockerfile +++ b/frameworks/CSharp/touchsocket/touchsocket-http31.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/TouchSocketHttp31 . RUN dotnet publish -c Release -o out -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime WORKDIR /app COPY --from=build /app/out ./ diff --git a/frameworks/CSharp/touchsocket/touchsocket-httpplatform.dockerfile b/frameworks/CSharp/touchsocket/touchsocket-httpplatform.dockerfile new file mode 100644 index 00000000000..0f30ba9b1b6 --- /dev/null +++ b/frameworks/CSharp/touchsocket/touchsocket-httpplatform.dockerfile @@ -0,0 +1,13 @@ +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /app +COPY src/TouchSocketHttpPlatform . +RUN dotnet publish -c Release -o out + +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime + +WORKDIR /app +COPY --from=build /app/out ./ + +EXPOSE 8080 + +ENTRYPOINT ["dotnet", "TouchSocketHttpPlatform.dll"] diff --git a/frameworks/CSharp/touchsocket/touchsocket-webapi31.dockerfile b/frameworks/CSharp/touchsocket/touchsocket-webapi31.dockerfile index 0d528dbfb91..9c6ec904cca 100644 --- a/frameworks/CSharp/touchsocket/touchsocket-webapi31.dockerfile +++ b/frameworks/CSharp/touchsocket/touchsocket-webapi31.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/TouchSocketWebApi31 . RUN dotnet publish -c Release -o out -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime WORKDIR /app COPY --from=build /app/out ./ diff --git a/frameworks/CSharp/touchsocket/touchsocket.dockerfile b/frameworks/CSharp/touchsocket/touchsocket.dockerfile index 96f1a166854..aacbf99557c 100644 --- a/frameworks/CSharp/touchsocket/touchsocket.dockerfile +++ b/frameworks/CSharp/touchsocket/touchsocket.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/TouchSocketWebApi . RUN dotnet publish -c Release -o out -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime WORKDIR /app COPY --from=build /app/out ./ diff --git a/frameworks/CSharp/wiredio/UnhGHttp/Program.cs b/frameworks/CSharp/wiredio/UnhGHttp/Program.cs new file mode 100644 index 00000000000..03d8a523ff3 --- /dev/null +++ b/frameworks/CSharp/wiredio/UnhGHttp/Program.cs @@ -0,0 +1,40 @@ +using System.Text.Json; +using GenHTTP.Api.Protocol; +using GenHTTP.Modules.IO; +using GenHTTP.Modules.Layouting; +using GenHTTP.Modules.Layouting.Provider; +using Unhinged; +using Unhinged.GenHttp.Experimental; + +internal class Program +{ + public static void Main(string[] args) + { + var builder = UnhingedEngine + .CreateBuilder() + .SetNWorkersSolver(() => Environment.ProcessorCount) + .SetBacklog(16384) + .SetMaxEventsPerWake(512) + .SetMaxNumberConnectionsPerWorker(512) + .SetPort(8080) + .SetSlabSizes(32 * 1024, 16 * 1024) + .Map(CreateLayoutBuilder()); + + var engine = builder.Build(); + engine.Run(); + } + + private static LayoutBuilder CreateLayoutBuilder() => + Layout + .Create() + .Add("/plaintext", Content.From(Resource.FromString("Hello, World!"))) + + .Add("/json", Content.From( + Resource.FromString(JsonSerializer.Serialize(new JsonMessage { message = "Hello, World!" })) + .Type(new FlexibleContentType("application/json")))); +} + +public class JsonMessage +{ + public string message { get; set; } +} \ No newline at end of file diff --git a/frameworks/CSharp/wiredio/UnhGHttp/UnhGHttp.csproj b/frameworks/CSharp/wiredio/UnhGHttp/UnhGHttp.csproj new file mode 100644 index 00000000000..09308ff4747 --- /dev/null +++ b/frameworks/CSharp/wiredio/UnhGHttp/UnhGHttp.csproj @@ -0,0 +1,23 @@ + + + + Exe + net9.0 + enable + enable + + true + true + true + true + + linux-musl-x64 + + + + + + + + + diff --git a/frameworks/CSharp/wiredio/benchmark_config.json b/frameworks/CSharp/wiredio/benchmark_config.json index e74c7696415..2d9ebf4896f 100644 --- a/frameworks/CSharp/wiredio/benchmark_config.json +++ b/frameworks/CSharp/wiredio/benchmark_config.json @@ -20,12 +20,12 @@ "display_name": "Wired.IO", "notes": "Only plaintext and JSON benchmarks implemented yet" }, - "plt": { + "mcr": { "plaintext_url": "/plaintext", "json_url": "/json", "port": 8080, "approach": "Realistic", - "classification": "Platform", + "classification": "Micro", "database": "None", "framework": "Unhinged", "language": "C#", @@ -34,8 +34,42 @@ "webserver": "Unhinged", "os": "Linux", "database_os": "Linux", - "display_name": "Wired.IO [Unhinged]", - "notes": "Not a framework" + "display_name": "Unhinged", + "notes": "epoll" + }, + "mcr-p": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "None", + "framework": "Unhinged", + "language": "C#", + "orm": "None", + "platform": ".NET", + "webserver": "Unhinged", + "os": "Linux", + "database_os": "Linux", + "display_name": "Unhinged [p]", + "notes": "epoll" + }, + "gen": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "None", + "framework": "GenHttp", + "language": "C#", + "orm": "None", + "platform": ".NET", + "webserver": "Unhinged", + "os": "Linux", + "database_os": "Linux", + "display_name": "genhttp [Unhinged]", + "notes": "Adapter" } } ] diff --git a/frameworks/CSharp/wiredio/config.toml b/frameworks/CSharp/wiredio/config.toml index fe292c91330..0b973f1f1fb 100644 --- a/frameworks/CSharp/wiredio/config.toml +++ b/frameworks/CSharp/wiredio/config.toml @@ -13,11 +13,35 @@ platform = ".NET" webserver = "Wired.IO" versus = "None" -[plt] +[mcr] urls.plaintext = "/plaintext" urls.json = "/json" approach = "Realistic" -classification = "Platform" +classification = "Micro" +os = "Linux" +database_os = "Linux" +orm = "None" +platform = ".NET" +webserver = "Unhinged" +versus = "None" + +[mcr-p] +urls.plaintext = "/plaintext" +urls.json = "/json" +approach = "Realistic" +classification = "Micro" +os = "Linux" +database_os = "Linux" +orm = "None" +platform = ".NET" +webserver = "Unhinged" +versus = "None" + +[gen] +urls.plaintext = "/plaintext" +urls.json = "/json" +approach = "Realistic" +classification = "Fullstack" os = "Linux" database_os = "Linux" orm = "None" diff --git a/frameworks/CSharp/wiredio/src/Platform/Platform.csproj b/frameworks/CSharp/wiredio/src/Platform/Platform.csproj index f560113a9f5..ea26e67a376 100644 --- a/frameworks/CSharp/wiredio/src/Platform/Platform.csproj +++ b/frameworks/CSharp/wiredio/src/Platform/Platform.csproj @@ -20,6 +20,6 @@ - + diff --git a/frameworks/CSharp/wiredio/src/Platform/Program.cs b/frameworks/CSharp/wiredio/src/Platform/Program.cs index a572a456ae9..cd8793de431 100644 --- a/frameworks/CSharp/wiredio/src/Platform/Program.cs +++ b/frameworks/CSharp/wiredio/src/Platform/Program.cs @@ -39,7 +39,7 @@ public static void Main(string[] args) // 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) + .SetNWorkersSolver(() => Environment.ProcessorCount - 2) // Accept up to 16384 connections .SetBacklog(16384) @@ -58,14 +58,19 @@ public static void Main(string[] args) engine.Run(); } - private static void RequestHandler(Connection connection) + private const string Json = "/json"; + private const string PlainText = "/plaintext"; + + private static ValueTask RequestHandler(Connection connection) { // FNV-1a Hashed routes to avoid string allocations - if(connection.HashedRoute == 291830056) // /json + if(connection.H1HeaderData.Route == Json) // /json CommitJsonResponse(connection); - else if (connection.HashedRoute == 3454831873) // /plaintext + else if (connection.H1HeaderData.Route == PlainText) // /plaintext CommitPlainTextResponse(connection); + + return ValueTask.CompletedTask; } [ThreadStatic] private static Utf8JsonWriter? t_utf8JsonWriter; diff --git a/frameworks/CSharp/wiredio/src/PlatformP/Platform.csproj b/frameworks/CSharp/wiredio/src/PlatformP/Platform.csproj new file mode 100644 index 00000000000..ea26e67a376 --- /dev/null +++ b/frameworks/CSharp/wiredio/src/PlatformP/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/PlatformP/Program.cs b/frameworks/CSharp/wiredio/src/PlatformP/Program.cs new file mode 100644 index 00000000000..46a7d69219c --- /dev/null +++ b/frameworks/CSharp/wiredio/src/PlatformP/Program.cs @@ -0,0 +1,98 @@ +// 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) + + .SetNWorkersSolver(() => Environment.ProcessorCount ) + + // 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 const string Json = "/json"; + private const string PlainText = "/plaintext"; + + private static ValueTask RequestHandler(Connection connection) + { + // FNV-1a Hashed routes to avoid string allocations + if(connection.H1HeaderData.Route == Json) // /json + CommitJsonResponse(connection); + + else if (connection.H1HeaderData.Route == PlainText) // /plaintext + CommitPlainTextResponse(connection); + + return ValueTask.CompletedTask; + } + + [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-gen.dockerfile b/frameworks/CSharp/wiredio/wiredio-gen.dockerfile new file mode 100644 index 00000000000..5436527f964 --- /dev/null +++ b/frameworks/CSharp/wiredio/wiredio-gen.dockerfile @@ -0,0 +1,24 @@ +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build +WORKDIR /source + +# copy csproj and restore as distinct layers +COPY UnhGHttp/*.csproj . +RUN dotnet restore -r linux-musl-x64 + +# copy and publish app and libraries +COPY UnhGHttp/ . +RUN dotnet publish -c release -o /app -r linux-musl-x64 --no-restore --self-contained + +# final stage/image +FROM mcr.microsoft.com/dotnet/runtime-deps:9.0-alpine + +ENV DOTNET_GCDynamicAdaptationMode=0 +ENV DOTNET_ReadyToRun=0 +ENV DOTNET_HillClimbing_Disable=1 + +WORKDIR /app +COPY --from=build /app . + +ENTRYPOINT ["./UnhGHttp"] + +EXPOSE 8080 diff --git a/frameworks/CSharp/wiredio/wiredio-mcr-p.dockerfile b/frameworks/CSharp/wiredio/wiredio-mcr-p.dockerfile new file mode 100644 index 00000000000..1ef18f083c2 --- /dev/null +++ b/frameworks/CSharp/wiredio/wiredio-mcr-p.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/PlatformP/ ./PlatformP/ +WORKDIR /src/PlatformP +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-plt.dockerfile b/frameworks/CSharp/wiredio/wiredio-mcr.dockerfile similarity index 100% rename from frameworks/CSharp/wiredio/wiredio-plt.dockerfile rename to frameworks/CSharp/wiredio/wiredio-mcr.dockerfile diff --git a/frameworks/Clojure/aleph/aleph.dockerfile b/frameworks/Clojure/aleph/aleph.dockerfile index e8268bd6b15..25f19f6bf0d 100644 --- a/frameworks/Clojure/aleph/aleph.dockerfile +++ b/frameworks/Clojure/aleph/aleph.dockerfile @@ -4,11 +4,11 @@ COPY src src COPY project.clj project.clj RUN lein uberjar -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /aleph COPY --from=lein /aleph/target/hello-aleph-standalone.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "--enable-native-access=ALL-UNNAMED", "-XX:+UseParallelGC", "-jar", "app.jar"] +CMD ["java", "-server", "--enable-native-access=ALL-UNNAMED", "-XX:+UseParallelGC", "-XX:MaxRAMPercentage=70", "-Dclojure.compiler.direct-linking=true","-jar", "app.jar"] diff --git a/frameworks/Clojure/aleph/src/hello/handler.clj b/frameworks/Clojure/aleph/src/hello/handler.clj index 758f5e8c98d..d7de60ebe49 100644 --- a/frameworks/Clojure/aleph/src/hello/handler.clj +++ b/frameworks/Clojure/aleph/src/hello/handler.clj @@ -19,7 +19,15 @@ (def jdbc-opts {:builder-fn rs/as-unqualified-maps}) (def db-spec - {:jdbcUrl "jdbc:postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass"}) + {:auto-commit false + :connection-timeout 1000 + :validation-timeout 1000 + :idle-timeout 15000 + :max-lifetime 60000 + :minimum-idle 0 + :maximum-pool-size 128 + :register-mbeans false + :jdbcUrl "jdbc:postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass"}) (def datasource (connection/->pool HikariDataSource db-spec)) @@ -62,7 +70,7 @@ jdbc-opts)) (defn- update-world - [{:keys [randomnumber id]}] + [{:keys [randomnumber id]}] (jdbc/execute-one! datasource ["update \"World\" set randomNumber = ? where id = ? returning *;" randomnumber id] jdbc-opts)) diff --git a/frameworks/Clojure/compojure/compojure-raw.dockerfile b/frameworks/Clojure/compojure/compojure-raw.dockerfile index 08aa20a839b..2a3a4758188 100644 --- a/frameworks/Clojure/compojure/compojure-raw.dockerfile +++ b/frameworks/Clojure/compojure/compojure-raw.dockerfile @@ -13,4 +13,4 @@ COPY resin.xml conf/resin.xml EXPOSE 8080 -CMD ["java", "-jar", "lib/resin.jar", "console"] +CMD ["java", "-XX:MaxRAMPercentage=70", "-Dclojure.compiler.direct-linking=true", "-jar", "lib/resin.jar", "console"] diff --git a/frameworks/Clojure/compojure/compojure.dockerfile b/frameworks/Clojure/compojure/compojure.dockerfile index 08aa20a839b..5205fcb18e6 100644 --- a/frameworks/Clojure/compojure/compojure.dockerfile +++ b/frameworks/Clojure/compojure/compojure.dockerfile @@ -13,4 +13,4 @@ COPY resin.xml conf/resin.xml EXPOSE 8080 -CMD ["java", "-jar", "lib/resin.jar", "console"] +CMD ["java", "-XX:MaxRAMPercentage=70", "-Dclojure.compiler.direct-linking=true","-jar", "lib/resin.jar", "console"] diff --git a/frameworks/Clojure/donkey/donkey.dockerfile b/frameworks/Clojure/donkey/donkey.dockerfile index cd7e6d18e57..5afe93e10c3 100644 --- a/frameworks/Clojure/donkey/donkey.dockerfile +++ b/frameworks/Clojure/donkey/donkey.dockerfile @@ -4,7 +4,7 @@ COPY src src COPY project.clj project.clj RUN lein uberjar -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 COPY --from=lein /donkey/target/hello-donkey-standalone.jar app.jar EXPOSE 8080 diff --git a/frameworks/Clojure/http-kit/http-kit-raw.dockerfile b/frameworks/Clojure/http-kit/http-kit-raw.dockerfile index d7e2dcbc93d..f0f00881f3f 100644 --- a/frameworks/Clojure/http-kit/http-kit-raw.dockerfile +++ b/frameworks/Clojure/http-kit/http-kit-raw.dockerfile @@ -7,4 +7,4 @@ RUN lein uberjar EXPOSE 8080 -CMD ["java", "-server", "-jar", "target/http-kit-standalone.jar"] +CMD ["java", "-server", "-Dclojure.compiler.direct-linking=true", "-jar", "target/http-kit-standalone.jar"] diff --git a/frameworks/Clojure/http-kit/http-kit.dockerfile b/frameworks/Clojure/http-kit/http-kit.dockerfile index d7e2dcbc93d..f0f00881f3f 100644 --- a/frameworks/Clojure/http-kit/http-kit.dockerfile +++ b/frameworks/Clojure/http-kit/http-kit.dockerfile @@ -7,4 +7,4 @@ RUN lein uberjar EXPOSE 8080 -CMD ["java", "-server", "-jar", "target/http-kit-standalone.jar"] +CMD ["java", "-server", "-Dclojure.compiler.direct-linking=true", "-jar", "target/http-kit-standalone.jar"] diff --git a/frameworks/Clojure/kit/benchmark_config.json b/frameworks/Clojure/kit/benchmark_config.json index bbde2d31918..21581010726 100755 --- a/frameworks/Clojure/kit/benchmark_config.json +++ b/frameworks/Clojure/kit/benchmark_config.json @@ -43,6 +43,24 @@ "display_name": "kit-majavat", "notes": "", "versus": "kit" + }, + "hiccup": { + "fortune_url": "/hiccup-fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "postgres", + "framework": "None", + "language": "Clojure", + "flavor": "None", + "orm": "Raw", + "platform": "None", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "kit-hiccup", + "notes": "", + "versus": "kit" } } ] diff --git a/frameworks/Clojure/kit/deps.edn b/frameworks/Clojure/kit/deps.edn index d517f976be1..9fc78535261 100644 --- a/frameworks/Clojure/kit/deps.edn +++ b/frameworks/Clojure/kit/deps.edn @@ -15,7 +15,8 @@ ;; HTML templating selmer/selmer {:mvn/version "1.12.62"} - org.clojars.jj/majavat {:mvn/version "1.12.3"} + org.clojars.jj/majavat {:mvn/version "1.13.0"} + hiccup/hiccup {:mvn/version "2.0.0"} ;; Database org.postgresql/postgresql {:mvn/version "42.7.8"} diff --git a/frameworks/Clojure/kit/kit-hiccup.dockerfile b/frameworks/Clojure/kit/kit-hiccup.dockerfile new file mode 100644 index 00000000000..01449abe9b0 --- /dev/null +++ b/frameworks/Clojure/kit/kit-hiccup.dockerfile @@ -0,0 +1,19 @@ +# syntax = docker/dockerfile:1.2 +FROM clojure:openjdk-17 AS build + +WORKDIR / +COPY . / + +RUN clj -Sforce -T:build all + +FROM amazoncorretto:25 + +COPY --from=build /target/te-bench-standalone.jar /te-bench/te-bench-standalone.jar + +EXPOSE 8080 + +ENV PORT=8080 +ENV JAVA_OPTS="-XX:+UseContainerSupport -Dfile.encoding=UTF-8 -XX:MaxRAMPercentage=70 -Dclojure.compiler.direct-linking=true" +ENV JDBC_URL="jdbc:postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass" + +ENTRYPOINT exec java $JAVA_OPTS -jar /te-bench/te-bench-standalone.jar diff --git a/frameworks/Clojure/kit/kit-majavat.dockerfile b/frameworks/Clojure/kit/kit-majavat.dockerfile index fbea7e95bd4..ab578f90cf7 100644 --- a/frameworks/Clojure/kit/kit-majavat.dockerfile +++ b/frameworks/Clojure/kit/kit-majavat.dockerfile @@ -6,14 +6,14 @@ COPY . / RUN clj -Sforce -T:build all -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 COPY --from=build /target/te-bench-standalone.jar /te-bench/te-bench-standalone.jar EXPOSE 8080 ENV PORT=8080 -ENV JAVA_OPTS="-XX:+UseContainerSupport -Dfile.encoding=UTF-8" +ENV JAVA_OPTS="-XX:+UseContainerSupport -Dfile.encoding=UTF-8 -XX:MaxRAMPercentage=70 -Dclojure.compiler.direct-linking=true" ENV JDBC_URL="jdbc:postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass" ENTRYPOINT exec java $JAVA_OPTS -jar /te-bench/te-bench-standalone.jar diff --git a/frameworks/Clojure/kit/kit.dockerfile b/frameworks/Clojure/kit/kit.dockerfile index fbea7e95bd4..ab578f90cf7 100644 --- a/frameworks/Clojure/kit/kit.dockerfile +++ b/frameworks/Clojure/kit/kit.dockerfile @@ -6,14 +6,14 @@ COPY . / RUN clj -Sforce -T:build all -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 COPY --from=build /target/te-bench-standalone.jar /te-bench/te-bench-standalone.jar EXPOSE 8080 ENV PORT=8080 -ENV JAVA_OPTS="-XX:+UseContainerSupport -Dfile.encoding=UTF-8" +ENV JAVA_OPTS="-XX:+UseContainerSupport -Dfile.encoding=UTF-8 -XX:MaxRAMPercentage=70 -Dclojure.compiler.direct-linking=true" ENV JDBC_URL="jdbc:postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass" ENTRYPOINT exec java $JAVA_OPTS -jar /te-bench/te-bench-standalone.jar diff --git a/frameworks/Clojure/kit/src/clj/io/github/kit_clj/te_bench/web/controllers/bench.clj b/frameworks/Clojure/kit/src/clj/io/github/kit_clj/te_bench/web/controllers/bench.clj index 2057a175140..c02f3621c49 100644 --- a/frameworks/Clojure/kit/src/clj/io/github/kit_clj/te_bench/web/controllers/bench.clj +++ b/frameworks/Clojure/kit/src/clj/io/github/kit_clj/te_bench/web/controllers/bench.clj @@ -5,6 +5,8 @@ [next.jdbc.result-set :as rs] [jj.majavat :as majavat] [jj.sql.boa :as boa] + [hiccup.page :as hp] + [hiccup.util :as hu] [jj.majavat.renderer :refer [->StringRenderer]] [jj.majavat.renderer.sanitizer :refer [->Html]] [ring.util.http-response :as http-response] @@ -20,6 +22,21 @@ (def ^:private render-fortune (majavat/build-renderer "html/fortunes.html" {:renderer (->StringRenderer {:sanitizer (->Html)})})) + +(defn render-hiccup-fortune [fortunes] + (hp/html5 + [:head + [:title "Fortunes"]] + [:body + [:table + [:tr + [:th "id"] + [:th "message"]] + (for [x fortunes] + [:tr + [:td (:id x)] + [:td (hu/escape-html (:message x))]])]])) + (def query-fortunes (boa/execute (boa/->NextJdbcAdapter) "sql/fortunes.sql")) (def selmer-opts {:custom-resource-path (clojure.java.io/resource "html")}) @@ -35,6 +52,10 @@ (http-response/ok) (http-response/content-type "text/html; charset=utf-8"))) +(defn hiccup-html-response + [body] + (-> (http-response/ok body) + (http-response/content-type "text/html; charset=utf-8"))) (defn rand-id [n] @@ -148,4 +169,12 @@ (as-> (query-fortunes db-conn) fortunes (conj fortunes {:id 0 :message "Additional fortune added at request time."}) (sort-by :message fortunes) - (majavat-html-response {:messages fortunes}))) \ No newline at end of file + (majavat-html-response {:messages fortunes}))) + +(defn hiccup-fortune-handler + [db-conn _request] + (as-> (query-fortunes db-conn) fortunes + (conj fortunes {:id 0 :message "Additional fortune added at request time."}) + (sort-by :message fortunes) + (render-hiccup-fortune fortunes) + (hiccup-html-response fortunes))) diff --git a/frameworks/Clojure/kit/src/clj/io/github/kit_clj/te_bench/web/routes/bench.clj b/frameworks/Clojure/kit/src/clj/io/github/kit_clj/te_bench/web/routes/bench.clj index 032ceb143f7..070fa899c17 100644 --- a/frameworks/Clojure/kit/src/clj/io/github/kit_clj/te_bench/web/routes/bench.clj +++ b/frameworks/Clojure/kit/src/clj/io/github/kit_clj/te_bench/web/routes/bench.clj @@ -18,7 +18,9 @@ ["/updates" {:get (partial bench/update-db-handler db-conn)}] ["/cached-queries" {:get (partial bench/cached-query-handler db-conn cache)}] ["/fortunes" {:get (partial bench/selmer-fortune-handler db-conn)}] - ["/majavat-fortunes" {:get (partial bench/majavat-fortune-handler db-conn)}]]) + ["/majavat-fortunes" {:get (partial bench/majavat-fortune-handler db-conn)}] + ["/hiccup-fortunes" {:get (partial bench/hiccup-fortune-handler db-conn)}] + ]) (defmethod ig/init-key :reitit.routes/bench [_ {:keys [base-path] diff --git a/frameworks/Clojure/luminus/luminus.dockerfile b/frameworks/Clojure/luminus/luminus.dockerfile index b5aa5430694..d57102d5b41 100644 --- a/frameworks/Clojure/luminus/luminus.dockerfile +++ b/frameworks/Clojure/luminus/luminus.dockerfile @@ -6,10 +6,10 @@ COPY resources resources COPY src src RUN lein uberjar -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /luminus COPY --from=lein /luminus/target/hello.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseParallelGC", "-jar", "app.jar"] +CMD ["java", "-server", "-XX:+UseParallelGC", "-XX:MaxRAMPercentage=70", "-Dclojure.compiler.direct-linking=true", "-jar", "app.jar"] diff --git a/frameworks/Clojure/pedestal/pedestal.dockerfile b/frameworks/Clojure/pedestal/pedestal.dockerfile index d0407c3c50c..fb3e7e23d34 100644 --- a/frameworks/Clojure/pedestal/pedestal.dockerfile +++ b/frameworks/Clojure/pedestal/pedestal.dockerfile @@ -8,4 +8,4 @@ RUN lein uberjar EXPOSE 8080 -CMD ["java", "-jar", "-Dio.pedestal.log.defaultMetricsRecorder=nil", "-Dio.pedestal.log.overrideLogger=nil", "target/pedestal-standalone.jar"] +CMD ["java", "-Dclojure.compiler.direct-linking=true", "-jar", "-Dio.pedestal.log.defaultMetricsRecorder=nil", "-Dio.pedestal.log.overrideLogger=nil", "target/pedestal-standalone.jar"] diff --git a/frameworks/Clojure/reitit/benchmark_config.json b/frameworks/Clojure/reitit/benchmark_config.json index 713c812c206..6f755e49966 100755 --- a/frameworks/Clojure/reitit/benchmark_config.json +++ b/frameworks/Clojure/reitit/benchmark_config.json @@ -39,6 +39,8 @@ "versus": "" }, "async": { + "json_url": "/json", + "plaintext_url": "/plaintext", "db_url": "/db", "port": 8080, "approach": "Realistic", @@ -54,7 +56,8 @@ "database_os": "Linux", "display_name": "reitit-async", "notes": "", - "versus": "undertow" + "versus": "undertow", + "tags": ["broken"] } }] } diff --git a/frameworks/Clojure/reitit/reitit-async.dockerfile b/frameworks/Clojure/reitit/reitit-async.dockerfile index e24189d9adb..2d07ee7f7b7 100644 --- a/frameworks/Clojure/reitit/reitit-async.dockerfile +++ b/frameworks/Clojure/reitit/reitit-async.dockerfile @@ -4,7 +4,7 @@ COPY project.clj project.clj COPY src src RUN lein uberjar -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /reitit COPY --from=lein /reitit/target/hello-reitit-standalone.jar app.jar diff --git a/frameworks/Clojure/reitit/reitit-jdbc.dockerfile b/frameworks/Clojure/reitit/reitit-jdbc.dockerfile index ab746e5c464..f58599d0ccb 100644 --- a/frameworks/Clojure/reitit/reitit-jdbc.dockerfile +++ b/frameworks/Clojure/reitit/reitit-jdbc.dockerfile @@ -4,10 +4,10 @@ COPY project.clj project.clj COPY src src RUN lein uberjar -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /reitit COPY --from=lein /reitit/target/hello-reitit-standalone.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseParallelGC", "-jar", "app.jar", "sync"] +CMD ["java", "-server", "-XX:+UseParallelGC", "-XX:MaxRAMPercentage=70", "-Dclojure.compiler.direct-linking=true", "-jar", "app.jar", "sync"] diff --git a/frameworks/Clojure/reitit/reitit.dockerfile b/frameworks/Clojure/reitit/reitit.dockerfile index 52fff78793a..da4069ba341 100644 --- a/frameworks/Clojure/reitit/reitit.dockerfile +++ b/frameworks/Clojure/reitit/reitit.dockerfile @@ -4,10 +4,10 @@ COPY project.clj project.clj COPY src src RUN lein uberjar -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /reitit COPY --from=lein /reitit/target/hello-reitit-standalone.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseParallelGC", "-jar", "app.jar"] +CMD ["java", "-server", "-XX:+UseParallelGC", "-XX:MaxRAMPercentage=70", "-Dclojure.compiler.direct-linking=true", "-jar", "app.jar"] diff --git a/frameworks/Clojure/reitit/src/hello/handler.clj b/frameworks/Clojure/reitit/src/hello/handler.clj index 7075cd4e5b6..97a8d8d1411 100644 --- a/frameworks/Clojure/reitit/src/hello/handler.clj +++ b/frameworks/Clojure/reitit/src/hello/handler.clj @@ -84,7 +84,7 @@ :else (constantly nil))] (-> (ring/ring-handler (ring/router - [["/plaintext" (exchange/constantly plain-text-handler)] + [["/plaintext" plain-text-handler] ["/json" json-handler] ["/db" db-handler]]) (ring/create-default-handler) diff --git a/frameworks/Clojure/ring-http-exchange/benchmark_config.json b/frameworks/Clojure/ring-http-exchange/benchmark_config.json index d8d2ba0ce3e..b0381b921ac 100755 --- a/frameworks/Clojure/ring-http-exchange/benchmark_config.json +++ b/frameworks/Clojure/ring-http-exchange/benchmark_config.json @@ -81,6 +81,26 @@ "display_name": "ring-http-exchange-robaho-graalvm", "notes": "", "versus": "ring-http-exchange-robaho" + }, + "robaho-semeru": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "fortune_url": "/fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "postgres", + "framework": "None", + "language": "Clojure", + "flavor": "None", + "orm": "Raw", + "platform": "None", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "ring-http-exchange-robaho-semeru", + "notes": "", + "versus": "ring-http-exchange-robaho" } } ] diff --git a/frameworks/Clojure/ring-http-exchange/project.clj b/frameworks/Clojure/ring-http-exchange/project.clj index 2f61228d669..e0734cff1a5 100644 --- a/frameworks/Clojure/ring-http-exchange/project.clj +++ b/frameworks/Clojure/ring-http-exchange/project.clj @@ -6,16 +6,15 @@ :dependencies [[org.clojure/clojure "1.12.3"] [org.clojure/tools.logging "1.3.0"] - [org.clojars.jj/ring-http-exchange "1.2.4"] + [org.clojars.jj/ring-http-exchange "1.2.9"] [seancorfield/next.jdbc "1.2.659"] - [org.clojars.jj/majavat "1.12.3"] + [org.clojars.jj/majavat "1.13.0"] [hikari-cp "3.3.0"] [org.clojars.jj/boa-sql "1.0.0"] - [io.netty/netty-transport-native-epoll "4.2.7.Final" :classifier "linux-x86_64"] [org.postgresql/postgresql "42.7.8"] [metosin/jsonista "0.3.13"] ] - :profiles {:robaho {:dependencies [[io.github.robaho/httpserver "1.0.28"]]}} + :profiles {:robaho {:dependencies [[io.github.robaho/httpserver "1.0.29"]]}} :resource-paths ["resources"] :main ring-http-exchange.benchmark) diff --git a/frameworks/Clojure/ring-http-exchange/ring-http-exchange-graalvm.dockerfile b/frameworks/Clojure/ring-http-exchange/ring-http-exchange-graalvm.dockerfile index 53a3998cd03..ad82982bcd9 100644 --- a/frameworks/Clojure/ring-http-exchange/ring-http-exchange-graalvm.dockerfile +++ b/frameworks/Clojure/ring-http-exchange/ring-http-exchange-graalvm.dockerfile @@ -11,4 +11,4 @@ COPY --from=lein /ring-http-exchange/target/ring-http-server-1.0.0-standalone.ja EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseParallelGC", "-jar", "app.jar"] +CMD ["java", "-server", "-XX:+UseZGC", "-XX:MaxRAMPercentage=70", "-Dclojure.compiler.direct-linking=true", "-jar", "app.jar"] diff --git a/frameworks/Clojure/ring-http-exchange/ring-http-exchange-robaho-graalvm.dockerfile b/frameworks/Clojure/ring-http-exchange/ring-http-exchange-robaho-graalvm.dockerfile index 8af31aebae0..151a6746e12 100644 --- a/frameworks/Clojure/ring-http-exchange/ring-http-exchange-robaho-graalvm.dockerfile +++ b/frameworks/Clojure/ring-http-exchange/ring-http-exchange-robaho-graalvm.dockerfile @@ -11,4 +11,4 @@ COPY --from=lein /ring-http-exchange/target/ring-http-server-1.0.0-standalone.ja EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseParallelGC", "-jar", "app.jar"] +CMD ["java", "-server", "-XX:+UseZGC", "-XX:MaxRAMPercentage=70", "-Dclojure.compiler.direct-linking=true", "-jar", "app.jar"] diff --git a/frameworks/Clojure/ring-http-exchange/ring-http-exchange-robaho-semeru.dockerfile b/frameworks/Clojure/ring-http-exchange/ring-http-exchange-robaho-semeru.dockerfile new file mode 100644 index 00000000000..bffbb459912 --- /dev/null +++ b/frameworks/Clojure/ring-http-exchange/ring-http-exchange-robaho-semeru.dockerfile @@ -0,0 +1,14 @@ +FROM clojure:lein as lein +WORKDIR /ring-http-exchange +COPY project.clj project.clj +COPY resources resources +COPY src src +RUN lein with-profile robaho uberjar + +FROM ibm-semeru-runtimes:open-25-jre-jammy +WORKDIR /ring-http-exchange +COPY --from=lein /ring-http-exchange/target/ring-http-server-1.0.0-standalone.jar app.jar + +EXPOSE 8080 + +CMD ["java", "-Xtune:throughput", "-Xgcpolicy:optthruput", "-XX:MaxRAMPercentage=70", "-XX:+UseContainerSupport", "-Dclojure.compiler.direct-linking=true", "-jar", "app.jar"] diff --git a/frameworks/Clojure/ring-http-exchange/ring-http-exchange-robaho.dockerfile b/frameworks/Clojure/ring-http-exchange/ring-http-exchange-robaho.dockerfile index e31848de2e6..095040b74d0 100644 --- a/frameworks/Clojure/ring-http-exchange/ring-http-exchange-robaho.dockerfile +++ b/frameworks/Clojure/ring-http-exchange/ring-http-exchange-robaho.dockerfile @@ -5,10 +5,10 @@ COPY resources resources COPY src src RUN lein with-profile robaho uberjar -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /ring-http-exchange COPY --from=lein /ring-http-exchange/target/ring-http-server-1.0.0-standalone.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseParallelGC", "-jar", "app.jar"] +CMD ["java", "-server", "-XX:+UseZGC", "-XX:MaxRAMPercentage=70", "-Dclojure.compiler.direct-linking=true", "-jar", "app.jar"] diff --git a/frameworks/Clojure/ring-http-exchange/ring-http-exchange.dockerfile b/frameworks/Clojure/ring-http-exchange/ring-http-exchange.dockerfile index b558aa938cf..f7b8946ab06 100644 --- a/frameworks/Clojure/ring-http-exchange/ring-http-exchange.dockerfile +++ b/frameworks/Clojure/ring-http-exchange/ring-http-exchange.dockerfile @@ -5,10 +5,10 @@ COPY resources resources COPY src src RUN lein uberjar -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /ring-http-exchange COPY --from=lein /ring-http-exchange/target/ring-http-server-1.0.0-standalone.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseParallelGC", "-jar", "app.jar"] +CMD ["java", "-server", "-XX:+UseZGC", "-XX:MaxRAMPercentage=70", "-Dclojure.compiler.direct-linking=true", "-jar", "app.jar"] diff --git a/frameworks/Clojure/ring-http-exchange/src/ring_http_exchange/benchmark.clj b/frameworks/Clojure/ring-http-exchange/src/ring_http_exchange/benchmark.clj index a5ee8a34384..6629b7c6a39 100644 --- a/frameworks/Clojure/ring-http-exchange/src/ring_http_exchange/benchmark.clj +++ b/frameworks/Clojure/ring-http-exchange/src/ring_http_exchange/benchmark.clj @@ -10,32 +10,33 @@ [ring-http-exchange.core :as server]) (:import (com.zaxxer.hikari HikariDataSource) - (io.netty.channel.epoll EpollEventLoopGroup))) + (java.util.concurrent Executors))) + +(defrecord Response [body status headers]) (def query-fortunes (boa/execute (boa/->NextJdbcAdapter) "fortune.sql")) -(def db-spec {:auto-commit true - :read-only false - :connection-timeout 30000 - :validation-timeout 5000 - :idle-timeout 600000 - :max-lifetime 1800000 - :minimum-idle 10 - :maximum-pool-size 520 - :minimum-pool-size 512 +(def db-spec {:auto-commit false + :connection-timeout 1000 + :validation-timeout 1000 + :idle-timeout 15000 + :max-lifetime 60000 + :minimum-idle 0 + :maximum-pool-size 128 :register-mbeans false - :jdbcUrl "jdbc:postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass"}) + :jdbcUrl "jdbc:postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass&prepareThreshold=1"} + ) +(def ^:private ^:const hello-world "Hello, World!") (def ^:private ^:const additional-message {:id 0 :message "Additional fortune added at request time."}) (def ^:private ^:const fortune-headers {"Server" "ring-http-exchange" "Content-Type" "text/html; charset=UTF-8"}) (def ^:private ^:const json-headers {"Server" "ring-http-exchange" "Content-Type" "application/json"}) -(def ^:private ^:const plaintext-response {:status 200 - :headers {"Server" "ring-http-exchange" - "Content-Type" "text/plain"} - :body "Hello, World!"}) +(def ^:private ^:const plain-text-headers {"Server" "ring-http-exchange" + "Content-Type" "text/plain"}) + (def ^:private render-fortune (majavat/build-renderer "fortune.html" {:renderer (->StringRenderer {:sanitizer (->Html)})})) @@ -53,14 +54,12 @@ (server/run-http-server (fn [req] (case (req :uri) - "/json" {:status 200 - :headers json-headers - :body (json/write-value-as-bytes {:message "Hello, World!"})} - "/fortunes" (let [body (get-body datasource)] - {:status 200 - :headers fortune-headers - :body body}) - plaintext-response)) - {:port 8080 - :host "0.0.0.0" - :executor (EpollEventLoopGroup.)}))) \ No newline at end of file + "/plaintext" (Response. hello-world 200 plain-text-headers) + "/json" (Response. (json/write-value-as-string {:message hello-world}) 200 json-headers) + "/fortunes" (let [body (get-body datasource)] (Response. body 200 fortune-headers)) + (Response. hello-world 200 {"Server" "ring-http-exchange" + "Content-Type" "text/plain"}))) + {:port 8080 + :host "0.0.0.0" + :record-support? true + :executor (Executors/newVirtualThreadPerTaskExecutor)}))) \ No newline at end of file diff --git a/frameworks/Crystal/crystal/crystal-radix.dockerfile b/frameworks/Crystal/crystal/crystal-radix.dockerfile index deda5e21148..fb3f1325da6 100644 --- a/frameworks/Crystal/crystal/crystal-radix.dockerfile +++ b/frameworks/Crystal/crystal/crystal-radix.dockerfile @@ -1,4 +1,4 @@ -FROM crystallang/crystal:1.12.1 +FROM crystallang/crystal:1.18.2 WORKDIR /crystal COPY shard.yml shard.yml diff --git a/frameworks/Crystal/crystal/crystal.dockerfile b/frameworks/Crystal/crystal/crystal.dockerfile index 678dd214cd4..a775fc07e66 100644 --- a/frameworks/Crystal/crystal/crystal.dockerfile +++ b/frameworks/Crystal/crystal/crystal.dockerfile @@ -1,4 +1,4 @@ -FROM crystallang/crystal:1.12.1 +FROM crystallang/crystal:1.18.2 WORKDIR /crystal COPY shard.yml shard.yml diff --git a/frameworks/Crystal/grip/grip.cr b/frameworks/Crystal/grip/grip.cr index 1b8a64b6667..6acd519566b 100644 --- a/frameworks/Crystal/grip/grip.cr +++ b/frameworks/Crystal/grip/grip.cr @@ -32,8 +32,10 @@ private def sanitized_query_count(request) queries.clamp(1..500) end -class Json < Grip::Controllers::Http - def get(context) +class JsonController + include Grip::Controllers::HTTP + + def get(context : Context) context .put_resp_header("Server", "Grip") .put_resp_header("Date", HTTP.format_time(Time.utc)) @@ -45,8 +47,10 @@ class Json < Grip::Controllers::Http end end -class Plaintext < Grip::Controllers::Http - def get(context) +class PlaintextController + include Grip::Controllers::HTTP + + def get(context : Context) context .put_resp_header("Server", "Grip") .put_resp_header("Date", HTTP.format_time(Time.utc)) @@ -56,8 +60,10 @@ class Plaintext < Grip::Controllers::Http end end -class Db < Grip::Controllers::Http - def get(context) +class DbController + include Grip::Controllers::HTTP + + def get(context : Context) context .put_resp_header("Server", "Grip") .put_resp_header("Date", HTTP.format_time(Time.utc)) @@ -67,8 +73,10 @@ class Db < Grip::Controllers::Http end end -class Queries < Grip::Controllers::Http - def get(context) +class QueriesController + include Grip::Controllers::HTTP + + def get(context : Context) results = (1..sanitized_query_count(context.request)).map do random_world end @@ -82,8 +90,10 @@ class Queries < Grip::Controllers::Http end end -class Updates < Grip::Controllers::Http - def get(context) +class UpdatesController + include Grip::Controllers::HTTP + + def get(context : Context) updated = (1..sanitized_query_count(context.request)).map do set_world({id: random_world[:id], randomNumber: rand(1..ID_MAXIMUM)}) end @@ -97,8 +107,10 @@ class Updates < Grip::Controllers::Http end end -class Fortunes < Grip::Controllers::Http - def get(context) +class FortunesController + include Grip::Controllers::HTTP + + def get(context : Context) data = fortunes additional_fortune = { id: 0, @@ -119,26 +131,23 @@ class Fortunes < Grip::Controllers::Http end end -class Application < Grip::Application - def initialize - super(environment: "production") - - get "/json", Json - get "/plaintext", Plaintext - get "/db", Db - get "/queries", Queries - get "/updates", Updates - get "/fortunes", Fortunes - end +class Application + include Grip::Application - def router : Array(HTTP::Handler) - [ - @http_handler, - ] of HTTP::Handler - end + property handlers : Array(HTTP::Handler) = [ + Grip::Handlers::HTTP.new + ] of HTTP::Handler - def server : HTTP::Server - HTTP::Server.new(@router) + property environment : String = + ENV["ENVIRONMENT"]? || "PRODUCTION" + + def initialize + get "/json", JsonController + get "/plaintext", PlaintextController + get "/db", DbController + get "/queries", QueriesController + get "/updates", UpdatesController + get "/fortunes", FortunesController end def reuse_port diff --git a/frameworks/Crystal/grip/grip.dockerfile b/frameworks/Crystal/grip/grip.dockerfile index 4d98926effb..a5e1efb3305 100644 --- a/frameworks/Crystal/grip/grip.dockerfile +++ b/frameworks/Crystal/grip/grip.dockerfile @@ -1,4 +1,4 @@ -FROM crystallang/crystal:1.12.1 +FROM crystallang/crystal:1.18.2 WORKDIR /grip COPY views views diff --git a/frameworks/Crystal/grip/shard.yml b/frameworks/Crystal/grip/shard.yml index ed1f5ab0a2e..41ac7355622 100644 --- a/frameworks/Crystal/grip/shard.yml +++ b/frameworks/Crystal/grip/shard.yml @@ -4,11 +4,11 @@ version: 0.2.0 dependencies: grip: github: grip-framework/grip - version: 3.0.0 + version: 4.0.0 pg: github: will/crystal-pg - version: 0.28.0 + version: 0.29.0 targets: grip: main: grip.cr diff --git a/frameworks/Crystal/lucky/lucky.dockerfile b/frameworks/Crystal/lucky/lucky.dockerfile index 1f352cf53bd..f2c38af3c71 100644 --- a/frameworks/Crystal/lucky/lucky.dockerfile +++ b/frameworks/Crystal/lucky/lucky.dockerfile @@ -1,4 +1,4 @@ -FROM crystallang/crystal:1.14.0 +FROM crystallang/crystal:1.18.2 WORKDIR /lucky COPY shard.lock shard.lock diff --git a/frameworks/Crystal/lucky/shard.lock b/frameworks/Crystal/lucky/shard.lock index 34f8bfcfea6..fe77e4ef539 100644 --- a/frameworks/Crystal/lucky/shard.lock +++ b/frameworks/Crystal/lucky/shard.lock @@ -6,7 +6,7 @@ shards: backtracer: git: https://github.com/sija/backtracer.cr.git - version: 1.2.2 + version: 1.2.4 cadmium_transliterator: git: https://github.com/cadmiumcr/transliterator.git diff --git a/frameworks/Crystal/onyx/README.md b/frameworks/Crystal/onyx/README.md deleted file mode 100755 index df04ff51c00..00000000000 --- a/frameworks/Crystal/onyx/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Crystal-Onyx - -This is the [Onyx](https://github.com/onyxframework/) test of the Framework Benchmarks. Crystal is a new language that closely resembles Ruby with a goal of removing typed variables and parameters (instead inferencing), whilst maintaining top speed through bindings into C. - -The framework consists of multiple components: - -[Onyx::HTTP](https://github.com/onyxframework/http) is a collection of HTTP handlers, which essentially are building blocks for your web application -[Onyx::REST](https://github.com/onyxframework/rest) is a REST layer on top of Onyx::HTTP which implements splitting business and rendering logic into Actions and Views, inspired by Hanami -[Onyx::SQL](https://github.com/onyxframework/rest) is a database-agnostic SQL ORM - -Onyx Framework is designed to be both powerful and adoptable by Crystal newcomers. It utilizes complex concepts like annotations and generics, but hides it under beautiful DSL. Such an approach makes it possible to write less code, thus reducing the possibility of bugs, but still make it easy to extend the framework’s functionality. diff --git a/frameworks/Crystal/onyx/config.toml b/frameworks/Crystal/onyx/config.toml deleted file mode 100644 index 8f7a33c7863..00000000000 --- a/frameworks/Crystal/onyx/config.toml +++ /dev/null @@ -1,18 +0,0 @@ -[framework] -name = "onyx" - -[main] -urls.plaintext = "/plaintext" -urls.json = "/json" -urls.db = "/db" -urls.query = "/queries?queries=" -urls.update = "/updates?queries=" -approach = "Realistic" -classification = "Fullstack" -database = "Postgres" -database_os = "Linux" -os = "Linux" -orm = "Full" -platform = "None" -webserver = "None" -versus = "None" diff --git a/frameworks/Crystal/onyx/onyx.dockerfile b/frameworks/Crystal/onyx/onyx.dockerfile deleted file mode 100644 index c861ec9e072..00000000000 --- a/frameworks/Crystal/onyx/onyx.dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM crystallang/crystal:0.27.2 - -WORKDIR /onyx -COPY run.sh run.sh -COPY src src -COPY shard.yml shard.yml - -ENV DATABASE_URL postgres://benchmarkdbuser:benchmarkdbpass@tfb-database:5432/hello_world?initial_pool_size=56&max_pool_size=56&max_idle_pool_size=56 -ENV TEST_HOST tfb-server -ENV CRYSTAL_ENV benchmarking - -RUN shards install -RUN crystal build --release --no-debug src/server_postgres.cr - -EXPOSE 8080 -CMD bash run.sh diff --git a/frameworks/Crystal/onyx/run.sh b/frameworks/Crystal/onyx/run.sh deleted file mode 100644 index f8f69e90674..00000000000 --- a/frameworks/Crystal/onyx/run.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -./server_postgres -p 8080 & - -wait diff --git a/frameworks/Crystal/onyx/shard.lock b/frameworks/Crystal/onyx/shard.lock deleted file mode 100644 index 952301ca654..00000000000 --- a/frameworks/Crystal/onyx/shard.lock +++ /dev/null @@ -1,50 +0,0 @@ -version: 1.0 -shards: - callbacks: - github: vladfaust/callbacks.cr - version: 0.2.0 - - db: - github: crystal-lang/crystal-db - version: 0.5.1 - - dotenv: - github: gdotdesign/cr-dotenv - version: 0.1.0 - - exception_page: - github: crystal-loot/exception_page - version: 0.1.2 - - http-params-serializable: - github: vladfaust/http-params-serializable - version: 0.3.0 - - kilt: - github: jeromegn/kilt - version: 0.4.0 - - onyx: - github: onyxframework/onyx - version: 0.3.1 - - onyx-http: - github: onyxframework/http - version: 0.7.1 - - onyx-sql: - github: onyxframework/sql - version: 0.7.1 - - pg: - github: will/crystal-pg - version: 0.15.0 - - radix: - github: luislavena/radix - version: 0.3.9 - - time_format: - github: vladfaust/time_format.cr - version: 0.1.1 - diff --git a/frameworks/Crystal/onyx/shard.yml b/frameworks/Crystal/onyx/shard.yml deleted file mode 100644 index 7f2f6d18bd3..00000000000 --- a/frameworks/Crystal/onyx/shard.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: onyx -version: 0.2.0 - -authors: - - Vlad Faust - - Carlos Donderis - -crystal: 0.27.2 - -license: MIT - -dependencies: - onyx: - github: onyxframework/onyx - version: ~> 0.3.0 - onyx-http: - github: onyxframework/http - version: ~> 0.7.0 - onyx-sql: - github: onyxframework/sql - version: ~> 0.7.0 - pg: - github: will/crystal-pg - version: ~> 0.15.0 diff --git a/frameworks/Crystal/onyx/src/endpoints/random_id.cr b/frameworks/Crystal/onyx/src/endpoints/random_id.cr deleted file mode 100644 index 51101ad470c..00000000000 --- a/frameworks/Crystal/onyx/src/endpoints/random_id.cr +++ /dev/null @@ -1,5 +0,0 @@ -module Endpoints::RandomID - def random_id - Random.rand(10_000).succ - end -end diff --git a/frameworks/Crystal/onyx/src/endpoints/worlds/many.cr b/frameworks/Crystal/onyx/src/endpoints/worlds/many.cr deleted file mode 100644 index 0904dcfc299..00000000000 --- a/frameworks/Crystal/onyx/src/endpoints/worlds/many.cr +++ /dev/null @@ -1,25 +0,0 @@ -struct Endpoints::Worlds::Many - include Onyx::HTTP::Endpoint - include RandomID - - QUERY = Models::World.where(id: 0).build(true)[0] - - params do - query do - type queries : String | Int32 = 1 - end - end - - def call - queries = params.query.queries.is_a?(String) ? 1 : params.query.queries.as(Int32) - - worlds = Array(Models::World).new - - queries.clamp(1..500).times.each do - world = Onyx.query(Models::World, QUERY, random_id).first - worlds << world - end - - return Views::Worlds.new(worlds) - end -end diff --git a/frameworks/Crystal/onyx/src/endpoints/worlds/random.cr b/frameworks/Crystal/onyx/src/endpoints/worlds/random.cr deleted file mode 100644 index e20ee671833..00000000000 --- a/frameworks/Crystal/onyx/src/endpoints/worlds/random.cr +++ /dev/null @@ -1,11 +0,0 @@ -struct Endpoints::Worlds::Random - include Onyx::HTTP::Endpoint - include RandomID - - QUERY = Models::World.where(id: 0).build(true)[0] - - def call - world = Onyx.query(Models::World, QUERY, random_id).first - return Views::World.new(world) - end -end diff --git a/frameworks/Crystal/onyx/src/endpoints/worlds/update.cr b/frameworks/Crystal/onyx/src/endpoints/worlds/update.cr deleted file mode 100644 index acf16a66267..00000000000 --- a/frameworks/Crystal/onyx/src/endpoints/worlds/update.cr +++ /dev/null @@ -1,28 +0,0 @@ -struct Endpoints::Worlds::Update - include Onyx::HTTP::Endpoint - include RandomID - - SELECT_QUERY = Models::World.where(id: 0).build(true)[0] - UPDATE_QUERY = Models::World.update.set(random_number: 0).where(id: 0).build[0] - - params do - query do - type queries : String | Int32 = 1 - end - end - - def call - queries = params.query.queries.is_a?(String) ? 1 : params.query.queries.as(Int32) - - worlds = Array(Models::World).new - - queries.clamp(1..500).times.each do - world = Onyx.query(Models::World, SELECT_QUERY, random_id).first - world.random_number = random_id - Onyx.exec(UPDATE_QUERY, world.random_number, world.id) - worlds << world - end - - return Views::Worlds.new(worlds) - end -end diff --git a/frameworks/Crystal/onyx/src/models/world.cr b/frameworks/Crystal/onyx/src/models/world.cr deleted file mode 100644 index a187eb97477..00000000000 --- a/frameworks/Crystal/onyx/src/models/world.cr +++ /dev/null @@ -1,8 +0,0 @@ -class Models::World - include Onyx::SQL::Model - - schema world do - pkey id : Int32 - type random_number : Int32, key: "randomnumber" - end -end diff --git a/frameworks/Crystal/onyx/src/server_postgres.cr b/frameworks/Crystal/onyx/src/server_postgres.cr deleted file mode 100644 index a0d51bb15f2..00000000000 --- a/frameworks/Crystal/onyx/src/server_postgres.cr +++ /dev/null @@ -1,37 +0,0 @@ -require "pg" -require "onyx/sql" -require "onyx/http" - -require "./models/*" -require "./views/*" -require "./endpoints/**" - -class CustomHandler - include HTTP::Handler - - def call(context) - context.response.headers["Server"] = "Onyx" - context.response.headers["Date"] = HTTP.format_time(Time.now) - call_next(context) - end -end - -Onyx.draw do - get "/json" do |env| - env.response.content_type = "application/json" - {message: "Hello, World!"}.to_json(env.response) - end - - get "/db", Endpoints::Worlds::Random - get "/queries", Endpoints::Worlds::Many - get "/updates", Endpoints::Worlds::Update - - get "/plaintext" do |env| - env.response.content_type = "text/plain" - env.response << "Hello, World!" - end -end - -Onyx.listen(ENV["TEST_HOST"], 8080) do - handlers.unshift(CustomHandler.new) -end diff --git a/frameworks/Crystal/onyx/src/views/world.cr b/frameworks/Crystal/onyx/src/views/world.cr deleted file mode 100644 index 06f8b989c9c..00000000000 --- a/frameworks/Crystal/onyx/src/views/world.cr +++ /dev/null @@ -1,13 +0,0 @@ -struct Views::World - include Onyx::HTTP::View - - def initialize(@world : Models::World) - end - - json do - object do - field "id", @world.id - field "randomnumber", @world.random_number - end - end -end diff --git a/frameworks/Crystal/onyx/src/views/worlds.cr b/frameworks/Crystal/onyx/src/views/worlds.cr deleted file mode 100644 index 64a02d282b3..00000000000 --- a/frameworks/Crystal/onyx/src/views/worlds.cr +++ /dev/null @@ -1,8 +0,0 @@ -struct Views::Worlds - include Onyx::HTTP::View - - def initialize(@worlds : Enumerable(Models::World)) - end - - json @worlds.map { |world| Views::World.new(world) } -end diff --git a/frameworks/Crystal/spider-gazelle/shard.lock b/frameworks/Crystal/spider-gazelle/shard.lock index a73d29d085c..bc26543af7e 100644 --- a/frameworks/Crystal/spider-gazelle/shard.lock +++ b/frameworks/Crystal/spider-gazelle/shard.lock @@ -2,7 +2,7 @@ version: 2.0 shards: action-controller: git: https://github.com/spider-gazelle/action-controller.git - version: 7.4.3 + version: 7.6.1 active-model: git: https://github.com/spider-gazelle/active-model.git @@ -10,7 +10,7 @@ shards: backtracer: git: https://github.com/sija/backtracer.cr.git - version: 1.2.2 + version: 1.2.4 db: git: https://github.com/crystal-lang/crystal-db.git @@ -18,7 +18,7 @@ shards: eventbus: git: https://github.com/spider-gazelle/eventbus.git - version: 1.0.0+git.commit.af63536d718348885a553dc4aa6debccc2946289 + version: 1.0.1+git.commit.a707ac06aba16ba6070ff4972acfd839f1f05e15 exception_page: git: https://github.com/crystal-loot/exception_page.git @@ -30,7 +30,7 @@ shards: hot_topic: git: https://github.com/jgaskins/hot_topic.git - version: 0.1.0+git.commit.3c901e77b6e000930398738260a2944b6f5785dc + version: 0.1.0+git.commit.4eafc046ed4d98bbab7a4534da57e163ea16b6c6 http-params-serializable: git: https://github.com/place-labs/http-params-serializable.git @@ -38,7 +38,7 @@ shards: json-schema: git: https://github.com/spider-gazelle/json-schema.git - version: 1.3.1 + version: 1.3.2 kilt: git: https://github.com/jeromegn/kilt.git @@ -46,21 +46,13 @@ shards: lucky_router: git: https://github.com/luckyframework/lucky_router.git - version: 0.6.0 + version: 0.6.1 pg: git: https://github.com/will/crystal-pg.git - version: 0.28.0 + version: 0.29.0 pg-orm: git: https://github.com/spider-gazelle/pg-orm.git - version: 1.1.2+git.commit.9b340ee269cd4a10ed6c5b51235cbaf45fc380e1 - - pool: - git: https://github.com/ysbaddaden/pool.git - version: 0.2.4 - - redis: - git: https://github.com/stefanwille/crystal-redis.git - version: 2.9.1 + version: 2.1.0 diff --git a/frameworks/Crystal/spider-gazelle/spider-gazelle.dockerfile b/frameworks/Crystal/spider-gazelle/spider-gazelle.dockerfile index c836b434c44..8f811eead03 100644 --- a/frameworks/Crystal/spider-gazelle/spider-gazelle.dockerfile +++ b/frameworks/Crystal/spider-gazelle/spider-gazelle.dockerfile @@ -1,4 +1,4 @@ -FROM crystallang/crystal:1.14.0 +FROM crystallang/crystal:1.18.2 WORKDIR /usr/src/app diff --git a/frameworks/Erlang/cowboy/benchmark_config.json b/frameworks/Erlang/cowboy/benchmark_config.json index 324b087d481..7c37a4a6864 100644 --- a/frameworks/Erlang/cowboy/benchmark_config.json +++ b/frameworks/Erlang/cowboy/benchmark_config.json @@ -20,6 +20,7 @@ "database_os": "Linux", "display_name": "Cowboy", "notes": "", + "tags": ["broken"], "versus": "" }}] } diff --git a/frameworks/Erlang/elli/benchmark_config.json b/frameworks/Erlang/elli/benchmark_config.json index 2910a94924c..ce58700f3e1 100644 --- a/frameworks/Erlang/elli/benchmark_config.json +++ b/frameworks/Erlang/elli/benchmark_config.json @@ -19,6 +19,7 @@ "database_os": "Linux", "display_name": "elli", "notes": "", + "tags": ["broken"], "versus": "" }}] } diff --git a/frameworks/Erlang/mochiweb/benchmark_config.json b/frameworks/Erlang/mochiweb/benchmark_config.json index 57f8dcbf8a8..e45bfbf83e7 100644 --- a/frameworks/Erlang/mochiweb/benchmark_config.json +++ b/frameworks/Erlang/mochiweb/benchmark_config.json @@ -21,6 +21,7 @@ "database_os": "Linux", "display_name": "mochiweb", "notes": "", + "tags": ["broken"], "versus": "" }}] } diff --git a/frameworks/FSharp/giraffe/benchmark_config.json b/frameworks/FSharp/giraffe/benchmark_config.json index 5552420b37f..cc2e70a748f 100644 --- a/frameworks/FSharp/giraffe/benchmark_config.json +++ b/frameworks/FSharp/giraffe/benchmark_config.json @@ -7,6 +7,7 @@ "json_url": "/json", "db_url": "/db", "query_url": "/queries?queries=", + "update_url": "/updates?queries=", "fortune_url": "/fortunes", "port": 8080, "approach": "Realistic", diff --git a/frameworks/FSharp/giraffe/config.toml b/frameworks/FSharp/giraffe/config.toml index a44ef83d919..ada171349cb 100644 --- a/frameworks/FSharp/giraffe/config.toml +++ b/frameworks/FSharp/giraffe/config.toml @@ -2,11 +2,12 @@ name = "giraffe" [main] -urls.plaintext = "/plaintext" urls.json = "/json" urls.db = "/db" urls.query = "/queries?queries=" urls.fortune = "/fortunes" +urls.update = "/updates?queries=" +urls.plaintext = "/plaintext" approach = "Realistic" classification = "fullstack" database = "Postgres" diff --git a/frameworks/FSharp/giraffe/src/App/App.fsproj b/frameworks/FSharp/giraffe/src/App/App.fsproj index 215f3bfc001..ef58a0c3618 100644 --- a/frameworks/FSharp/giraffe/src/App/App.fsproj +++ b/frameworks/FSharp/giraffe/src/App/App.fsproj @@ -7,10 +7,10 @@ - + diff --git a/frameworks/FSharp/giraffe/src/App/Program.fs b/frameworks/FSharp/giraffe/src/App/Program.fs index b4e63e7333f..f7d62db7d33 100644 --- a/frameworks/FSharp/giraffe/src/App/Program.fs +++ b/frameworks/FSharp/giraffe/src/App/Program.fs @@ -18,15 +18,15 @@ module Common = Database=hello_world; User Id=benchmarkdbuser; Password=benchmarkdbpass; - SSL Mode=Disable; Maximum Pool Size=1024; NoResetOnClose=true; Enlist=false; - Max Auto Prepare=4; - Multiplexing=true; - Write Coalescing Buffer Threshold Bytes=1000 + Max Auto Prepare=4 """ + [] + let MultiplexedConnectionString = ConnectionString + ";Multiplexing=true" + [] type JsonMode = | System @@ -46,8 +46,43 @@ module Common = member _.Next () = rnd.Next (min, max) - [] - let MaxDegreeOfParallelism = 3 + // Cache SQL strings for bulk updates to avoid rebuilding on every request + // This module generates and caches SQL UPDATE statements that use PostgreSQL's + // VALUES clause to update multiple rows in a single statement. + module BatchUpdateSql = + let private cache = Array.zeroCreate 501 + + let get (count: int) = + match cache.[count] with + | null -> + let lastIndex = count - 1 + + // Build the VALUES clause: (@Id_0, @Rn_0), (@Id_1, @Rn_1), ... + // Each pair represents (id, new_randomnumber) for one row + let valueClauses = + List.init lastIndex (fun i -> sprintf "(@Id_%d, @Rn_%d), " i i) + |> String.concat "" + + // The final SQL uses a CTE-like VALUES construct to update multiple rows: + // UPDATE world SET randomnumber = temp.randomnumber + // FROM (VALUES ...) AS temp(id, randomnumber) + // WHERE temp.id = world.id + let sql = + sprintf + """ + UPDATE world + SET randomnumber = temp.randomnumber + FROM (VALUES %s(@Id_%d, @Rn_%d) ORDER BY 1) + AS temp(id, randomnumber) + WHERE temp.id = world.id + """ + valueClauses + lastIndex + lastIndex + + cache.[count] <- sql + sql + | sql -> sql [] module HtmlViews = @@ -87,10 +122,12 @@ module HttpHandlers = message = "Additional fortune added at request time." } - let private fortunes: HttpHandler = + let fortunes: HttpHandler = fun _ ctx -> task { - use conn = new NpgsqlConnection (ConnectionString) + let dataSource = ctx.GetService () + use conn = dataSource.CreateConnection () + do! conn.OpenAsync () let! data = conn.QueryAsync ("SELECT id, message FROM fortune") @@ -106,11 +143,13 @@ module HttpHandlers = return! ctx.WriteBytesAsync bytes } - let private db: HttpHandler = + let db: HttpHandler = fun _ ctx -> task { let rnd = ctx.GetService () - use conn = new NpgsqlConnection (ConnectionString) + let dataSource = ctx.GetService () + use conn = dataSource.CreateConnection () + do! conn.OpenAsync () let! data = conn.QuerySingleAsync ( @@ -121,7 +160,7 @@ module HttpHandlers = return! ctx.WriteJsonAsync data } - let private queries: HttpHandler = + let queries: HttpHandler = fun _ ctx -> task { let queryParam = @@ -137,30 +176,94 @@ module HttpHandlers = |> Option.defaultValue 1 let rnd = ctx.GetService () + let dataSource = ctx.GetService () + + use conn = dataSource.CreateConnection () + do! conn.OpenAsync () - let! res = - Array.init queryParam (fun _ -> rnd.Next ()) - |> Array.map (fun id -> - use conn = new NpgsqlConnection (ConnectionString) + // Read all rows sequentially + let results = Array.zeroCreate queryParam + for i in 0 .. queryParam - 1 do + let! world = conn.QuerySingleAsync ( "SELECT id, randomnumber FROM world WHERE id = @Id", - {| Id = id |} + {| Id = rnd.Next () |} ) - |> Async.AwaitTask + + results.[i] <- world + + return! ctx.WriteJsonAsync results + } + + let updates: HttpHandler = + fun _ ctx -> + task { + let queryParam = + ctx.TryGetQueryStringValue "queries" + |> Option.map (fun value -> + match System.Int32.TryParse value with + | true, intValue -> + if intValue < 1 then 1 + elif intValue > 500 then 500 + else intValue + | false, _ -> 1 ) - |> fun computations -> - Async.Parallel (computations, MaxDegreeOfParallelism) + |> Option.defaultValue 1 + + let rnd = ctx.GetService () + + // Use multiplexed connection for updates (more efficient for sequential ops) + use conn = new NpgsqlConnection (MultiplexedConnectionString) + do! conn.OpenAsync () + + // Read all rows sequentially + let readResults = Array.zeroCreate queryParam - return! ctx.WriteJsonAsync res + for i in 0 .. queryParam - 1 do + let! world = + conn.QuerySingleAsync ( + "SELECT id, randomnumber FROM world WHERE id = @Id", + {| Id = rnd.Next () |} + ) + + readResults.[i] <- world + + // Update random numbers functionally + let updatedData = + readResults + |> Array.map (fun data -> { data with randomNumber = rnd.Next () }) + + // Build bulk update parameters functionally + // We use a single UPDATE statement with a VALUES clause to update all rows at once. + // + // Example SQL for 2 rows: + // UPDATE world SET randomnumber = temp.randomnumber + // FROM (VALUES (@Id_0, @Rn_0), (@Id_1, @Rn_1) ORDER BY 1) AS temp(id, randomnumber) + // WHERE temp.id = world.id + let updateParams = + updatedData + |> Array.mapi (fun i data -> [ + sprintf "@Id_%d" i, box data.id // Parameter for the id + sprintf "@Rn_%d" i, box data.randomNumber // Parameter for the new random number + ]) + |> Array.collect List.toArray // Flatten the list of parameter pairs + |> dict // Convert to dictionary for Dapper + + // Execute bulk update using Dapper + let sql = BatchUpdateSql.get queryParam + let! _ = conn.ExecuteAsync (sql, updateParams) + + return! ctx.WriteJsonAsync updatedData } let endpoints: Endpoint list = [ - route "/plaintext" (text "Hello, World!") route "/json" (json {| message = "Hello, World!" |}) route "/db" db route "/queries" queries route "/fortunes" fortunes + route "/updates" updates + route "/plaintext" (text "Hello, World!") ] @@ -173,6 +276,7 @@ module Main = open Microsoft.Extensions.Logging open System.Text.Json open Newtonsoft.Json + open Npgsql [] let main args = @@ -202,6 +306,7 @@ module Main = builder.Services .AddSingleton(jsonSerializer) .AddSingleton(rnd) + .AddSingleton(NpgsqlDataSource.Create (ConnectionString)) .AddGiraffe () |> ignore diff --git a/frameworks/FSharp/oxpecker/README.md b/frameworks/FSharp/oxpecker/README.md index a35cbf08522..6ac388b2d50 100644 --- a/frameworks/FSharp/oxpecker/README.md +++ b/frameworks/FSharp/oxpecker/README.md @@ -5,7 +5,7 @@ This includes tests for plaintext, json, fortunes, single query, mutliple querie **Language** -* F# 8.0 +* F# 10.0 **Platforms** diff --git a/frameworks/FSharp/oxpecker/benchmark_config.json b/frameworks/FSharp/oxpecker/benchmark_config.json index 562c9514420..4c8cd1bb59e 100644 --- a/frameworks/FSharp/oxpecker/benchmark_config.json +++ b/frameworks/FSharp/oxpecker/benchmark_config.json @@ -1,5 +1,6 @@ { "framework": "oxpecker", + "maintainers": ["Lanayx"], "tests": [ { "default": { diff --git a/frameworks/FSharp/oxpecker/oxpecker.dockerfile b/frameworks/FSharp/oxpecker/oxpecker.dockerfile index 6424bcad50c..480ed2e3dd8 100644 --- a/frameworks/FSharp/oxpecker/oxpecker.dockerfile +++ b/frameworks/FSharp/oxpecker/oxpecker.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/App . RUN dotnet publish -c Release -o out -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime ENV DOTNET_GCDynamicAdaptationMode=0 ENV DOTNET_ReadyToRun 0 diff --git a/frameworks/FSharp/oxpecker/src/App/App.fsproj b/frameworks/FSharp/oxpecker/src/App/App.fsproj index d54b0983e8b..a3e2378df54 100644 --- a/frameworks/FSharp/oxpecker/src/App/App.fsproj +++ b/frameworks/FSharp/oxpecker/src/App/App.fsproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 false @@ -13,10 +13,10 @@ - - - - + + + + \ No newline at end of file diff --git a/frameworks/FSharp/oxpecker/src/App/Db.fs b/frameworks/FSharp/oxpecker/src/App/Db.fs index e4466dc08c8..7c0a4635fa0 100644 --- a/frameworks/FSharp/oxpecker/src/App/Db.fs +++ b/frameworks/FSharp/oxpecker/src/App/Db.fs @@ -32,20 +32,15 @@ module Db = cmd.Parameters.Add(id) |> ignore struct(cmd, id) - let private readSingleRow (cmd: NpgsqlCommand) = - task { - use! rdr = cmd.ExecuteReaderAsync(CommandBehavior.SingleRow) - let! _ = rdr.ReadAsync() - return { id = rdr.GetInt32(0); randomnumber = rdr.GetInt32(1) } - } - let loadSingleRow () = task { use db = new NpgsqlConnection(ConnectionString) let struct(cmd', _) = createReadCommand db use cmd = cmd' do! db.OpenAsync() - return! readSingleRow cmd + use! rdr = cmd.ExecuteReaderAsync(CommandBehavior.SingleRow) + let! _ = rdr.ReadAsync() + return { id = rdr.GetInt32(0); randomnumber = rdr.GetInt32(1) } } let private readMultipleRows (count: int) (conn: NpgsqlConnection) = @@ -54,8 +49,9 @@ module Db = let struct(cmd', idParam) = createReadCommand conn use cmd = cmd' for i in 0..result.Length-1 do - let! row = readSingleRow cmd - result[i] <- row + use! rdr = cmd.ExecuteReaderAsync(CommandBehavior.SingleRow) + let! _ = rdr.ReadAsync() + result[i] <- { id = rdr.GetInt32(0); randomnumber = rdr.GetInt32(1) } idParam.TypedValue <- Random.Shared.Next(1, 10001) return result } diff --git a/frameworks/FSharp/oxpecker/src/App/RenderHelpers.fs b/frameworks/FSharp/oxpecker/src/App/RenderHelpers.fs index 7a94b2552ba..c26eb0ed93b 100644 --- a/frameworks/FSharp/oxpecker/src/App/RenderHelpers.fs +++ b/frameworks/FSharp/oxpecker/src/App/RenderHelpers.fs @@ -17,7 +17,7 @@ sb.Append(ht.Head) |> ignore for fortune in fortunesData do (tr() { - td() { raw <| string fortune.id } + td() { fortune.id } td() { fortune.message } }).Render(sb) sb.Append(ht.Tail) |> ignore diff --git a/frameworks/Go/atreugo/src/go.mod b/frameworks/Go/atreugo/src/go.mod index 46944099dc5..01fb51e3d5c 100644 --- a/frameworks/Go/atreugo/src/go.mod +++ b/frameworks/Go/atreugo/src/go.mod @@ -1,6 +1,6 @@ module atreugo/src -go 1.23.0 +go 1.24.0 toolchain go1.24.1 @@ -20,8 +20,8 @@ require ( github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.60.0 // indirect - golang.org/x/crypto v0.36.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/crypto v0.45.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect ) diff --git a/frameworks/Go/atreugo/src/go.sum b/frameworks/Go/atreugo/src/go.sum index 0850edc3bd7..87b06ac2495 100644 --- a/frameworks/Go/atreugo/src/go.sum +++ b/frameworks/Go/atreugo/src/go.sum @@ -36,14 +36,14 @@ github.com/valyala/quicktemplate v1.8.0 h1:zU0tjbIqTRgKQzFY1L42zq0qR3eh4WoQQdIdq github.com/valyala/quicktemplate v1.8.0/go.mod h1:qIqW8/igXt8fdrUln5kOSb+KWMaJ4Y8QUsfd1k6L2jM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/frameworks/Go/fiber/src/go.mod b/frameworks/Go/fiber/src/go.mod index 6980da19018..6e1dcc6247f 100644 --- a/frameworks/Go/fiber/src/go.mod +++ b/frameworks/Go/fiber/src/go.mod @@ -1,6 +1,6 @@ module fiber/app -go 1.23.0 +go 1.24.0 toolchain go1.24.1 @@ -24,8 +24,8 @@ require ( github.com/rivo/uniseg v0.4.7 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.60.0 // indirect - golang.org/x/crypto v0.36.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/crypto v0.45.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect ) diff --git a/frameworks/Go/fiber/src/go.sum b/frameworks/Go/fiber/src/go.sum index 386b9e79452..bbb70d60f3f 100644 --- a/frameworks/Go/fiber/src/go.sum +++ b/frameworks/Go/fiber/src/go.sum @@ -43,15 +43,15 @@ github.com/valyala/quicktemplate v1.8.0 h1:zU0tjbIqTRgKQzFY1L42zq0qR3eh4WoQQdIdq github.com/valyala/quicktemplate v1.8.0/go.mod h1:qIqW8/igXt8fdrUln5kOSb+KWMaJ4Y8QUsfd1k6L2jM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/frameworks/Go/gin/gin-gorm/go.mod b/frameworks/Go/gin/gin-gorm/go.mod index 4e73bd0d4e2..1660edbccf5 100644 --- a/frameworks/Go/gin/gin-gorm/go.mod +++ b/frameworks/Go/gin/gin-gorm/go.mod @@ -1,6 +1,6 @@ module gin-gorm/app -go 1.23.0 +go 1.24.0 toolchain go1.24.1 @@ -39,11 +39,11 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect golang.org/x/arch v0.15.0 // indirect - golang.org/x/crypto v0.36.0 // indirect - golang.org/x/net v0.38.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/crypto v0.45.0 // indirect + golang.org/x/net v0.47.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/frameworks/Go/gin/gin-gorm/go.sum b/frameworks/Go/gin/gin-gorm/go.sum index 8d103d7745f..79a5ba8e1a4 100644 --- a/frameworks/Go/gin/gin-gorm/go.sum +++ b/frameworks/Go/gin/gin-gorm/go.sum @@ -84,17 +84,17 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/frameworks/Go/goravel/benchmark_config.json b/frameworks/Go/goravel/benchmark_config.json index bcb01875139..5be71f6fdbe 100644 --- a/frameworks/Go/goravel/benchmark_config.json +++ b/frameworks/Go/goravel/benchmark_config.json @@ -48,6 +48,7 @@ "database_os": "Linux", "display_name": "Goravel Fiber", "notes": "", + "tags": ["broken"], "versus": "go" } } diff --git a/frameworks/Go/goravel/src/fiber/go.mod b/frameworks/Go/goravel/src/fiber/go.mod index 6fd142f91bf..e0ee741ee37 100644 --- a/frameworks/Go/goravel/src/fiber/go.mod +++ b/frameworks/Go/goravel/src/fiber/go.mod @@ -1,6 +1,6 @@ module goravel -go 1.23.0 +go 1.24.0 toolchain go1.24.1 @@ -162,14 +162,14 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect - golang.org/x/crypto v0.35.0 // indirect + golang.org/x/crypto v0.45.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.26.0 // indirect + golang.org/x/net v0.47.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sync v0.11.0 // indirect - golang.org/x/sys v0.30.0 // indirect - golang.org/x/term v0.29.0 // indirect - golang.org/x/text v0.22.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect + golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/api v0.171.0 // indirect google.golang.org/appengine v1.6.8 // indirect diff --git a/frameworks/Go/goravel/src/fiber/go.sum b/frameworks/Go/goravel/src/fiber/go.sum index bc5125921ca..5e100bb5998 100644 --- a/frameworks/Go/goravel/src/fiber/go.sum +++ b/frameworks/Go/goravel/src/fiber/go.sum @@ -723,8 +723,8 @@ golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= -golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -764,8 +764,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -812,8 +812,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -840,8 +840,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -905,8 +905,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -917,8 +917,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= -golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -935,8 +935,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1002,8 +1002,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/frameworks/Go/hertz/go.mod b/frameworks/Go/hertz/go.mod index 4119d421b62..741b2016451 100644 --- a/frameworks/Go/hertz/go.mod +++ b/frameworks/Go/hertz/go.mod @@ -1,6 +1,6 @@ module hertz -go 1.23.0 +go 1.24.0 toolchain go1.24.1 @@ -28,10 +28,10 @@ require ( github.com/tidwall/pretty v1.2.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect golang.org/x/arch v0.15.0 // indirect - golang.org/x/crypto v0.36.0 // indirect + golang.org/x/crypto v0.45.0 // indirect golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect google.golang.org/protobuf v1.36.6 // indirect ) diff --git a/frameworks/Go/hertz/go.sum b/frameworks/Go/hertz/go.sum index 7c4f93bbbfe..9159cda26d4 100644 --- a/frameworks/Go/hertz/go.sum +++ b/frameworks/Go/hertz/go.sum @@ -84,8 +84,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -101,8 +101,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -112,8 +112,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -126,8 +126,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/frameworks/Go/indigo/src/go.mod b/frameworks/Go/indigo/src/go.mod index cf0eeb1cb9e..874efeac4de 100644 --- a/frameworks/Go/indigo/src/go.mod +++ b/frameworks/Go/indigo/src/go.mod @@ -18,8 +18,8 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/net v0.43.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/text v0.28.0 // indirect + golang.org/x/crypto v0.45.0 // indirect + golang.org/x/net v0.47.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/text v0.31.0 // indirect ) diff --git a/frameworks/Go/indigo/src/go.sum b/frameworks/Go/indigo/src/go.sum index 2207dda2ca6..99170600d2b 100644 --- a/frameworks/Go/indigo/src/go.sum +++ b/frameworks/Go/indigo/src/go.sum @@ -36,14 +36,14 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/quicktemplate v1.8.0 h1:zU0tjbIqTRgKQzFY1L42zq0qR3eh4WoQQdIdqCysW5k= github.com/valyala/quicktemplate v1.8.0/go.mod h1:qIqW8/igXt8fdrUln5kOSb+KWMaJ4Y8QUsfd1k6L2jM= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/frameworks/Go/ronykit/benchmark_config.json b/frameworks/Go/ronykit/benchmark_config.json index 69684f9bcef..dcff4ef38bd 100644 --- a/frameworks/Go/ronykit/benchmark_config.json +++ b/frameworks/Go/ronykit/benchmark_config.json @@ -18,6 +18,7 @@ "os": "Linux", "display_name": "RonyKIT", "notes": "", + "tags": ["broken"], "versus": "go" }, "prefork": { @@ -36,8 +37,9 @@ "os": "Linux", "display_name": "RonyKIT", "notes": "", + "tags": ["broken"], "versus": "go" } } ] -} \ No newline at end of file +} diff --git a/frameworks/Go/sprapp/benchmark_config.json b/frameworks/Go/sprapp/benchmark_config.json index a8764b2fe88..9074fd3c2db 100644 --- a/frameworks/Go/sprapp/benchmark_config.json +++ b/frameworks/Go/sprapp/benchmark_config.json @@ -19,6 +19,7 @@ "database_os": "Linux", "display_name": "SPRAPP", "notes": "", + "tags": ["broken"], "versus": "None" } } diff --git a/frameworks/Groovy/grails/benchmark_config.json b/frameworks/Groovy/grails/benchmark_config.json index 10e22e0217b..aa247529c33 100644 --- a/frameworks/Groovy/grails/benchmark_config.json +++ b/frameworks/Groovy/grails/benchmark_config.json @@ -22,7 +22,8 @@ "database_os": "Linux", "display_name": "Grails", "notes": "", - "versus": "servlet" + "versus": "servlet", + "tags": ["broken"] } }] } diff --git a/frameworks/Groovy/hot/benchmark_config.json b/frameworks/Groovy/hot/benchmark_config.json deleted file mode 100644 index 0f309f9fce4..00000000000 --- a/frameworks/Groovy/hot/benchmark_config.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "framework": "hot", - "tests": [{ - "default": { - "json_url": "/rest/json", - "plaintext_url": "/rest/plaintext", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "None", - "framework": "Hot", - "language": "Groovy", - "orm": "Raw", - "platform": "Jetty", - "webserver": "Jetty", - "os": "Linux", - "database_os": "Linux", - "display_name": "Hot", - "notes": "", - "versus": "" - }, - "mongodb" : { - "db_url": "/rest/db/mongodb", - "query_url": "/rest/queries/mongodb?queries=", - "fortune_url": "/rest/fortunes/mongodb", - "update_url": "/rest/updates/mongodb?queries=", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "MongoDB", - "framework": "Hot", - "language": "Groovy", - "orm": "Raw", - "platform": "Jetty", - "webserver": "Jetty", - "os": "Linux", - "database_os": "Linux", - "display_name": "Hot", - "notes": "", - "versus": "", - "tags": ["broken"] - }, "postgres" : { - "db_url": "/rest/db/pgsql", - "query_url": "/rest/queries/pgsql?queries=", - "fortune_url": "/rest/fortunes/pgsql", - "update_url": "/rest/updates/pgsql?queries=", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "Postgres", - "framework": "Hot", - "language": "Groovy", - "orm": "Raw", - "platform": "Jetty", - "webserver": "Jetty", - "os": "Linux", - "database_os": "Linux", - "display_name": "Hot", - "notes": "", - "versus": "", - "tags": ["broken"] - }, "mysql" : { - "db_url": "/rest/db/mysql", - "query_url": "/rest/queries/mysql?queries=", - "fortune_url": "/rest/fortunes/mysql", - "update_url": "/rest/updates/mysql?queries=", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "MySQL", - "framework": "Hot", - "language": "Groovy", - "orm": "Raw", - "platform": "Jetty", - "webserver": "Jetty", - "os": "Linux", - "database_os": "Linux", - "display_name": "Hot", - "notes": "", - "versus": "" - } - }] -} diff --git a/frameworks/Groovy/hot/config-mysql.json b/frameworks/Groovy/hot/config-mysql.json deleted file mode 100644 index f8c78fe4db1..00000000000 --- a/frameworks/Groovy/hot/config-mysql.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "techempower", - "version": "0.1", - "devMode": false, - "dataSources": [ - { - "name": "mysql", - "engine": "MYSQL", - "hostname": "tfb-database", - "port": 3306, - "database": "hello_world", - "username": "benchmarkdbuser", - "password": "benchmarkdbpass" - } - ] -} \ No newline at end of file diff --git a/frameworks/Groovy/hot/config-pgsql.json b/frameworks/Groovy/hot/config-pgsql.json deleted file mode 100644 index 42bff295fe5..00000000000 --- a/frameworks/Groovy/hot/config-pgsql.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "techempower", - "version": "0.1", - "devMode": false, - "dataSources": [ - { - "name": "pgsql", - "engine": "PGSQL", - "hostname": "tfb-database", - "port": 5432, - "database": "hello_world", - "username": "benchmarkdbuser", - "password": "benchmarkdbpass" - } - ] -} \ No newline at end of file diff --git a/frameworks/Groovy/hot/config.json b/frameworks/Groovy/hot/config.json deleted file mode 100644 index eff1c92811d..00000000000 --- a/frameworks/Groovy/hot/config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "techempower", - "version": "0.1", - "devMode": false, - "dataSources": [ - { - "name": "mongo", - "engine": "MONGODB", - "hostname": "tfb-database", - "port": 27017, - "database": "hello_world", - "username": "", - "password": "" - } - ] -} \ No newline at end of file diff --git a/frameworks/Groovy/hot/config.toml b/frameworks/Groovy/hot/config.toml deleted file mode 100644 index 040ce1c5526..00000000000 --- a/frameworks/Groovy/hot/config.toml +++ /dev/null @@ -1,60 +0,0 @@ -[framework] -name = "hot" - -[main] -urls.plaintext = "/rest/plaintext" -urls.json = "/rest/json" -approach = "Realistic" -classification = "Platform" -database = "None" -database_os = "Linux" -os = "Linux" -orm = "Raw" -platform = "Jetty" -webserver = "Jetty" -versus = "" - -[mongodb] -urls.db = "/rest/db/mongodb" -urls.query = "/rest/queries/mongodb?queries=" -urls.update = "/rest/updates/mongodb?queries=" -urls.fortune = "/rest/fortunes/mongodb" -approach = "Realistic" -classification = "Platform" -database = "MongoDB" -database_os = "Linux" -os = "Linux" -orm = "Raw" -platform = "Jetty" -webserver = "Jetty" -versus = "" - -[postgres] -urls.db = "/rest/db/pgsql" -urls.query = "/rest/queries/pgsql?queries=" -urls.update = "/rest/updates/pgsql?queries=" -urls.fortune = "/rest/fortunes/pgsql" -approach = "Realistic" -classification = "Platform" -database = "Postgres" -database_os = "Linux" -os = "Linux" -orm = "Raw" -platform = "Jetty" -webserver = "Jetty" -versus = "" - -[mysql] -urls.db = "/rest/db/mysql" -urls.query = "/rest/queries/mysql?queries=" -urls.update = "/rest/updates/mysql?queries=" -urls.fortune = "/rest/fortunes/mysql" -approach = "Realistic" -classification = "Platform" -database = "MySQL" -database_os = "Linux" -os = "Linux" -orm = "Raw" -platform = "Jetty" -webserver = "Jetty" -versus = "" diff --git a/frameworks/Groovy/hot/hot-mongodb.dockerfile b/frameworks/Groovy/hot/hot-mongodb.dockerfile deleted file mode 100644 index 5dbec3b87b6..00000000000 --- a/frameworks/Groovy/hot/hot-mongodb.dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM openjdk:8-jdk -WORKDIR /hot -COPY shows shows -COPY config.json config.json -ENV HOT_VERSION 0.9.15-SNAPSHOT -RUN curl -sL https://github.com/dsolimando/Hot/releases/download/${HOT_VERSION}/hot-${HOT_VERSION}.tar.gz | tar xz -ENV HOT_HOME /hot/hot-${HOT_VERSION} -ENV PATH ${HOT_HOME}:${PATH} - -EXPOSE 8080 - -CMD ["hot", "run"] diff --git a/frameworks/Groovy/hot/hot-mysql.dockerfile b/frameworks/Groovy/hot/hot-mysql.dockerfile deleted file mode 100644 index f4efb402f16..00000000000 --- a/frameworks/Groovy/hot/hot-mysql.dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM openjdk:8-jdk -WORKDIR /hot -COPY shows shows -COPY config-mysql.json config.json -ENV HOT_VERSION 0.9.15-SNAPSHOT -RUN curl -sL https://github.com/dsolimando/Hot/releases/download/${HOT_VERSION}/hot-${HOT_VERSION}.tar.gz | tar xz -ENV HOT_HOME /hot/hot-${HOT_VERSION} -ENV PATH ${HOT_HOME}:${PATH} - -EXPOSE 8080 - -CMD ["hot", "run"] diff --git a/frameworks/Groovy/hot/hot-postgres.dockerfile b/frameworks/Groovy/hot/hot-postgres.dockerfile deleted file mode 100644 index 567a7181896..00000000000 --- a/frameworks/Groovy/hot/hot-postgres.dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM openjdk:8-jdk -WORKDIR /hot -COPY shows shows -COPY config-pgsql.json config.json -ENV HOT_VERSION 0.9.15-SNAPSHOT -RUN curl -sL https://github.com/dsolimando/Hot/releases/download/${HOT_VERSION}/hot-${HOT_VERSION}.tar.gz | tar xz -ENV HOT_HOME /hot/hot-${HOT_VERSION} -ENV PATH ${HOT_HOME}:${PATH} - -EXPOSE 8080 - -CMD ["hot", "run"] diff --git a/frameworks/Groovy/hot/hot.dockerfile b/frameworks/Groovy/hot/hot.dockerfile deleted file mode 100644 index 5dbec3b87b6..00000000000 --- a/frameworks/Groovy/hot/hot.dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM openjdk:8-jdk -WORKDIR /hot -COPY shows shows -COPY config.json config.json -ENV HOT_VERSION 0.9.15-SNAPSHOT -RUN curl -sL https://github.com/dsolimando/Hot/releases/download/${HOT_VERSION}/hot-${HOT_VERSION}.tar.gz | tar xz -ENV HOT_HOME /hot/hot-${HOT_VERSION} -ENV PATH ${HOT_HOME}:${PATH} - -EXPOSE 8080 - -CMD ["hot", "run"] diff --git a/frameworks/Groovy/hot/shows/benchmark.show.groovy b/frameworks/Groovy/hot/shows/benchmark.show.groovy deleted file mode 100644 index 7f00feccb25..00000000000 --- a/frameworks/Groovy/hot/shows/benchmark.show.groovy +++ /dev/null @@ -1,122 +0,0 @@ -import org.apache.commons.lang3.StringEscapeUtils - -show.scale() - -def mongo = show.dbs.mongo -def pgsqldb = show.dbs.pgsql -def mysql = show.dbs.mysql - -def generator = new Random () - -def generate = { - Math.max(generator.nextInt(10000),1) -} - -def validateNumQueries = { - Integer numQueries - - if (!it) numQueries = 1 - - try { - numQueries = it[0] as Integer - } catch (e) { - numQueries = 1 - } - Math.max(1,Math.min(500,numQueries)) -} - -def query = { db, idLabel = '_id' -> - db.world.findOne([(idLabel):generate()]) -} - -rest.get('/db/mongodb').then { query mongo } -rest.get('/db/pgsql').then { query pgsqldb, 'id' } -rest.get('/db/mysql').then { query mysql, 'id' } - -def queries = { req, db, idLabel = '_id' -> - - def numQueries = validateNumQueries(req?.requestParams?.queries) - def deferred = show.Deferred() - def promise = deferred.promise() - def results = [] - - (1..numQueries).each { i -> - promise = promise.then { - db.world.findOne((idLabel):generate()) - }.then { world -> - results << world - results - } - } - deferred.resolve() - promise -} - -rest.get('/queries/mongodb').then { req -> queries req, mongo } -rest.get('/queries/pgsql').then { req -> queries req, pgsqldb, 'id' } -rest.get('/queries/mysql').then { req -> queries req, mysql, 'id' } - -def template = { content -> - """Fortunes -$content -
idmessage
-""" -} - -def fortune = { db, idLabel = '_id', parseId = { it } -> - db.fortune.find().promise().then { fortunes -> - - fortunes << [(idLabel):'0', message:'Additional fortune added at request time.'] - response = template(fortunes - .sort { it.message } - .collect({ - "${parseId(it[idLabel])}${StringEscapeUtils.escapeHtml4(it.message)}" - }).join('') - ) - new hot.Response(200,['Content-Type':'text/html'], response) - } -} - -rest.get('/fortunes/mongodb').then { - fortune mongo, '_id', { Float.parseFloat(it) as Integer } -} -rest.get('/fortunes/pgsql').then { fortune pgsqldb, 'id' } -rest.get('/fortunes/mysql').then { fortune mysql, 'id' } - -def update = { req, db, idLabel = '_id' -> - def numQueries = validateNumQueries(req?.requestParams?.queries) - - def deferred = show.Deferred() - def promise = deferred.promise() - def results = [] - - (1..numQueries).each { i -> - def genId = generate() - - promise = promise.then { - db.world.findOne((idLabel):genId).promise() - }.then { world -> - world.randomNumber = generate() - db.world.update([(idLabel):genId],[$set:[randomNumber:world.randomNumber]]).then { - world - } - }.then { world -> - results << world - results - } - } - deferred.resolve() - promise -} - -rest.get('/updates/mongodb').then { req -> update req, mongo } -rest.get('/updates/pgsql').then { req -> update req, pgsqldb, 'id' } -rest.get('/updates/mysql').then { req -> update req, mysql, 'id' } - -rest.get("/json").then { - [message:'Hello, World!'] -} - -rest.get('/plaintext').then { - new hot.Response(200,['Content-Type':'text/plain'],'Hello, World!') -} \ No newline at end of file diff --git a/frameworks/Java/activej/activej.dockerfile b/frameworks/Java/activej/activej.dockerfile index cea75f79e0d..da3ba92ee5a 100644 --- a/frameworks/Java/activej/activej.dockerfile +++ b/frameworks/Java/activej/activej.dockerfile @@ -1,11 +1,11 @@ -FROM maven:3.6.1-jdk-11-slim as maven - +FROM maven:3.9.0-eclipse-temurin-17 as maven WORKDIR /activej COPY pom.xml pom.xml COPY src src RUN mvn compile assembly:single -q -FROM openjdk:11.0.3-jdk-slim +FROM amazoncorretto:25 WORKDIR /activej COPY --from=maven /activej/target/activej-server-benchmark-0.0.1-SNAPSHOT-jar-with-dependencies.jar app.jar -CMD ["java", "-Xms2G", "-Xmx2G", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-DHttpServerConnection.initialWriteBufferSize=4096", "-DHttpHeadersMultimap.initialSize=16", "-jar", "app.jar"] \ No newline at end of file +EXPOSE 8080 +CMD ["java", "-server", "-XX:+UseParallelGC", "-jar", "app.jar"] \ No newline at end of file diff --git a/frameworks/Java/dropwizard/dropwizard-jdbi-postgres.dockerfile b/frameworks/Java/dropwizard/dropwizard-jdbi-postgres.dockerfile index 21a897236d7..13b5b94ce53 100644 --- a/frameworks/Java/dropwizard/dropwizard-jdbi-postgres.dockerfile +++ b/frameworks/Java/dropwizard/dropwizard-jdbi-postgres.dockerfile @@ -4,7 +4,7 @@ COPY pom.xml pom.xml COPY src src RUN mvn package -q -P postgres,jdbi -FROM openjdk:11.0.3-jdk-slim +FROM amazoncorretto:25 WORKDIR /dropwizard COPY --from=maven /dropwizard/target/hello-world-0.0.1-SNAPSHOT.jar app.jar COPY hello-world-jdbi-postgres.yml hello-world-jdbi-postgres.yml diff --git a/frameworks/Java/dropwizard/dropwizard-mongodb.dockerfile b/frameworks/Java/dropwizard/dropwizard-mongodb.dockerfile index 1d13f4f9013..ce1fb9d4bbc 100644 --- a/frameworks/Java/dropwizard/dropwizard-mongodb.dockerfile +++ b/frameworks/Java/dropwizard/dropwizard-mongodb.dockerfile @@ -4,7 +4,7 @@ COPY pom.xml pom.xml COPY src src RUN mvn package -q -P mongo -FROM openjdk:11.0.3-jdk-slim +FROM amazoncorretto:25 WORKDIR /dropwizard COPY --from=maven /dropwizard/target/hello-world-0.0.1-SNAPSHOT.jar app.jar COPY hello-world-mongo.yml hello-world-mongo.yml diff --git a/frameworks/Java/dropwizard/dropwizard-postgres.dockerfile b/frameworks/Java/dropwizard/dropwizard-postgres.dockerfile index b088d2df510..25cb2080922 100644 --- a/frameworks/Java/dropwizard/dropwizard-postgres.dockerfile +++ b/frameworks/Java/dropwizard/dropwizard-postgres.dockerfile @@ -4,7 +4,7 @@ COPY pom.xml pom.xml COPY src src RUN mvn package -q -P postgres -FROM openjdk:11.0.3-jdk-slim +FROM amazoncorretto:25 WORKDIR /dropwizard COPY --from=maven /dropwizard/target/hello-world-0.0.1-SNAPSHOT.jar app.jar COPY hello-world-postgres.yml hello-world-postgres.yml diff --git a/frameworks/Java/dropwizard/dropwizard.dockerfile b/frameworks/Java/dropwizard/dropwizard.dockerfile index af3b49c8682..206455df590 100644 --- a/frameworks/Java/dropwizard/dropwizard.dockerfile +++ b/frameworks/Java/dropwizard/dropwizard.dockerfile @@ -4,7 +4,7 @@ COPY pom.xml pom.xml COPY src src RUN mvn package -q -P mysql -FROM openjdk:11.0.3-jdk-slim +FROM amazoncorretto:25 WORKDIR /dropwizard COPY --from=maven /dropwizard/target/hello-world-0.0.1-SNAPSHOT.jar app.jar COPY hello-world-mysql.yml hello-world-mysql.yml diff --git a/frameworks/Java/gemini/benchmark_config.json b/frameworks/Java/gemini/benchmark_config.json index e4049a488c6..0f051744dfa 100644 --- a/frameworks/Java/gemini/benchmark_config.json +++ b/frameworks/Java/gemini/benchmark_config.json @@ -20,6 +20,7 @@ "database_os": "Linux", "display_name": "Gemini", "notes": "", + "tags": ["broken"], "versus": "servlet" }, "mysql": { @@ -42,6 +43,7 @@ "database_os": "Linux", "display_name": "Gemini", "notes": "", + "tags": ["broken"], "versus": "servlet" }, "postgres": { @@ -64,6 +66,7 @@ "database_os": "Linux", "display_name": "Gemini", "notes": "", + "tags": ["broken"], "versus": "servlet" } } diff --git a/frameworks/Java/httpserver/httpserver-graalvm.dockerfile b/frameworks/Java/httpserver/httpserver-graalvm.dockerfile index f9cd7e29cfb..9af2d5f4026 100644 --- a/frameworks/Java/httpserver/httpserver-graalvm.dockerfile +++ b/frameworks/Java/httpserver/httpserver-graalvm.dockerfile @@ -10,4 +10,4 @@ COPY --from=maven /httpserver/target/httpserver-1.0-jar-with-dependencies.jar ap EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar"] +CMD ["java", "-server", "-XX:MaxRAMPercentage=70", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar"] diff --git a/frameworks/Java/httpserver/httpserver-postgres.dockerfile b/frameworks/Java/httpserver/httpserver-postgres.dockerfile index 4cb88012254..6856f3431fa 100644 --- a/frameworks/Java/httpserver/httpserver-postgres.dockerfile +++ b/frameworks/Java/httpserver/httpserver-postgres.dockerfile @@ -4,10 +4,10 @@ COPY pom.xml pom.xml COPY src src RUN mvn compile assembly:single -q -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /httpserver COPY --from=maven /httpserver/target/httpserver-1.0-jar-with-dependencies.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar", "postgres"] +CMD ["java", "-server", "-XX:MaxRAMPercentage=70", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar", "postgres"] diff --git a/frameworks/Java/httpserver/httpserver-robaho-graalvm.dockerfile b/frameworks/Java/httpserver/httpserver-robaho-graalvm.dockerfile index 44b6b0975f0..f6646e3095e 100644 --- a/frameworks/Java/httpserver/httpserver-robaho-graalvm.dockerfile +++ b/frameworks/Java/httpserver/httpserver-robaho-graalvm.dockerfile @@ -10,4 +10,4 @@ COPY --from=maven /httpserver-robaho/target/httpserver-1.0-jar-with-dependencies EXPOSE 8080 -CMD ["java", "-server", "-jar", "app.jar"] +CMD ["java", "-server", "-XX:MaxRAMPercentage=70", "-jar", "app.jar"] diff --git a/frameworks/Java/httpserver/httpserver-robaho-postgres.dockerfile b/frameworks/Java/httpserver/httpserver-robaho-postgres.dockerfile index 7e204f66f52..0b99cb7fe41 100644 --- a/frameworks/Java/httpserver/httpserver-robaho-postgres.dockerfile +++ b/frameworks/Java/httpserver/httpserver-robaho-postgres.dockerfile @@ -4,10 +4,10 @@ COPY pom.xml pom.xml COPY src src RUN mvn compile -P robaho assembly:single -q -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /httpserver-robaho COPY --from=maven /httpserver-robaho/target/httpserver-1.0-jar-with-dependencies.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-jar", "app.jar", "postgres"] +CMD ["java", "-server", "-XX:MaxRAMPercentage=70", "-jar", "app.jar", "postgres"] diff --git a/frameworks/Java/httpserver/httpserver-robaho.dockerfile b/frameworks/Java/httpserver/httpserver-robaho.dockerfile index 1d09e486ef1..0943f9f7ef2 100644 --- a/frameworks/Java/httpserver/httpserver-robaho.dockerfile +++ b/frameworks/Java/httpserver/httpserver-robaho.dockerfile @@ -4,10 +4,10 @@ COPY pom.xml pom.xml COPY src src RUN mvn compile -P robaho assembly:single -q -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /httpserver-robaho COPY --from=maven /httpserver-robaho/target/httpserver-1.0-jar-with-dependencies.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-jar", "app.jar"] +CMD ["java", "-server", "-XX:MaxRAMPercentage=70", "-jar", "app.jar"] diff --git a/frameworks/Java/httpserver/httpserver.dockerfile b/frameworks/Java/httpserver/httpserver.dockerfile index 01aaecc935c..2de799e386d 100644 --- a/frameworks/Java/httpserver/httpserver.dockerfile +++ b/frameworks/Java/httpserver/httpserver.dockerfile @@ -4,10 +4,10 @@ COPY pom.xml pom.xml COPY src src RUN mvn compile assembly:single -q -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /httpserver COPY --from=maven /httpserver/target/httpserver-1.0-jar-with-dependencies.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar"] +CMD ["java", "-server", "-XX:MaxRAMPercentage=70", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-jar", "app.jar"] diff --git a/frameworks/Java/httpserver/pom.xml b/frameworks/Java/httpserver/pom.xml index 26673413278..58cf78deeda 100644 --- a/frameworks/Java/httpserver/pom.xml +++ b/frameworks/Java/httpserver/pom.xml @@ -30,23 +30,21 @@ postgresql 42.7.2 - - com.zaxxer - HikariCP - 3.3.1 - - com.github.httl httl 1.0.11 - org.slf4j slf4j-simple 1.8.0-beta4 + + com.zaxxer + HikariCP + 7.0.2 + @@ -70,7 +68,7 @@ true org.apache.maven.plugins maven-compiler-plugin - 3.8.0 + 3.14.1 false 21 diff --git a/frameworks/Java/httpserver/src/main/java/benchmarks/Server.java b/frameworks/Java/httpserver/src/main/java/benchmarks/Server.java index 2b4beb71889..799f183f46b 100755 --- a/frameworks/Java/httpserver/src/main/java/benchmarks/Server.java +++ b/frameworks/Java/httpserver/src/main/java/benchmarks/Server.java @@ -51,13 +51,24 @@ private static List queryFortunes(DataSource ds) throws SQLException { return fortunes; } - private static DataSource createPostgresDataSource() throws ClassNotFoundException { - Class.forName("org.postgresql.Driver"); + private static DataSource createPostgresDataSource() { HikariConfig config = new HikariConfig(); + config.setJdbcUrl("jdbc:postgresql://tfb-database:5432/hello_world"); config.setUsername("benchmarkdbuser"); config.setPassword("benchmarkdbpass"); - config.setMaximumPoolSize(512); + + config.setMaximumPoolSize(64); + config.setMinimumIdle(0); + + config.setConnectionTimeout(1000); + config.setIdleTimeout(15000); + config.setMaxLifetime(60000); + + config.setAutoCommit(true); + + config.setPoolName("PostgreSQL-HikariCP-Pool"); + return new HikariDataSource(config); } @@ -145,4 +156,4 @@ static void main(String[] args) throws Exception { // start server server.start(); } -} +} \ No newline at end of file diff --git a/frameworks/Java/jetty/jetty-servlet.dockerfile b/frameworks/Java/jetty/jetty-servlet.dockerfile index a352022e489..aafe6afc370 100644 --- a/frameworks/Java/jetty/jetty-servlet.dockerfile +++ b/frameworks/Java/jetty/jetty-servlet.dockerfile @@ -4,7 +4,7 @@ COPY pom.xml pom.xml COPY src src RUN mvn compile assembly:single -q -P servlet -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /jetty COPY --from=maven /jetty/target/jetty-example-0.1-jar-with-dependencies.jar app.jar diff --git a/frameworks/Java/jetty/jetty.dockerfile b/frameworks/Java/jetty/jetty.dockerfile index 15c208ef4e8..996ee1627be 100644 --- a/frameworks/Java/jetty/jetty.dockerfile +++ b/frameworks/Java/jetty/jetty.dockerfile @@ -4,7 +4,7 @@ COPY pom.xml pom.xml COPY src src RUN mvn compile assembly:single -q -FROM openjdk:25-jdk-slim +FROM amazoncorretto:25 WORKDIR /jetty COPY --from=maven /jetty/target/jetty-example-0.1-jar-with-dependencies.jar app.jar diff --git a/frameworks/Java/jooby/jooby-jetty.dockerfile b/frameworks/Java/jooby/jooby-jetty.dockerfile index 0c3c605cc1b..fb23bc745c4 100644 --- a/frameworks/Java/jooby/jooby-jetty.dockerfile +++ b/frameworks/Java/jooby/jooby-jetty.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.9.9-eclipse-temurin-24-noble as maven +FROM maven:3.9.11-eclipse-temurin-25-noble as maven WORKDIR /jooby COPY pom.xml pom.xml COPY src src diff --git a/frameworks/Java/jooby/jooby-mvc.dockerfile b/frameworks/Java/jooby/jooby-mvc.dockerfile index ec8150d3fae..e88198b64bd 100644 --- a/frameworks/Java/jooby/jooby-mvc.dockerfile +++ b/frameworks/Java/jooby/jooby-mvc.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.9.9-eclipse-temurin-24-noble as maven +FROM maven:3.9.11-eclipse-temurin-25-noble as maven WORKDIR /jooby COPY pom.xml pom.xml COPY src src diff --git a/frameworks/Java/jooby/jooby-netty.dockerfile b/frameworks/Java/jooby/jooby-netty.dockerfile index daf8bed238c..cee8fa0aef4 100644 --- a/frameworks/Java/jooby/jooby-netty.dockerfile +++ b/frameworks/Java/jooby/jooby-netty.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.9.9-eclipse-temurin-24-noble as maven +FROM maven:3.9.11-eclipse-temurin-25-noble as maven WORKDIR /jooby COPY pom.xml pom.xml COPY src src diff --git a/frameworks/Java/jooby/jooby-pgclient.dockerfile b/frameworks/Java/jooby/jooby-pgclient.dockerfile index e5917ae2af5..e4ddf09382f 100644 --- a/frameworks/Java/jooby/jooby-pgclient.dockerfile +++ b/frameworks/Java/jooby/jooby-pgclient.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.9.9-eclipse-temurin-24-noble as maven +FROM maven:3.9.11-eclipse-temurin-25-noble as maven WORKDIR /jooby COPY pom.xml pom.xml COPY src src diff --git a/frameworks/Java/jooby/jooby.dockerfile b/frameworks/Java/jooby/jooby.dockerfile index 4685ba51c95..3170040c2de 100644 --- a/frameworks/Java/jooby/jooby.dockerfile +++ b/frameworks/Java/jooby/jooby.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.9.9-eclipse-temurin-24-noble as maven +FROM maven:3.9.11-eclipse-temurin-25-noble as maven WORKDIR /jooby COPY pom.xml pom.xml COPY src src diff --git a/frameworks/Java/jooby/pom.xml b/frameworks/Java/jooby/pom.xml index 1c86733ddc9..eef2366bd98 100644 --- a/frameworks/Java/jooby/pom.xml +++ b/frameworks/Java/jooby/pom.xml @@ -11,12 +11,12 @@ jooby - 4.0.9 + 4.0.11 2.0.2 42.7.7 UTF-8 - 24 - 24 + 25 + 25 com.techempower.App diff --git a/frameworks/Java/jooby/src/main/java/com/techempower/App.java b/frameworks/Java/jooby/src/main/java/com/techempower/App.java index fbc4bdb8164..0c11074d79f 100644 --- a/frameworks/Java/jooby/src/main/java/com/techempower/App.java +++ b/frameworks/Java/jooby/src/main/java/com/techempower/App.java @@ -5,7 +5,6 @@ import static io.jooby.ExecutionMode.EVENT_LOOP; import static io.jooby.MediaType.JSON; -import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.PreparedStatement; diff --git a/frameworks/Java/jooby/src/main/java/com/techempower/ReactivePg.java b/frameworks/Java/jooby/src/main/java/com/techempower/ReactivePg.java index 385c7180539..9123447f1a2 100644 --- a/frameworks/Java/jooby/src/main/java/com/techempower/ReactivePg.java +++ b/frameworks/Java/jooby/src/main/java/com/techempower/ReactivePg.java @@ -110,10 +110,9 @@ public class ReactivePg extends Jooby { private void selectWorlds(Context ctx, int queries, Consumer> consumer) { sqlClient.group( client -> { - var statement = client.preparedQuery(SELECT_WORLD); List worlds = new ArrayList<>(queries); for (int i = 0; i < queries; i++) { - statement + client.preparedQuery(SELECT_WORLD) .execute(Tuple.of(Util.boxedRandomWorld())) .map(rs -> new World(rs.iterator().next().getInteger(0), Util.boxedRandomWorld())) .onComplete( diff --git a/frameworks/Java/jooby/src/main/java/com/techempower/Util.java b/frameworks/Java/jooby/src/main/java/com/techempower/Util.java index fd2f14c86ca..e54ae1074a6 100644 --- a/frameworks/Java/jooby/src/main/java/com/techempower/Util.java +++ b/frameworks/Java/jooby/src/main/java/com/techempower/Util.java @@ -24,7 +24,7 @@ public static int randomWorld() { return 1 + ThreadLocalRandom.current().nextInt(10000); } - public static int boxedRandomWorld() { + public static Integer boxedRandomWorld() { final int rndValue = ThreadLocalRandom.current().nextInt(1, 10001); return BOXED_RND[rndValue - 1]; } diff --git a/frameworks/Java/officefloor/benchmark_config.json b/frameworks/Java/officefloor/benchmark_config.json index 1a309d4ccbd..d90efc51b9d 100755 --- a/frameworks/Java/officefloor/benchmark_config.json +++ b/frameworks/Java/officefloor/benchmark_config.json @@ -47,6 +47,7 @@ "os": "Linux", "database_os": "Linux", "display_name": "OfficeFloor-r2dbc", + "tags": ["broken"], "notes": "" }, "sqlclient": { @@ -69,6 +70,7 @@ "os": "Linux", "database_os": "Linux", "display_name": "OfficeFloor-sqlclient", + "tags": ["broken"], "notes": "" }, "rawsqlclient": { @@ -91,6 +93,7 @@ "os": "Linux", "database_os": "Linux", "display_name": "OfficeFloor-rawsqlclient", + "tags": ["broken"], "notes": "" }, "async": { @@ -162,6 +165,7 @@ "database_os": "Linux", "display_name": "OfficeFloor-thread_affinity", "notes": "", + "tags": ["broken"], "versus": "OfficeFloor-r2dbc" }, "netty": { diff --git a/frameworks/Java/ratpack/benchmark_config.json b/frameworks/Java/ratpack/benchmark_config.json index c3a755d87ab..85d054fed35 100755 --- a/frameworks/Java/ratpack/benchmark_config.json +++ b/frameworks/Java/ratpack/benchmark_config.json @@ -19,6 +19,7 @@ "database_os": "Linux", "display_name": "Ratpack", "notes": "", + "tags": ["broken"], "versus": "Netty" }, "jdbc": { @@ -40,6 +41,7 @@ "database_os": "Linux", "display_name": "Ratpack-jdbc", "notes": "", + "tags": ["broken"], "versus": "Netty" }, "pgclient": { @@ -61,6 +63,7 @@ "database_os": "Linux", "display_name": "Ratpack-pgclient", "notes": "", + "tags": ["broken"], "versus": "Netty" } } diff --git a/frameworks/Java/restexpress/pom.xml b/frameworks/Java/restexpress/pom.xml index 743f4cf5168..5940ab63e7e 100644 --- a/frameworks/Java/restexpress/pom.xml +++ b/frameworks/Java/restexpress/pom.xml @@ -37,7 +37,7 @@ com.fasterxml.jackson.core jackson-databind - 2.12.6.1 + 2.16.0 com.fasterxml.jackson.core diff --git a/frameworks/Java/revenj-jvm/benchmark_config.json b/frameworks/Java/revenj-jvm/benchmark_config.json index 4187598430b..ffc6b919ca6 100644 --- a/frameworks/Java/revenj-jvm/benchmark_config.json +++ b/frameworks/Java/revenj-jvm/benchmark_config.json @@ -22,6 +22,7 @@ "database_os": "Linux", "display_name": "Revenj.JVM", "notes": "", + "tags": ["broken"], "versus": "servlet" } }] diff --git a/frameworks/Java/servlet3/benchmark_config.json b/frameworks/Java/servlet3/benchmark_config.json index b6e4d1b5400..cd2a050e174 100644 --- a/frameworks/Java/servlet3/benchmark_config.json +++ b/frameworks/Java/servlet3/benchmark_config.json @@ -17,6 +17,7 @@ "database_os": "Linux", "display_name": "servlet3", "notes": "Servlet 3.1 Async I/O", + "tags": ["broken"], "versus": "servlet" }, "sync": { @@ -35,6 +36,7 @@ "database_os": "Linux", "display_name": "servlet3", "notes": "", + "tags": ["broken"], "versus": "servlet" } }] diff --git a/frameworks/Java/smart-socket/feat-smart-servlet.dockerfile b/frameworks/Java/smart-socket/feat-smart-servlet.dockerfile index 4209283ec42..7ec765572a8 100644 --- a/frameworks/Java/smart-socket/feat-smart-servlet.dockerfile +++ b/frameworks/Java/smart-socket/feat-smart-servlet.dockerfile @@ -4,7 +4,7 @@ COPY pom.xml pom.xml COPY src src RUN mvn install -q -FROM openjdk:21-jdk-slim +FROM amazoncorretto:25.0.1-alpine WORKDIR /smart-socket COPY --from=maven /smart-socket/target/smart-socket-benchmark-1.0.jar app.jar diff --git a/frameworks/Java/smart-socket/feat.dockerfile b/frameworks/Java/smart-socket/feat.dockerfile index f7eaec61f67..e21235baa58 100644 --- a/frameworks/Java/smart-socket/feat.dockerfile +++ b/frameworks/Java/smart-socket/feat.dockerfile @@ -4,7 +4,7 @@ COPY pom.xml pom.xml COPY src src RUN mvn install -q -FROM openjdk:21-jdk-slim +FROM amazoncorretto:25.0.1-alpine WORKDIR /smart-socket COPY --from=maven /smart-socket/target/smart-socket-benchmark-1.0.jar app.jar diff --git a/frameworks/Java/smart-socket/pom.xml b/frameworks/Java/smart-socket/pom.xml index 7cf9b85b3e7..171f036e654 100644 --- a/frameworks/Java/smart-socket/pom.xml +++ b/frameworks/Java/smart-socket/pom.xml @@ -20,7 +20,7 @@ tech.smartboot.feat feat-cloud-starter - 1.1.0-SNAPSHOT + 1.3.2-SNAPSHOT diff --git a/frameworks/Java/vertx/vertx-postgres.dockerfile b/frameworks/Java/vertx/vertx-postgres.dockerfile index fe4477726c8..a444c3541ee 100644 --- a/frameworks/Java/vertx/vertx-postgres.dockerfile +++ b/frameworks/Java/vertx/vertx-postgres.dockerfile @@ -30,6 +30,7 @@ CMD export DBIP=`getent hosts tfb-database | awk '{ print $1 }'` && \ -Dio.netty.noUnsafe=false \ -Dio.netty.buffer.checkBounds=false \ -Dio.netty.buffer.checkAccessible=false \ + -Dio.netty.iouring.ringSize=16384 \ -jar \ target/vertx.benchmark-0.0.1-SNAPSHOT-fat.jar \ src/main/conf/config.json diff --git a/frameworks/Java/vertx/vertx.dockerfile b/frameworks/Java/vertx/vertx.dockerfile index ae194f4c7f8..1920ebc0228 100644 --- a/frameworks/Java/vertx/vertx.dockerfile +++ b/frameworks/Java/vertx/vertx.dockerfile @@ -6,4 +6,4 @@ RUN mvn package -q EXPOSE 8080 -CMD ["java", "--enable-native-access=ALL-UNNAMED", "--sun-misc-unsafe-memory-access=allow", "--add-opens=java.base/java.lang=ALL-UNNAMED", "-Xms2G", "-Xmx2G", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints", "-Djava.lang.Integer.IntegerCache.high=10000", "-Dvertx.disableMetrics=true", "-Dvertx.disableWebsockets=true", "-Dvertx.disableContextTimings=true", "-Dvertx.disableHttpHeadersValidation=true", "-Dvertx.cacheImmutableHttpResponseHeaders=true", "-Dvertx.internCommonHttpRequestHeadersToLowerCase=true", "-Dio.netty.noUnsafe=false", "-Dio.netty.buffer.checkBounds=false", "-Dio.netty.buffer.checkAccessible=false", "-jar", "target/vertx.benchmark-0.0.1-SNAPSHOT-fat.jar", "src/main/conf/config.json"] +CMD ["java", "--enable-native-access=ALL-UNNAMED", "--sun-misc-unsafe-memory-access=allow", "--add-opens=java.base/java.lang=ALL-UNNAMED", "-Xms2G", "-Xmx2G", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints", "-Djava.lang.Integer.IntegerCache.high=10000", "-Dvertx.disableMetrics=true", "-Dvertx.disableWebsockets=true", "-Dvertx.disableContextTimings=true", "-Dvertx.disableHttpHeadersValidation=true", "-Dvertx.cacheImmutableHttpResponseHeaders=true", "-Dvertx.internCommonHttpRequestHeadersToLowerCase=true", "-Dio.netty.noUnsafe=false", "-Dio.netty.buffer.checkBounds=false", "-Dio.netty.buffer.checkAccessible=false", "-Dio.netty.iouring.ringSize=16384", "-jar", "target/vertx.benchmark-0.0.1-SNAPSHOT-fat.jar", "src/main/conf/config.json"] diff --git a/frameworks/Java/voovan/voovan.dockerfile b/frameworks/Java/voovan/voovan.dockerfile index 2ffcb0dbcfc..26ed65a1bdf 100644 --- a/frameworks/Java/voovan/voovan.dockerfile +++ b/frameworks/Java/voovan/voovan.dockerfile @@ -5,7 +5,7 @@ COPY src src COPY config/framework.properties config/framework.properties RUN mvn package -q -FROM openjdk:25-ea-slim-bullseye +FROM amazoncorretto:25 WORKDIR /voovan COPY --from=maven /voovan/target/voovan-bench-0.1-jar-with-dependencies.jar app.jar COPY --from=maven /voovan/config/framework.properties config/framework.properties diff --git a/frameworks/Java/wildfly-ee/benchmark_config.json b/frameworks/Java/wildfly-ee/benchmark_config.json index 1628dc35eef..7fc9770b023 100644 --- a/frameworks/Java/wildfly-ee/benchmark_config.json +++ b/frameworks/Java/wildfly-ee/benchmark_config.json @@ -22,7 +22,8 @@ "database_os": "Linux", "display_name": "wildfly-ee", "notes": "", + "tags": ["broken"], "versus": "" - } + } }] } diff --git a/frameworks/JavaScript/elide/benchmark_config.json b/frameworks/JavaScript/elide/benchmark_config.json index 32c9d7e82aa..8b8e8599c57 100644 --- a/frameworks/JavaScript/elide/benchmark_config.json +++ b/frameworks/JavaScript/elide/benchmark_config.json @@ -14,6 +14,7 @@ "os": "Linux", "database_os": "Linux", "display_name": "elide", + "tags": ["broken"], "versus": "nodejs" } }] diff --git a/frameworks/JavaScript/spliffy/benchmark_config.json b/frameworks/JavaScript/spliffy/benchmark_config.json index 750dc5bd0cc..40dcb1614bd 100644 --- a/frameworks/JavaScript/spliffy/benchmark_config.json +++ b/frameworks/JavaScript/spliffy/benchmark_config.json @@ -19,6 +19,7 @@ "database_os": "Linux", "display_name": "spliffy", "notes": "directory based routing for node", + "tags": ["broken"], "versus": "nodejs" }, "mongodb": { @@ -41,6 +42,7 @@ "database_os": "Linux", "display_name": "spliffy", "notes": "directory based routing for node", + "tags": ["broken"], "versus": "nodejs" }, "mysql": { @@ -63,6 +65,7 @@ "database_os": "Linux", "display_name": "spliffy", "notes": "directory based routing for node", + "tags": ["broken"], "versus": "nodejs" }, "postgres": { @@ -85,6 +88,7 @@ "database_os": "Linux", "display_name": "spliffy", "notes": "directory based routing for node", + "tags": ["broken"], "versus": "nodejs" } } diff --git a/frameworks/Kotlin/http4k/benchmark_config.json b/frameworks/Kotlin/http4k/benchmark_config.json index 448f868871c..ed160cd0d0d 100755 --- a/frameworks/Kotlin/http4k/benchmark_config.json +++ b/frameworks/Kotlin/http4k/benchmark_config.json @@ -22,6 +22,7 @@ "webserver": "None", "os": "Linux", "notes": "https://http4k.org", + "tags": [ "broken" ], "versus": "servlet" }, "apache4": { @@ -88,6 +89,7 @@ "webserver": "None", "os": "Linux", "notes": "https://http4k.org", + "tags": [ "broken" ], "versus": "helidon-jdbc" }, "jetty": { diff --git a/frameworks/Kotlin/kooby/kooby.dockerfile b/frameworks/Kotlin/kooby/kooby.dockerfile index b689c6e7348..d337708c0df 100644 --- a/frameworks/Kotlin/kooby/kooby.dockerfile +++ b/frameworks/Kotlin/kooby/kooby.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.9.9-eclipse-temurin-24-noble as maven +FROM maven:3.9.11-eclipse-temurin-25-noble as maven WORKDIR /kooby COPY pom.xml pom.xml COPY src src diff --git a/frameworks/Kotlin/kooby/pom.xml b/frameworks/Kotlin/kooby/pom.xml index a27aaaa2a03..3255a6f63a5 100644 --- a/frameworks/Kotlin/kooby/pom.xml +++ b/frameworks/Kotlin/kooby/pom.xml @@ -12,11 +12,11 @@ kooby: jooby+kotlin - 4.0.9 + 4.0.11 42.7.7 UTF-8 - 24 - 24 + 25 + 25 2.2.0 diff --git a/frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle.kts b/frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle.kts index 0622963101a..382ad0c83f9 100644 --- a/frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle.kts +++ b/frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle.kts @@ -2,7 +2,7 @@ plugins { application kotlin("jvm") version "2.0.21" kotlin("plugin.serialization") version "2.0.0" - id("com.github.johnrengelman.shadow") version "8.1.0" + id("com.gradleup.shadow") version "8.3.9" } group = "org.jetbrains.ktor" diff --git a/frameworks/Kotlin/ktor/ktor-cio.dockerfile b/frameworks/Kotlin/ktor/ktor-cio.dockerfile index 7443aed952f..aaa05c4659b 100644 --- a/frameworks/Kotlin/ktor/ktor-cio.dockerfile +++ b/frameworks/Kotlin/ktor/ktor-cio.dockerfile @@ -1,12 +1,11 @@ -FROM maven:3.9.9-amazoncorretto-21-debian-bookworm as maven +FROM gradle:8.13-jdk21 AS build WORKDIR /ktor -COPY ktor/pom.xml pom.xml -COPY ktor/src src -RUN mvn clean package -q +COPY ktor/ ./ +RUN chmod +x gradlew && ./gradlew --no-daemon clean cioBundle FROM amazoncorretto:21-al2023-headless WORKDIR /ktor -COPY --from=maven /ktor/target/tech-empower-framework-benchmark-1.0-SNAPSHOT-cio-bundle.jar app.jar +COPY --from=build /ktor/build/libs/tech-empower-framework-benchmark-1.0-SNAPSHOT-cio-bundle.jar app.jar EXPOSE 9090 diff --git a/frameworks/Kotlin/ktor/ktor-exposed/app/build.gradle.kts b/frameworks/Kotlin/ktor/ktor-exposed/app/build.gradle.kts index 1ce1ba7f1fb..5f29b997834 100644 --- a/frameworks/Kotlin/ktor/ktor-exposed/app/build.gradle.kts +++ b/frameworks/Kotlin/ktor/ktor-exposed/app/build.gradle.kts @@ -1,15 +1,18 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { application kotlin("jvm") version "2.1.21" kotlin("plugin.serialization") version "2.1.21" - id("com.github.johnrengelman.shadow") version "8.1.0" + id("com.gradleup.shadow") version "8.3.9" } repositories { mavenCentral() } -val ktorVersion = "3.1.3" +val ktorVersion = "3.3.3" val kotlinxSerializationVersion = "1.8.1" val exposedVersion = "0.61.0" @@ -31,3 +34,13 @@ dependencies { } application.mainClass.set("AppKt") + +kotlin { + jvmToolchain(21) +} + +tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_21) + } +} diff --git a/frameworks/Kotlin/ktor/ktor-exposed/app/src/main/kotlin/App.kt b/frameworks/Kotlin/ktor/ktor-exposed/app/src/main/kotlin/App.kt index 50ffd37975d..4b4bf93741d 100644 --- a/frameworks/Kotlin/ktor/ktor-exposed/app/src/main/kotlin/App.kt +++ b/frameworks/Kotlin/ktor/ktor-exposed/app/src/main/kotlin/App.kt @@ -10,7 +10,6 @@ import io.ktor.server.plugins.defaultheaders.* import io.ktor.server.response.* import io.ktor.server.routing.* import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext import kotlinx.html.* import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json @@ -22,8 +21,9 @@ import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.ResultRow import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.Transaction -import org.jetbrains.exposed.sql.transactions.transaction -import org.jetbrains.exposed.sql.update +import org.jetbrains.exposed.sql.statements.BatchUpdateStatement +import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction +import org.jetbrains.exposed.sql.transactions.TransactionManager import java.util.concurrent.ThreadLocalRandom @Serializable @@ -73,12 +73,12 @@ fun main(args: Array) { } fun Application.module(exposedMode: ExposedMode) { - val dbRows = 10000 - val poolSize = 48 + val poolSize = Runtime.getRuntime().availableProcessors() * 2 val pool = HikariDataSource(HikariConfig().apply { configurePostgres(poolSize) }) - Database.connect(pool) - suspend fun withDatabaseContextAndTransaction(statement: Transaction.() -> T) = - withContext(Dispatchers.IO) { transaction(statement = statement) } + val database = Database.connect(pool) + val databaseDispatcher = Dispatchers.IO.limitedParallelism(poolSize) + suspend fun withDatabaseTransaction(statement: suspend Transaction.() -> T) = + newSuspendedTransaction(context = databaseDispatcher, db = database, statement = statement) install(DefaultHeaders) @@ -93,7 +93,7 @@ fun Application.module(exposedMode: ExposedMode) { Fortune(this[FortuneTable.id].value, this[FortuneTable.message]) fun ThreadLocalRandom.nextIntWithinRows() = - nextInt(dbRows) + 1 + nextInt(DB_ROWS) + 1 fun selectSingleWorld(random: ThreadLocalRandom): World = selectWorldsWithIdQuery(random.nextIntWithinRows()).single().toWorld() @@ -103,7 +103,7 @@ fun Application.module(exposedMode: ExposedMode) { get("/db") { val random = ThreadLocalRandom.current() - val result = withDatabaseContextAndTransaction { + val result = withDatabaseTransaction { when (exposedMode) { Dsl -> selectSingleWorld(random) Dao -> WorldDao[random.nextIntWithinRows()].toWorld() @@ -117,7 +117,7 @@ fun Application.module(exposedMode: ExposedMode) { val queries = call.queries() val random = ThreadLocalRandom.current() - val result = withDatabaseContextAndTransaction { + val result = withDatabaseTransaction { when (exposedMode) { Dsl -> selectWorlds(queries, random) Dao -> //List(queries) { WorldDao[random.nextIntWithinRows()].toWorld() } @@ -129,7 +129,7 @@ fun Application.module(exposedMode: ExposedMode) { } get("/fortunes") { - val result = withDatabaseContextAndTransaction { + val result = withDatabaseTransaction { when (exposedMode) { Dsl -> FortuneTable.select(FortuneTable.id, FortuneTable.message) .asSequence().map { it.toFortune() } @@ -164,23 +164,17 @@ fun Application.module(exposedMode: ExposedMode) { val random = ThreadLocalRandom.current() lateinit var result: List - withDatabaseContextAndTransaction { + withDatabaseTransaction { when (exposedMode) { Dsl -> { result = selectWorlds(queries, random) - result.forEach { it.randomNumber = random.nextInt(dbRows) + 1 } - result - // sort the data to avoid data race because all updates are in one transaction - .sortedBy { it.id } - .forEach { world -> - WorldTable.update({ WorldTable.id eq world.id }) { - it[randomNumber] = world.randomNumber - } - /* - // An alternative approach: commit every change to avoid data race - commit() - */ - } + result.forEach { it.randomNumber = random.nextIntWithinRows() } + val batch = BatchUpdateStatement(WorldTable) + result.sortedBy { it.id }.forEach { world -> + batch.addBatch(EntityID(world.id, WorldTable)) + batch[WorldTable.randomNumber] = world.randomNumber + } + batch.execute(TransactionManager.current()) } Dao -> /*{ @@ -202,6 +196,8 @@ fun Application.module(exposedMode: ExposedMode) { } } +private const val DB_ROWS = 10_000 + fun HikariConfig.configurePostgres(poolSize: Int) { jdbcUrl = "jdbc:postgresql://tfb-database/hello_world?useSSL=false" driverClassName = org.postgresql.Driver::class.java.name @@ -224,3 +220,4 @@ fun HikariConfig.configureCommon(poolSize: Int) { fun ApplicationCall.queries() = request.queryParameters["queries"]?.toIntOrNull()?.coerceIn(1, 500) ?: 1 + diff --git a/frameworks/Kotlin/ktor/ktor-jetty.dockerfile b/frameworks/Kotlin/ktor/ktor-jetty.dockerfile index 52855ab4a55..c8fd555f50f 100644 --- a/frameworks/Kotlin/ktor/ktor-jetty.dockerfile +++ b/frameworks/Kotlin/ktor/ktor-jetty.dockerfile @@ -1,12 +1,11 @@ -FROM maven:3.9.9-amazoncorretto-21-debian-bookworm as maven +FROM gradle:8.13-jdk21 AS build WORKDIR /ktor -COPY ktor/pom.xml pom.xml -COPY ktor/src src -RUN mvn clean package -q +COPY ktor/ ./ +RUN chmod +x gradlew && ./gradlew --no-daemon clean jettyBundle FROM amazoncorretto:21-al2023-headless WORKDIR /ktor -COPY --from=maven /ktor/target/tech-empower-framework-benchmark-1.0-SNAPSHOT-jetty-bundle.jar app.jar +COPY --from=build /ktor/build/libs/tech-empower-framework-benchmark-1.0-SNAPSHOT-jetty-bundle.jar app.jar EXPOSE 9090 diff --git a/frameworks/Kotlin/ktor/ktor-pgclient/build.gradle.kts b/frameworks/Kotlin/ktor/ktor-pgclient/build.gradle.kts index c98ef463979..baf22d05337 100644 --- a/frameworks/Kotlin/ktor/ktor-pgclient/build.gradle.kts +++ b/frameworks/Kotlin/ktor/ktor-pgclient/build.gradle.kts @@ -1,8 +1,11 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { application - kotlin("jvm") version "2.0.21" - kotlin("plugin.serialization") version "2.0.0" - id("com.github.johnrengelman.shadow") version "8.1.0" + kotlin("jvm") version "2.1.21" + kotlin("plugin.serialization") version "2.1.21" + id("com.gradleup.shadow") version "8.3.9" } group = "org.jetbrains.ktor" @@ -16,8 +19,8 @@ application { mainClass = "io.ktor.server.netty.EngineMain" } -val ktor_version = "3.1.2" -val vertx_version = "4.5.11" +val ktor_version = "3.3.3" +val vertx_version = "5.0.5" dependencies { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1") @@ -36,6 +39,16 @@ java { } } +kotlin { + jvmToolchain(21) +} + +tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_21) + } +} + tasks.shadowJar { archiveBaseName.set("ktor-pgclient") archiveClassifier.set("") diff --git a/frameworks/Kotlin/ktor/ktor-pgclient/gradle/wrapper/gradle-wrapper.properties b/frameworks/Kotlin/ktor/ktor-pgclient/gradle/wrapper/gradle-wrapper.properties index 81aa1c0448a..2733ed5dc3c 100644 --- a/frameworks/Kotlin/ktor/ktor-pgclient/gradle/wrapper/gradle-wrapper.properties +++ b/frameworks/Kotlin/ktor/ktor-pgclient/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/frameworks/Kotlin/ktor/ktor-pgclient/src/main/kotlin/main.kt b/frameworks/Kotlin/ktor/ktor-pgclient/src/main/kotlin/main.kt index 1afafc28fcd..261e9749611 100644 --- a/frameworks/Kotlin/ktor/ktor-pgclient/src/main/kotlin/main.kt +++ b/frameworks/Kotlin/ktor/ktor-pgclient/src/main/kotlin/main.kt @@ -1,3 +1,5 @@ +import io.ktor.http.ContentType +import io.ktor.http.content.TextContent import io.ktor.server.application.* import io.ktor.server.html.* import io.ktor.server.plugins.defaultheaders.* @@ -8,14 +10,23 @@ import io.vertx.pgclient.PgBuilder import io.vertx.pgclient.PgConnectOptions import io.vertx.sqlclient.PoolOptions import io.vertx.sqlclient.Tuple +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope import kotlinx.html.* import java.util.concurrent.ThreadLocalRandom val rand: ThreadLocalRandom get() = ThreadLocalRandom.current() +private const val HELLO_WORLD = "Hello, World!" +private const val WORLD_ROWS = 10_000 + +private fun nextWorldId(): Int = rand.nextInt(1, WORLD_ROWS + 1) + interface Repository { suspend fun getWorld(): World + suspend fun getWorlds(count: Int): List suspend fun getFortunes(): List suspend fun updateWorlds(worlds: List) } @@ -23,8 +34,8 @@ interface Repository { class PgclientRepository : Repository { companion object { private const val FORTUNES_QUERY = "select id, message from FORTUNE" - private const val SELECT_WORLD_QUERY = "SELECT id, randomnumber from WORLD where id=$1" - private const val UPDATE_WORLD_QUERY = "UPDATE WORLD SET randomnumber=$1 WHERE id=$2" + private const val SELECT_WORLD_QUERY = "SELECT id, randomnumber from WORLD where id=\$1" + private const val UPDATE_WORLD_QUERY = "UPDATE WORLD SET randomnumber=\$1 WHERE id=\$2" } private val connectOptions = @@ -38,35 +49,43 @@ class PgclientRepository : Repository { pipeliningLimit = 100000 } + private val poolSize = Runtime.getRuntime().availableProcessors() * 2 private val poolOptions = PoolOptions() + .setMaxSize(poolSize) + .setMaxWaitQueueSize(poolSize * 2) private val client = PgBuilder.client() .with(poolOptions) .connectingTo(connectOptions) .build() + private val selectWorldStatement = client.preparedQuery(SELECT_WORLD_QUERY) + private val updateWorldStatement = client.preparedQuery(UPDATE_WORLD_QUERY) + private val fortunesStatement = client.preparedQuery(FORTUNES_QUERY) + override suspend fun getFortunes(): List { - val results = client.preparedQuery(FORTUNES_QUERY).execute().coAwait() + val results = fortunesStatement.execute().coAwait() return results.map { Fortune(it.getInteger(0), it.getString(1)) } } - override suspend fun getWorld(): World { - val worldId = rand.nextInt(1, 10001) - val result = - client - .preparedQuery(SELECT_WORLD_QUERY) - .execute(Tuple.of(worldId)) - .coAwait() + override suspend fun getWorld(): World = + getWorlds(1).first() + + override suspend fun getWorlds(count: Int): List = coroutineScope { + List(count) { + async { fetchWorld(nextWorldId()) } + }.awaitAll() + } + + private suspend fun fetchWorld(id: Int): World { + val result = selectWorldStatement.execute(Tuple.of(id)).coAwait() val row = result.first() return World(row.getInteger(0), row.getInteger(1)!!) } override suspend fun updateWorlds(worlds: List) { - // Worlds should be sorted before being batch-updated with to avoid data race and deadlocks. + if (worlds.isEmpty()) return val batch = worlds.sortedBy { it.id }.map { Tuple.of(it.randomNumber, it.id) } - client - .preparedQuery(UPDATE_WORLD_QUERY) - .executeBatch(batch) - .coAwait() + updateWorldStatement.executeBatch(batch).coAwait() } } @@ -115,11 +134,11 @@ fun Application.main() { install(DefaultHeaders) routing { get("/plaintext") { - call.respondText("Hello, World!") + call.respond(TextContent(HELLO_WORLD, ContentType.Text.Plain)) } get("/json") { - call.respondJson(Message("Hello, World!")) + call.respondJson(Message(HELLO_WORLD)) } get("/db") { @@ -128,7 +147,7 @@ fun Application.main() { get("/query") { val queries = call.parameters["queries"]?.toBoxedInt(1..500) ?: 1 - val worlds = List(queries) { db.getWorld() } + val worlds = db.getWorlds(queries) call.respondJson(worlds) } @@ -142,12 +161,12 @@ fun Application.main() { get("/updates") { val queries = call.parameters["queries"]?.toBoxedInt(1..500) ?: 1 - val worlds = List(queries) { db.getWorld() } - val newWorlds = worlds.map { it.copy(randomNumber = rand.nextInt(1, 10001)) } - - db.updateWorlds(newWorlds) - - call.respondJson(newWorlds) + val worlds = db.getWorlds(queries).map { world -> + world.randomNumber = nextWorldId() + world + } + db.updateWorlds(worlds) + call.respondJson(worlds) } } } diff --git a/frameworks/Kotlin/ktor/ktor-r2dbc.dockerfile b/frameworks/Kotlin/ktor/ktor-r2dbc.dockerfile index 0c7fc7c2e15..9aa09916483 100644 --- a/frameworks/Kotlin/ktor/ktor-r2dbc.dockerfile +++ b/frameworks/Kotlin/ktor/ktor-r2dbc.dockerfile @@ -1,12 +1,11 @@ -FROM maven:3.9.9-amazoncorretto-21-debian-bookworm as maven +FROM gradle:8.13-jdk21 AS build WORKDIR /ktor-r2dbc -COPY ktor-r2dbc/pom.xml pom.xml -COPY ktor-r2dbc/src src -RUN mvn clean package -q +COPY ktor-r2dbc/ ./ +RUN chmod +x gradlew && ./gradlew --no-daemon clean nettyBundle FROM amazoncorretto:21-al2023-headless WORKDIR /ktor-r2dbc -COPY --from=maven /ktor-r2dbc/target/tech-empower-framework-benchmark-1.0-SNAPSHOT-netty-bundle.jar app.jar +COPY --from=build /ktor-r2dbc/build/libs/tech-empower-framework-benchmark-1.0-SNAPSHOT-netty-bundle.jar app.jar EXPOSE 9090 diff --git a/frameworks/Kotlin/ktor/ktor-r2dbc/README.md b/frameworks/Kotlin/ktor/ktor-r2dbc/README.md index 5b758d68dbd..0cf954902e5 100644 --- a/frameworks/Kotlin/ktor/ktor-r2dbc/README.md +++ b/frameworks/Kotlin/ktor/ktor-r2dbc/README.md @@ -10,27 +10,25 @@ More information is available at [ktor.io](http://ktor.io). # Requirements -* Maven 3 * JDK 21 +* Gradle (wrapper provided) * Kotlin * ktor * netty * R2DBC -Maven is downloaded automatically via Maven Wrapper script (`mvnw`), add dependencies are specified in `pom.xml` so will be downloaded automatically from maven central and jcenter repositories. - # Deployment -Run maven to build a bundle +Use the Gradle wrapper to build the executable bundle: ```bash -./mvnw package +./gradlew nettyBundle ``` -Once bundle build complete and mysql server is running you can launch the application +Once the bundle build completes and Postgres is running you can launch the application ```bash -java -jar target/tech-empower-framework-benchmark-1.0-SNAPSHOT.jar +java -jar build/libs/tech-empower-framework-benchmark-1.0-SNAPSHOT-netty-bundle.jar ``` Please note that the server holds tty so you may need nohup. See `setup.sh` for details. diff --git a/frameworks/Kotlin/ktor/ktor-r2dbc/build.gradle.kts b/frameworks/Kotlin/ktor/ktor-r2dbc/build.gradle.kts new file mode 100644 index 00000000000..1a9fe97655b --- /dev/null +++ b/frameworks/Kotlin/ktor/ktor-r2dbc/build.gradle.kts @@ -0,0 +1,99 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + kotlin("jvm") version "2.1.21" + kotlin("plugin.serialization") version "2.1.21" + id("com.gradleup.shadow") version "8.3.9" +} + +group = "org.jetbrains.ktor" +version = "1.0-SNAPSHOT" + +val ktorVersion = "3.3.3" +val serializationVersion = "1.8.1" +val kotlinxHtmlVersion = "0.12.0" +val coroutinesVersion = "1.10.1" +val logbackVersion = "1.5.13" +val reactorVersion = "3.8.0" +val r2dbcPstgrsVersion = "1.1.1.RELEASE" +val r2dbcPoolVersion = "1.0.2.RELEASE" +val postgresqlVersion = "42.7.5" + +repositories { + mavenCentral() +} + +dependencies { + implementation(kotlin("reflect")) + + implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$serializationVersion") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-io:$serializationVersion") + implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:$kotlinxHtmlVersion") + + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$coroutinesVersion") + + implementation("io.ktor:ktor-server-default-headers-jvm:$ktorVersion") + implementation("io.ktor:ktor-server-html-builder-jvm:$ktorVersion") + implementation("io.ktor:ktor-server-netty-jvm:$ktorVersion") + + implementation("org.postgresql:r2dbc-postgresql:$r2dbcPstgrsVersion") + implementation("io.r2dbc:r2dbc-pool:$r2dbcPoolVersion") + implementation("io.projectreactor:reactor-core:$reactorVersion") + + implementation("ch.qos.logback:logback-classic:$logbackVersion") +} + +sourceSets { + main { + java.srcDirs("src/main/kotlin") + } +} + +kotlin { + jvmToolchain(21) +} + +tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_21) + } +} + +tasks.named("shadowJar") { + enabled = false +} + +fun registerBundle( + name: String, + classifier: String, + mainClass: String +) = tasks.register(name, ShadowJar::class) { + archiveBaseName.set("tech-empower-framework-benchmark") + archiveVersion.set(project.version.toString()) + archiveClassifier.set(classifier) + manifest { + attributes["Main-Class"] = mainClass + } + from(sourceSets.main.get().output) + configurations = listOf(project.configurations.runtimeClasspath.get()) +} + +val nettyBundle by registerBundle( + name = "nettyBundle", + classifier = "netty-bundle", + mainClass = "io.ktor.server.netty.EngineMain" +) + +tasks.register("bundleAll") { + description = "Builds the runnable Netty uber-jar." + dependsOn(nettyBundle) +} + +tasks.named("build") { + dependsOn(nettyBundle) +} + diff --git a/frameworks/Kotlin/ktor/ktor-r2dbc/gradle/wrapper/gradle-wrapper.jar b/frameworks/Kotlin/ktor/ktor-r2dbc/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..28861d273a5 Binary files /dev/null and b/frameworks/Kotlin/ktor/ktor-r2dbc/gradle/wrapper/gradle-wrapper.jar differ diff --git a/frameworks/Kotlin/ktor/ktor-r2dbc/gradle/wrapper/gradle-wrapper.properties b/frameworks/Kotlin/ktor/ktor-r2dbc/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..e6045a98350 --- /dev/null +++ b/frameworks/Kotlin/ktor/ktor-r2dbc/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip diff --git a/frameworks/Kotlin/ktor/ktor-r2dbc/gradlew b/frameworks/Kotlin/ktor/ktor-r2dbc/gradlew new file mode 100755 index 00000000000..cccdd3d517f --- /dev/null +++ b/frameworks/Kotlin/ktor/ktor-r2dbc/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/frameworks/Kotlin/ktor/ktor-r2dbc/gradlew.bat b/frameworks/Kotlin/ktor/ktor-r2dbc/gradlew.bat new file mode 100644 index 00000000000..e95643d6a2c --- /dev/null +++ b/frameworks/Kotlin/ktor/ktor-r2dbc/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/frameworks/Kotlin/ktor/ktor-r2dbc/pom.xml b/frameworks/Kotlin/ktor/ktor-r2dbc/pom.xml deleted file mode 100644 index 9f0754b9512..00000000000 --- a/frameworks/Kotlin/ktor/ktor-r2dbc/pom.xml +++ /dev/null @@ -1,179 +0,0 @@ - - - - 4.0.0 - - org.jetbrains.ktor - tech-empower-framework-benchmark - 1.0-SNAPSHOT - jar - - org.jetbrains.ktor tech-empower-framework-benchmark - - - 2.1.21 - 1.10.1 - 3.1.3 - 1.8.1 - 0.12.0 - UTF-8 - 1.5.13 - 3.7.1 - 42.7.5 - 1.0.7.RELEASE - 1.0.2.RELEASE - - - - - - org.jetbrains.kotlin - kotlin-reflect - ${kotlin.version} - - - org.jetbrains.kotlinx - kotlinx-serialization-core - ${serialization.version} - - - org.jetbrains.kotlinx - kotlinx-serialization-json - ${serialization.version} - - - org.jetbrains.kotlinx - kotlinx-serialization-json-io - ${serialization.version} - - - org.jetbrains.kotlinx - kotlinx-html-jvm - ${kotlinx.html.version} - - - org.jetbrains.kotlinx - kotlinx-coroutines-core - ${kotlin.coroutines.version} - - - org.jetbrains.kotlinx - kotlinx-coroutines-reactor - ${kotlin.coroutines.version} - - - io.ktor - ktor-server-default-headers-jvm - ${ktor.version} - - - io.ktor - ktor-server-html-builder-jvm - ${ktor.version} - - - org.postgresql - r2dbc-postgresql - ${r2dbc.version} - - - io.r2dbc - r2dbc-pool - ${r2dbc.pool.version} - - - io.projectreactor - reactor-core - ${reactor.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - io.ktor - ktor-server-netty-jvm - ${ktor.version} - - - - - src/main/kotlin - - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - - - compile - compile - - compile - - - - test-compile - test-compile - - test-compile - - - - - - kotlinx-serialization - - - - - org.jetbrains.kotlin - kotlin-maven-serialization - ${kotlin.version} - - - - - maven-jar-plugin - - true - - - - default-jar - none - - - - - maven-assembly-plugin - 3.7.1 - - - - netty - - single - - - package - - - - src/main/assembly/netty-bundle.xml - - - - io.ktor.server.netty.EngineMain - - - - - - - - - diff --git a/frameworks/Kotlin/ktor/ktor-r2dbc/settings.gradle.kts b/frameworks/Kotlin/ktor/ktor-r2dbc/settings.gradle.kts new file mode 100644 index 00000000000..b031caa3339 --- /dev/null +++ b/frameworks/Kotlin/ktor/ktor-r2dbc/settings.gradle.kts @@ -0,0 +1,2 @@ +rootProject.name = "tech-empower-framework-benchmark" + diff --git a/frameworks/Kotlin/ktor/ktor-r2dbc/src/main/kotlin/org/jetbrains/ktor/benchmarks/Hello.kt b/frameworks/Kotlin/ktor/ktor-r2dbc/src/main/kotlin/org/jetbrains/ktor/benchmarks/Hello.kt index b0a05351157..54a77082a07 100644 --- a/frameworks/Kotlin/ktor/ktor-r2dbc/src/main/kotlin/org/jetbrains/ktor/benchmarks/Hello.kt +++ b/frameworks/Kotlin/ktor/ktor-r2dbc/src/main/kotlin/org/jetbrains/ktor/benchmarks/Hello.kt @@ -15,15 +15,15 @@ import io.r2dbc.postgresql.PostgresqlConnectionFactory import io.r2dbc.postgresql.client.SSLMode import io.r2dbc.spi.Connection import io.r2dbc.spi.ConnectionFactory -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow import kotlinx.coroutines.reactive.awaitFirst import kotlinx.coroutines.reactive.awaitFirstOrNull +import kotlinx.coroutines.reactor.awaitSingle import kotlinx.html.* import reactor.core.publisher.Flux import reactor.core.publisher.Mono import java.time.Duration -import kotlin.random.Random +import java.util.concurrent.ThreadLocalRandom +import kotlin.math.min const val HELLO_WORLD = "Hello, World!" const val WORLD_QUERY = "SELECT id, randomnumber FROM world WHERE id = $1" @@ -36,7 +36,6 @@ fun Application.main() { val dbConnFactory = configurePostgresR2DBC(config) val helloWorldContent = TextContent("Hello, World!", ContentType.Text.Plain) - val random = Random.Default install(DefaultHeaders) @@ -50,44 +49,18 @@ fun Application.main() { } get("/db") { - val request = getWorld(dbConnFactory, random) - val result = request.awaitFirstOrNull() - - call.respondJson(result) - } - - fun selectWorlds(queries: Int, random: Random): Flow = flow { - repeat(queries) { - emit(getWorld(dbConnFactory, random).awaitFirst()) - } + val world = dbConnFactory.fetchWorld() + call.respondJson(world) } get("/queries") { val queries = call.queries() - - val result = buildList { - selectWorlds(queries, random).collect { - add(it) - } - } - - call.respondJson(result) + val worlds = dbConnFactory.fetchWorlds(queries) + call.respondJson(worlds) } get("/fortunes") { - val result = mutableListOf() - - val request = Flux.usingWhen(dbConnFactory.create(), { connection -> - Flux.from(connection.createStatement(FORTUNES_QUERY).execute()).flatMap { r -> - Flux.from(r.map { row, _ -> - Fortune( - row.get(0, Int::class.java)!!, row.get(1, String::class.java)!! - ) - }) - } - }, { connection -> connection.close() }) - - request.collectList().awaitFirstOrNull()?.let { result.addAll(it) } + val result = dbConnFactory.fetchFortunes().toMutableList() result.add(Fortune(0, "Additional fortune added at request time.")) result.sortBy { it.message } @@ -113,47 +86,85 @@ fun Application.main() { get("/updates") { val queries = call.queries() - val worlds = selectWorlds(queries, random) - - val worldsUpdated = buildList { - worlds.collect { world -> - world.randomNumber = random.nextInt(DB_ROWS) + 1 - add(world) - - Mono.usingWhen(dbConnFactory.create(), { connection -> - Mono.from( - connection.createStatement(UPDATE_QUERY) - .bind(0, world.randomNumber) - .bind(1, world.id) - .execute() - ).flatMap { Mono.from(it.rowsUpdated) } - }, Connection::close).awaitFirstOrNull() - } - } - - call.respondJson(worldsUpdated) + val worlds = dbConnFactory.fetchWorlds(queries) + val updatedWorlds = worlds.map { + it.copy(randomNumber = ThreadLocalRandom.current().nextInt(1, DB_ROWS + 1)) + }.sortedBy { it.id } + + Mono.usingWhen(dbConnFactory.create(), { connection -> + Mono.from(connection.beginTransaction()) + .thenMany( + Flux.fromIterable(updatedWorlds) + .concatMap { world -> + Mono.from( + connection.createStatement(UPDATE_QUERY) + .bind("$1", world.randomNumber) + .bind("$2", world.id) + .execute() + ).flatMap { Mono.from(it.rowsUpdated) } + } + ) + .then(Mono.from(connection.commitTransaction())) + }, + Connection::close, + { connection, _ -> connection.rollbackTransaction() }, + { connection -> connection.rollbackTransaction() } + ).awaitFirstOrNull() + + call.respondJson(updatedWorlds) } } } -private fun getWorld( - dbConnFactory: ConnectionFactory, random: Random -): Mono = Mono.usingWhen(dbConnFactory.create(), { connection -> - Mono.from(connection.createStatement(WORLD_QUERY) - .bind("$1", random.nextInt(DB_ROWS) + 1) - .execute()) - .flatMap { r -> - Mono.from(r.map { row, _ -> - val id = row.get(0, Int::class.java) - val randomNumber = row.get(1, Int::class.java) - if (id != null && randomNumber != null) { - World(id, randomNumber) - } else { - throw IllegalStateException("Database returned null values for required fields") - } - }) - } -}, Connection::close) +private suspend fun ConnectionFactory.fetchWorld(): World = + Mono.usingWhen(create(), { connection -> + selectWorld(connection) + }, Connection::close).awaitSingle() + +private suspend fun ConnectionFactory.fetchWorlds( + count: Int +): List { + if (count <= 0) return emptyList() + val concurrency = min(count, 32) + return Mono.usingWhen(create(), { connection -> + Flux.range(0, count) + .flatMap({ selectWorldPublisher(connection) }, concurrency) + .collectList() + }, Connection::close).awaitSingle() +} + +private fun selectWorld(connection: Connection): Mono = + selectWorldPublisher(connection) + +private fun selectWorldPublisher(connection: Connection): Mono { + val worldId = ThreadLocalRandom.current().nextInt(1, DB_ROWS + 1) + return Mono.from( + connection.createStatement(WORLD_QUERY) + .bind("$1", worldId) + .execute() + ).flatMap { result -> + Mono.from(result.map { row, _ -> + World( + row.get(0, Int::class.java) ?: error("id is null"), + row.get(1, Int::class.java) ?: error("randomNumber is null") + ) + }) + } +} + +private suspend fun ConnectionFactory.fetchFortunes(): List = + Mono.usingWhen(create(), { connection -> + Flux.from(connection.createStatement(FORTUNES_QUERY).execute()) + .flatMap { result -> + Flux.from(result.map { row, _ -> + Fortune( + row.get(0, Int::class.java) ?: error("id is null"), + row.get(1, String::class.java) ?: error("message is null") + ) + }) + } + .collectList() + }, Connection::close).awaitSingle() private fun configurePostgresR2DBC(config: ApplicationConfig): ConnectionFactory { val cfo = PostgresqlConnectionConfiguration.builder() diff --git a/frameworks/Kotlin/ktor/ktor.dockerfile b/frameworks/Kotlin/ktor/ktor.dockerfile index c2624695540..d0d81f0217f 100644 --- a/frameworks/Kotlin/ktor/ktor.dockerfile +++ b/frameworks/Kotlin/ktor/ktor.dockerfile @@ -1,12 +1,11 @@ -FROM maven:3.9.9-amazoncorretto-21-debian-bookworm as maven +FROM gradle:8.13-jdk21 AS build WORKDIR /ktor -COPY ktor/pom.xml pom.xml -COPY ktor/src src -RUN mvn clean package -q +COPY ktor/ ./ +RUN chmod +x gradlew && ./gradlew --no-daemon clean nettyBundle FROM amazoncorretto:21-al2023-headless WORKDIR /ktor -COPY --from=maven /ktor/target/tech-empower-framework-benchmark-1.0-SNAPSHOT-netty-bundle.jar app.jar +COPY --from=build /ktor/build/libs/tech-empower-framework-benchmark-1.0-SNAPSHOT-netty-bundle.jar app.jar EXPOSE 9090 diff --git a/frameworks/Kotlin/ktor/ktor/README.md b/frameworks/Kotlin/ktor/ktor/README.md index 02a13760b07..a265333db59 100644 --- a/frameworks/Kotlin/ktor/ktor/README.md +++ b/frameworks/Kotlin/ktor/ktor/README.md @@ -10,27 +10,25 @@ More information is available at [ktor.io](http://ktor.io). # Requirements -* Maven 3 * JDK 21 +* Gradle (wrapper provided) * Kotlin * ktor * netty * hikariCP -Maven is downloaded automatically via Maven Wrapper script (`mvnw`), add dependencies are specified in `pom.xml` so will be downloaded automatically from maven central and jcenter repositories. - # Deployment -Run maven to build a bundle +Use the Gradle wrapper to assemble the desired runnable bundle (Netty shown below). ```bash -./mvnw package +./gradlew nettyBundle ``` -Once bundle build complete and mysql server is running you can launch the application +Once the bundle build completes and Postgres is running you can launch the application ```bash -java -jar target/tech-empower-framework-benchmark-1.0-SNAPSHOT.jar +java -jar build/libs/tech-empower-framework-benchmark-1.0-SNAPSHOT-netty-bundle.jar ``` Please note that the server holds tty so you may need nohup. See `setup.sh` for details. diff --git a/frameworks/Kotlin/ktor/ktor/build.gradle.kts b/frameworks/Kotlin/ktor/ktor/build.gradle.kts new file mode 100644 index 00000000000..366dc9f1c04 --- /dev/null +++ b/frameworks/Kotlin/ktor/ktor/build.gradle.kts @@ -0,0 +1,108 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + kotlin("jvm") version "2.1.21" + kotlin("plugin.serialization") version "2.1.21" + id("com.gradleup.shadow") version "8.3.9" +} + +group = "org.jetbrains.ktor" +version = "1.0-SNAPSHOT" + +val ktorVersion = "3.3.3" +val serializationVersion = "1.8.1" +val kotlinxHtmlVersion = "0.12.0" +val hikariVersion = "5.1.0" +val logbackVersion = "1.5.13" +val mysqlVersion = "8.0.33" +val postgresqlVersion = "42.7.5" + +repositories { + mavenCentral() +} + +dependencies { + implementation(kotlin("stdlib")) + implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$serializationVersion") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion") + implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:$kotlinxHtmlVersion") + + implementation("io.ktor:ktor-server-default-headers-jvm:$ktorVersion") + implementation("io.ktor:ktor-server-html-builder-jvm:$ktorVersion") + implementation("io.ktor:ktor-server-cio-jvm:$ktorVersion") + implementation("io.ktor:ktor-server-netty-jvm:$ktorVersion") + implementation("io.ktor:ktor-server-jetty-jvm:$ktorVersion") + + implementation("com.zaxxer:HikariCP:$hikariVersion") + implementation("ch.qos.logback:logback-classic:$logbackVersion") + + implementation("org.postgresql:postgresql:$postgresqlVersion") + implementation("mysql:mysql-connector-java:$mysqlVersion") +} + +kotlin { + jvmToolchain(21) +} + +tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_21) + } +} + +tasks.named("shadowJar") { + enabled = false +} + +fun registerBundle( + name: String, + classifier: String, + mainClass: String, + exclusions: List +) = tasks.register(name, ShadowJar::class) { + archiveBaseName.set("tech-empower-framework-benchmark") + archiveVersion.set(project.version.toString()) + archiveClassifier.set(classifier) + manifest { + attributes["Main-Class"] = mainClass + } + from(sourceSets.main.get().output) + configurations = listOf(project.configurations.runtimeClasspath.get()) + dependencies { + exclusions.forEach { exclude(dependency(it)) } + } + mergeServiceFiles() +} + +val nettyBundle by registerBundle( + name = "nettyBundle", + classifier = "netty-bundle", + mainClass = "io.ktor.server.netty.EngineMain", + exclusions = listOf("io.ktor:ktor-server-jetty.*", "io.ktor:ktor-server-cio.*") +) + +val jettyBundle by registerBundle( + name = "jettyBundle", + classifier = "jetty-bundle", + mainClass = "io.ktor.server.jetty.EngineMain", + exclusions = listOf("io.ktor:ktor-server-netty.*", "io.ktor:ktor-server-cio.*") +) + +val cioBundle by registerBundle( + name = "cioBundle", + classifier = "cio-bundle", + mainClass = "io.ktor.server.cio.EngineMain", + exclusions = listOf("io.ktor:ktor-server-netty.*", "io.ktor:ktor-server-jetty.*") +) + +tasks.register("bundleAll") { + description = "Builds all runnable uber-jars (CIO, Jetty, Netty)." + dependsOn(nettyBundle, jettyBundle, cioBundle) +} + +tasks.named("build") { + dependsOn("bundleAll") +} + diff --git a/frameworks/Kotlin/ktor/ktor/gradle/wrapper/gradle-wrapper.jar b/frameworks/Kotlin/ktor/ktor/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..28861d273a5 Binary files /dev/null and b/frameworks/Kotlin/ktor/ktor/gradle/wrapper/gradle-wrapper.jar differ diff --git a/frameworks/Kotlin/ktor/ktor/gradle/wrapper/gradle-wrapper.properties b/frameworks/Kotlin/ktor/ktor/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..e6045a98350 --- /dev/null +++ b/frameworks/Kotlin/ktor/ktor/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip diff --git a/frameworks/Kotlin/ktor/ktor/gradlew b/frameworks/Kotlin/ktor/ktor/gradlew new file mode 100755 index 00000000000..cccdd3d517f --- /dev/null +++ b/frameworks/Kotlin/ktor/ktor/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/frameworks/Kotlin/ktor/ktor/gradlew.bat b/frameworks/Kotlin/ktor/ktor/gradlew.bat new file mode 100644 index 00000000000..e95643d6a2c --- /dev/null +++ b/frameworks/Kotlin/ktor/ktor/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/frameworks/Kotlin/ktor/ktor/pom.xml b/frameworks/Kotlin/ktor/ktor/pom.xml deleted file mode 100644 index a6adb0a651b..00000000000 --- a/frameworks/Kotlin/ktor/ktor/pom.xml +++ /dev/null @@ -1,213 +0,0 @@ - - - - 4.0.0 - - org.jetbrains.ktor - tech-empower-framework-benchmark - 1.0-SNAPSHOT - jar - - org.jetbrains.ktor tech-empower-framework-benchmark - - - 2.1.21 - 3.1.3 - 1.8.1 - 0.12.0 - UTF-8 - 5.1.0 - 1.5.13 - 8.0.33 - 42.7.5 - - - - - org.jetbrains.kotlin - kotlin-stdlib - ${kotlin.version} - - - - org.jetbrains.kotlinx - kotlinx-serialization-core - ${serialization.version} - - - org.jetbrains.kotlinx - kotlinx-serialization-json - ${serialization.version} - - - org.jetbrains.kotlinx - kotlinx-html-jvm - ${kotlinx.html.version} - - - io.ktor - ktor-server-default-headers-jvm - ${ktor.version} - - - io.ktor - ktor-server-html-builder-jvm - ${ktor.version} - - - com.zaxxer - HikariCP - ${hikaricp.version} - - - - org.postgresql - postgresql - ${postgresql.version} - - - - mysql - mysql-connector-java - ${mysql.version} - - - - ch.qos.logback - logback-classic - ${logback.version} - - - io.ktor - ktor-server-netty-jvm - ${ktor.version} - - - io.ktor - ktor-server-jetty-jvm - ${ktor.version} - - - io.ktor - ktor-server-cio-jvm - ${ktor.version} - - - - - src/main/kotlin - - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - - - compile - compile - - compile - - - - test-compile - test-compile - - test-compile - - - - - - kotlinx-serialization - - - - - org.jetbrains.kotlin - kotlin-maven-serialization - ${kotlin.version} - - - - - maven-jar-plugin - - true - - - - default-jar - none - - - - - maven-assembly-plugin - 3.7.1 - - - - cio - - single - - - package - - - - src/main/assembly/cio-bundle.xml - - - - io.ktor.server.cio.EngineMain - - - - - - netty - - single - - - package - - - - src/main/assembly/netty-bundle.xml - - - - io.ktor.server.netty.EngineMain - - - - - - jetty - - single - - - package - - - - src/main/assembly/jetty-bundle.xml - - - - io.ktor.server.jetty.EngineMain - - - - - - - - - diff --git a/frameworks/Kotlin/ktor/ktor/settings.gradle.kts b/frameworks/Kotlin/ktor/ktor/settings.gradle.kts new file mode 100644 index 00000000000..b031caa3339 --- /dev/null +++ b/frameworks/Kotlin/ktor/ktor/settings.gradle.kts @@ -0,0 +1,2 @@ +rootProject.name = "tech-empower-framework-benchmark" + diff --git a/frameworks/Kotlin/ktor/ktor/src/main/kotlin/org/jetbrains/ktor/benchmarks/main.kt b/frameworks/Kotlin/ktor/ktor/src/main/kotlin/org/jetbrains/ktor/benchmarks/main.kt index eea3566b953..aaca738fa49 100644 --- a/frameworks/Kotlin/ktor/ktor/src/main/kotlin/org/jetbrains/ktor/benchmarks/main.kt +++ b/frameworks/Kotlin/ktor/ktor/src/main/kotlin/org/jetbrains/ktor/benchmarks/main.kt @@ -13,9 +13,9 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.withContext import kotlinx.html.* -import java.sql.Connection import java.util.StringJoiner -import kotlin.random.Random +import java.util.concurrent.ThreadLocalRandom +import kotlinx.coroutines.CoroutineDispatcher const val HELLO_WORLD = "Hello, World!" const val WORLD_QUERY = "SELECT id, randomNumber FROM World WHERE id = ?" @@ -30,7 +30,6 @@ fun Application.main() { // Create a dedicated dispatcher for database operations val databaseDispatcher = Dispatchers.IO.limitedParallelism(poolSize) val helloWorldContent = TextContent(HELLO_WORLD, ContentType.Text.Plain) - val random = Random.Default install(DefaultHeaders) @@ -44,36 +43,13 @@ fun Application.main() { } get("/db") { - val world = withContext(databaseDispatcher) { - pool.connection.use { connection -> - connection.prepareStatement(WORLD_QUERY).use { statement -> - statement.setInt(1, random.nextInt(DB_ROWS) + 1) - statement.executeQuery().use { rs -> - rs.next() - World(rs.getInt(1), rs.getInt(2)) - } - } - } - } + val world = fetchWorld(pool, databaseDispatcher) call.respondJson(world) } - fun Connection.selectWorlds(queries: Int): Array = - prepareStatement(WORLD_QUERY).use { statement -> - Array(queries) { i -> - statement.setInt(1, random.nextInt(DB_ROWS) + 1) - statement.executeQuery().use { rs -> - rs.next() - World(rs.getInt(1), rs.getInt(2)) - } - } - } - get("/queries") { val queries = call.queries() - val result = withContext(databaseDispatcher) { - pool.connection.use { it.selectWorlds(queries) } - } + val result = fetchWorlds(pool, queries, databaseDispatcher) call.respondJson(result) } @@ -113,20 +89,18 @@ fun Application.main() { get("/updates") { val queries = call.queries() - val result: Array + val result = fetchWorlds(pool, queries, databaseDispatcher) withContext(databaseDispatcher) { pool.connection.use { connection -> - result = connection.selectWorlds(queries) - val updateSql = StringJoiner( ", ", "UPDATE World SET randomNumber = temp.randomNumber FROM (VALUES ", " ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = World.id" ) - for (i in result.indices) { - result[i].randomNumber = random.nextInt(DB_ROWS) + 1 + for (world in result) { + world.randomNumber = ThreadLocalRandom.current().nextInt(1, DB_ROWS + 1) updateSql.add("(?, ?)") } @@ -146,6 +120,46 @@ fun Application.main() { } } +suspend fun fetchWorld( + pool: HikariDataSource, + dispatcher: CoroutineDispatcher +): World = withContext(dispatcher) { + pool.connection.use { connection -> + fetchWorld(connection) + } +} + +private fun fetchWorld(connection: java.sql.Connection): World = + connection.prepareStatement(WORLD_QUERY).use { statement -> + statement.setInt(1, ThreadLocalRandom.current().nextInt(1, DB_ROWS + 1)) + statement.executeQuery().use { rs -> + rs.next() + World(rs.getInt(1), rs.getInt(2)) + } + } + +suspend fun fetchWorlds( + pool: HikariDataSource, + queries: Int, + dispatcher: CoroutineDispatcher +): Array = withContext(dispatcher) { + if (queries <= 0) { + emptyArray() + } else { + pool.connection.use { connection -> + connection.prepareStatement(WORLD_QUERY).use { statement -> + Array(queries) { + statement.setInt(1, ThreadLocalRandom.current().nextInt(1, DB_ROWS + 1)) + statement.executeQuery().use { rs -> + rs.next() + World(rs.getInt(1), rs.getInt(2)) + } + } + } + } + } +} + fun ApplicationCall.queries() = request.queryParameters["queries"]?.toIntOrNull()?.coerceIn(1, 500) ?: 1 diff --git a/frameworks/Kotlin/vertx-web-kotlin-coroutines/benchmark_config.json b/frameworks/Kotlin/vertx-web-kotlin-coroutines/benchmark_config.json index 2b8ebd26c83..6697013773f 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-coroutines/benchmark_config.json +++ b/frameworks/Kotlin/vertx-web-kotlin-coroutines/benchmark_config.json @@ -18,6 +18,7 @@ "database_os": "Linux", "display_name": "vertx-web-kotlin-coroutines", "notes": "", + "tags": ["broken"], "versus": "vertx-web" }, "postgres": { diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/README.md b/frameworks/Kotlin/vertx-web-kotlin-dsljson/README.md index b8ae3f33b30..2cb792746e2 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/README.md +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/README.md @@ -31,6 +31,12 @@ http://localhost:8080/query?queries= http://localhost:8080/update?queries= -### FORTUNES -http://localhost:8080/fortunes +Testing: + +```shell +../../../tfb \ + --mode benchmark \ + --test vertx-web-kotlin-dsljson \ + --type json +``` \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/benchmark_config.json b/frameworks/Kotlin/vertx-web-kotlin-dsljson/benchmark_config.json index 445d7e5f319..0625b6406be 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/benchmark_config.json +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/benchmark_config.json @@ -24,7 +24,6 @@ "postgresql": { "db_url": "/db", "query_url": "/queries?queries=", - "fortune_url": "/fortunes", "update_url": "/updates?queries=", "port": 8080, "approach": "Realistic", diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts b/frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts index 5131d1b9ec7..03517f3a9a7 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts @@ -1,86 +1,116 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { - kotlin("jvm") version "1.9.22" - kotlin("kapt") version "1.9.22" + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.kotlin.kapt) + alias(libs.plugins.shadow) application - id("com.github.johnrengelman.shadow") version "7.1.2" } group = "com.example" version = "1.0.0-SNAPSHOT" -repositories { - mavenCentral() -} - java { toolchain { - languageVersion.set(JavaLanguageVersion.of(21)) + languageVersion.set(JavaLanguageVersion.of(25)) } } kotlin { compilerOptions { - jvmTarget = JvmTarget.JVM_21 + jvmTarget = JvmTarget.JVM_25 + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_3) + languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_3) + freeCompilerArgs.addAll(listOf( + "-Xjvm-default=all", + "-Xlambdas=indy", + "-Xjdk-release=25" + )) } - jvmToolchain(21) + jvmToolchain(25) } -val mainClassName = "com.example.starter.App" - -val vertxVersion = "4.5.9" -val nettyVersion = "4.1.112.Final" -val scramVersion = "2.1" -val dslJsonVersion = "2.0.2" -val htmlFlowVersion = "4.6" -val log4jVersion = "2.23.1" - application { - mainClass = mainClassName + mainClass = "com.example.starter.AppKt" } dependencies { - listOfNotNull( - // Kotlin - kotlin("stdlib-jdk8"), - kotlin("reflect"), - - // Vertx - platform("io.vertx:vertx-stack-depchain:$vertxVersion"), - "io.vertx:vertx-core", - "io.vertx:vertx-web", - "io.vertx:vertx-pg-client", - "io.vertx:vertx-lang-kotlin", - "io.vertx:vertx-lang-kotlin-coroutines", - - // Netty - "io.netty:netty-transport-native-epoll:$nettyVersion:linux-x86_64", - - // Postgres - "com.ongres.scram:client:$scramVersion", - - // dsljson - "com.dslplatform:dsl-json:$dslJsonVersion", - - // HtmlFlow - "com.github.xmlet:htmlflow:$htmlFlowVersion", - - // Logging - "org.apache.logging.log4j:log4j-core:$log4jVersion", - "org.apache.logging.log4j:log4j-api:$log4jVersion", - "org.apache.logging.log4j:log4j-api-kotlin:1.4.0", - "com.lmax:disruptor:4.0.0", - ).map { implementation(it) } - - listOf( - "com.dslplatform:dsl-json:$dslJsonVersion", - "org.apache.logging.log4j:log4j-core:$log4jVersion", - ).map { kapt(it) } + // Kotlin + implementation(libs.kotlin.stdlib) + implementation(libs.kotlin.reflect) + + // Vert.x + implementation(platform(libs.vertx.bom)) + implementation(libs.vertx.core) + implementation(libs.vertx.web) + implementation(libs.vertx.pg.client) + implementation(libs.vertx.lang.kotlin) + implementation(libs.vertx.lang.kotlin.coroutines) + implementation(libs.vertx.micrometer) + + // Micrometer + implementation(libs.micrometer.registry.prometheus) + + // Netty + implementation(platform(libs.netty.bom)) + resolvePlatformSpecificNettyDependencies(libs.versions.netty.get()) + .forEach { implementation(it) } + + // DSL-JSON + implementation(libs.dsl.json) + kapt(libs.dsl.json) + + // Log4j + implementation(libs.log4j.core) + implementation(libs.log4j.api) + implementation(libs.log4j.api.kotlin) + implementation(libs.disruptor) } -tasks.withType { - archiveClassifier = "fat" - mergeServiceFiles() +tasks { + register("server") { + dependsOn(this@tasks.classes) + + mainClass.set(application.mainClass.get()) + classpath = sourceSets.main.get().runtimeClasspath + + jvmArgs = listOf( + "-server", + "--enable-native-access=ALL-UNNAMED", + "--add-opens=java.base/java.lang=ALL-UNNAMED", + "--sun-misc-unsafe-memory-access=allow", + "-Xms2G", + "-Xmx2G", + "-XX:+AlwaysPreTouch", + "-XX:+UseParallelGC", + "-XX:InitialCodeCacheSize=512m", + "-XX:ReservedCodeCacheSize=512m", + "-XX:MaxInlineLevel=20", + "-XX:+UseNUMA", + "-XX:-UseCodeCacheFlushing", + "-XX:AutoBoxCacheMax=10001", + "-XX:+UseCompactObjectHeaders", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+DebugNonSafepoints", + "-Djava.net.preferIPv4Stack=true", + "-Dvertx.disableMetrics=true", + "-Dvertx.disableWebsockets=true", + "-Dvertx.disableContextTimings=true", + "-Dvertx.cacheImmutableHttpResponseHeaders=true", + "-Dvertx.internCommonHttpRequestHeadersToLowerCase=true", + "-Dvertx.disableHttpHeadersValidation=true", + "-Dio.netty.noUnsafe=false", + "-Dio.netty.buffer.checkBounds=false", + "-Dio.netty.buffer.checkAccessible=false", + "-Dio.netty.leakDetection.level=disabled", + "-Dio.netty.iouring.ringSize=4096", + "-Dio.netty.iouring.cqSize=8192", + "-Dtfb.type=basic", + ) + } + + shadowJar { + archiveClassifier = "fat" + mergeServiceFiles() + } } diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/buildSrc/build.gradle.kts b/frameworks/Kotlin/vertx-web-kotlin-dsljson/buildSrc/build.gradle.kts new file mode 100644 index 00000000000..4a87641372c --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/buildSrc/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + `kotlin-dsl` +} + +repositories { + mavenCentral() +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/buildSrc/src/main/kotlin/Helper.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/buildSrc/src/main/kotlin/Helper.kt new file mode 100644 index 00000000000..99d81bec357 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/buildSrc/src/main/kotlin/Helper.kt @@ -0,0 +1,58 @@ +enum class SystemType { + LINUX_X86_64, + LINUX_AMD64, + LINUX_AARCH64, + OSX_X86_64, + OSX_AARCH64, + WINDOWS_AMD64, + WINDOWS_AARCH64, + UNKNOWN, +} + +data class SystemInfo( + val type: SystemType, + val os: OperatingSystem, +) { + data class OperatingSystem( + val name: String, + val arch: String, + ) +} + +val CURRENT_SYSTEM_INFO by lazy { + val os = System.getProperty("os.name").lowercase() + val arch = System.getProperty("os.arch").lowercase() + val type = when { + os.startsWith("linux") && arch == "x86_64" -> SystemType.LINUX_X86_64 + os.startsWith("linux") && arch == "amd64" -> SystemType.LINUX_AMD64 + os.startsWith("linux") && arch == "aarch64" -> SystemType.LINUX_AARCH64 + os.startsWith("mac") && arch == "x86_64" -> SystemType.OSX_X86_64 + os.startsWith("mac") && arch == "aarch64" -> SystemType.OSX_AARCH64 + os.startsWith("windows") && arch == "amd64" -> SystemType.WINDOWS_AMD64 + os.startsWith("windows") && arch == "aarch64" -> SystemType.WINDOWS_AARCH64 + else -> SystemType.UNKNOWN + } + + SystemInfo( + type = type, + os = SystemInfo.OperatingSystem( + name = os, + arch = arch, + ) + ) +} + +fun resolvePlatformSpecificNettyDependencies(version: String) = when (CURRENT_SYSTEM_INFO.type) { + SystemType.LINUX_X86_64, + SystemType.LINUX_AMD64 -> arrayOf( + "io.netty:netty-transport-native-io_uring:$version:linux-x86_64", + ) + SystemType.LINUX_AARCH64 -> arrayOf( + "io.netty:netty-transport-native-io_uring:$version:linux-aarch_64", + ) + SystemType.OSX_AARCH64 -> arrayOf( + "io.netty:netty-transport-native-kqueue:$version:osx-aarch_64", + "io.netty:netty-resolver-dns-native-macos:$version:osx-aarch_64", + ) + else -> throw IllegalStateException("Unsupported system: $CURRENT_SYSTEM_INFO") +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/configuration/scripts/server.sh b/frameworks/Kotlin/vertx-web-kotlin-dsljson/configuration/scripts/server.sh old mode 100644 new mode 100755 index a5b03908062..6b8380b9308 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/configuration/scripts/server.sh +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/configuration/scripts/server.sh @@ -1,45 +1,92 @@ #!/bin/bash -JVM_OPTS="-server \ +set -euo pipefail + +if [ -f /proc/cpuinfo ]; then + CPU_COUNT=$(grep --count ^processor /proc/cpuinfo) +else + CPU_COUNT=$(sysctl -n hw.ncpu 2>/dev/null || echo 1) +fi + +JAR_PATH="./build/libs/vertx-web-kotlin-dsljson-benchmark-1.0.0-SNAPSHOT-fat.jar" +PG_DOCKER_PATH="../../../toolset/databases/postgres" + +HAS_DB=false +while [[ $# -gt 0 ]]; do + case $1 in + -db) + HAS_DB=true + ;; + esac + shift +done + +if [ "$HAS_DB" = true ]; then + docker image inspect tfb-postgres >/dev/null 2>&1 || \ + docker build -f "$PG_DOCKER_PATH/postgres.dockerfile" -t tfb-postgres "$PG_DOCKER_PATH" + + # ensure no old container blocks name reuse + docker rm -f tfb-postgres >/dev/null 2>&1 || true + + docker run --rm --name tfb-postgres -p 5432:5432 -d tfb-postgres + + until PGPASSWORD=benchmarkdbpass psql -h "0.0.0.0" -U benchmarkdbuser -d hello_world -c '\dt' > /dev/null 2>&1; do + sleep 1 + done +fi + +cleanup() { + echo "Caught termination signal. Cleaning up..." + if [ -n "${JAVA_PID:-}" ]; then + kill -SIGTERM "$JAVA_PID" 2>/dev/null || true + wait "$JAVA_PID" 2>/dev/null || true + fi + + if [ "$HAS_DB" = true ]; then + echo "Stopping postgres container..." + docker stop tfb-postgres >/dev/null 2>&1 || true + docker rm -f tfb-postgres >/dev/null 2>&1 || true + fi +} + +trap cleanup SIGINT SIGTERM EXIT + +java \ + -server \ + --enable-native-access=ALL-UNNAMED \ + --add-opens=java.base/java.lang=ALL-UNNAMED \ -Xms2G \ -Xmx2G \ -XX:+AlwaysPreTouch \ - -XX:+UseParallelGC \ - -XX:+PreserveFramePointer \ + -XX:+UseZGC \ + -XX:+ZUncommit \ + -XX:+DisableExplicitGC \ + -XX:+UseLargePages \ + -XX:+UseStringDeduplication \ -XX:+EnableDynamicAgentLoading \ -XX:InitialCodeCacheSize=512m \ -XX:ReservedCodeCacheSize=512m \ -XX:MaxInlineLevel=20 \ -XX:+UseNUMA \ - -Djava.lang.Integer.IntegerCache.high=10000 \ + -XX:-UseCodeCacheFlushing \ + -XX:AutoBoxCacheMax=10001 \ + -Djava.net.preferIPv4Stack=true \ -Dvertx.disableMetrics=true \ - -Dvertx.disableH2c=true \ + -Dvertx.disableDnsResolver=true \ -Dvertx.disableWebsockets=true \ - -Dvertx.flashPolicyHandler=false \ - -Dvertx.threadChecks=false \ -Dvertx.disableContextTimings=true \ - -Dvertx.disableTCCL=true \ + -Dvertx.cacheImmutableHttpResponseHeaders=true \ + -Dvertx.internCommonHttpRequestHeadersToLowerCase=true \ -Dvertx.disableHttpHeadersValidation=true \ - -Dvertx.eventLoopPoolSize=$((`grep --count ^processor /proc/cpuinfo`)) \ - -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \ + -Dio.netty.noUnsafe=false \ -Dio.netty.buffer.checkBounds=false \ -Dio.netty.buffer.checkAccessible=false \ - -Dtfb.hasDB=false" - -JAR_PATH="./build/libs/vertx-web-kotlin-dsljson-benchmark-1.0.0-SNAPSHOT-fat.jar" - -cleanup() { - echo "Caught SIGINT signal. Stopping the Java program..." - if [ ! -z "$JAVA_PID" ]; then - kill -SIGTERM "$JAVA_PID" - wait "$JAVA_PID" - fi - exit 0 -} - -trap cleanup SIGINT + -Dio.netty.recycler.maxCapacity.default=0 \ + -Dio.netty.maxDirectMemory=0 \ + "-Dtfb.hasDB=$HAS_DB" \ + "-Dtfb.pgHostOverride=0.0.0.0" \ + -jar "$JAR_PATH" & -java $JVM_OPTS -jar $JAR_PATH & JAVA_PID=$! echo "Server PID: $JAVA_PID" diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/libs.versions.toml b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/libs.versions.toml new file mode 100644 index 00000000000..42556c390c6 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/libs.versions.toml @@ -0,0 +1,44 @@ +[versions] +kotlin = "2.3.0-Beta2" +shadow = "9.2.2" +vertx = "5.0.5" +micrometer = "1.16.0" +netty = "4.2.7.Final" +dsljson = "2.0.2" +log4j = "2.25.2" +log4j-kotlin = "1.5.0" +disruptor = "4.0.0" + +[libraries] +# Kotlin +kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" } +kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } + +# Vert.x +vertx-bom = { module = "io.vertx:vertx-stack-depchain", version.ref = "vertx" } +vertx-core = { module = "io.vertx:vertx-core" } +vertx-web = { module = "io.vertx:vertx-web" } +vertx-pg-client = { module = "io.vertx:vertx-pg-client" } +vertx-lang-kotlin = { module = "io.vertx:vertx-lang-kotlin" } +vertx-lang-kotlin-coroutines = { module = "io.vertx:vertx-lang-kotlin-coroutines" } +vertx-micrometer = { module = "io.vertx:vertx-micrometer-metrics" } + +# Prometheus +micrometer-registry-prometheus = { module = "io.micrometer:micrometer-registry-prometheus", version.ref = "micrometer" } + +# Netty +netty-bom = { module = "io.netty:netty-bom", version.ref = "netty" } + +# DSL-JSON +dsl-json = { module = "com.dslplatform:dsl-json", version.ref = "dsljson" } + +# Logging +log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j" } +log4j-api = { module = "org.apache.logging.log4j:log4j-api", version.ref = "log4j" } +log4j-api-kotlin = { module = "org.apache.logging.log4j:log4j-api-kotlin", version.ref = "log4j-kotlin" } +disruptor = { module = "com.lmax:disruptor", version.ref = "disruptor" } + +[plugins] +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } +shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.jar b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.jar index 2c3521197d7..8bdaf60c75a 100644 Binary files a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.jar and b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.jar differ diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.properties b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.properties index 09523c0e549..bad7c2462f5 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.properties +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew old mode 100644 new mode 100755 index f5feea6d6b1..adff685a034 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -173,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -206,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew.bat b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew.bat index 9d21a21834d..c4bdd3ab8e3 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew.bat +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/settings.gradle.kts b/frameworks/Kotlin/vertx-web-kotlin-dsljson/settings.gradle.kts index a5d0428ce6f..a9e579940ea 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/settings.gradle.kts +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/settings.gradle.kts @@ -1 +1,15 @@ +pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + } +} + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + mavenCentral() + } +} + rootProject.name = "vertx-web-kotlin-dsljson-benchmark" diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/App.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/App.kt index ee66a635231..21b08c43611 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/App.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/App.kt @@ -1,50 +1,80 @@ package com.example.starter -import com.example.starter.utils.PeriodicDateResolver +import com.example.starter.helpers.PeriodicResolver +import com.example.starter.helpers.Properties import com.example.starter.utils.block import io.vertx.core.Vertx import io.vertx.kotlin.core.deploymentOptionsOf import io.vertx.kotlin.core.vertxOptionsOf +import io.vertx.kotlin.coroutines.coAwait +import io.vertx.kotlin.micrometer.micrometerMetricsOptionsOf +import io.vertx.kotlin.micrometer.vertxPrometheusOptionsOf import kotlin.time.Duration.Companion.seconds -import org.apache.logging.log4j.kotlin.Logging +import kotlinx.coroutines.runBlocking +import org.apache.logging.log4j.kotlin.logger -object App : Logging { - private const val SERVER_NAME = "Vert.x-Web Benchmark" +private val LOGGER = logger("App") - @JvmStatic - fun main(args: Array?) { - val eventLoopPoolSize = System.getProperty("vertx.eventLoopPoolSize")?.toInt() - ?: Runtime.getRuntime().availableProcessors() +fun main(): Unit = runBlocking { + val vertx = Vertx.vertx( + vertxOptionsOf( + eventLoopPoolSize = Properties.EVENT_LOOP_POOL_SIZE, + preferNativeTransport = true, + disableTCCL = true, + blockedThreadCheckInterval = 60_000, + metricsOptions = if (Properties.METRICS_ENABLED) { + micrometerMetricsOptionsOf( + enabled = true, + jvmMetricsEnabled = true, + nettyMetricsEnabled = true, + prometheusOptions = vertxPrometheusOptionsOf( + enabled = true, + ), + ) + } else null + ) + ) - val vertx = Vertx.vertx( - vertxOptionsOf( - eventLoopPoolSize = eventLoopPoolSize, - preferNativeTransport = true, - ) + if (!vertx.isNativeTransportEnabled) { + throw IllegalStateException( + "Native transport not enabled; missing required dependencies", + vertx.unavailableNativeTransportCause(), ) - vertx.exceptionHandler { - logger.error(it) { "Vertx unexpected exception:" } - vertx.close().block(5.seconds) - } + } + + vertx.exceptionHandler { + LOGGER.error("Vertx unexpected exception", it) + } - // Add the SIGINT handler - Runtime.getRuntime().addShutdownHook(Thread { + Runtime.getRuntime().addShutdownHook( + Thread { vertx.close().block(5.seconds) - }) + } + ) - // Initialize the periodic date resolver - PeriodicDateResolver.init(vertx) + PeriodicResolver.init(vertx) - // Check the type of test that is being run - val hasDb = System.getProperty("tfb.hasDB")?.toBoolean() ?: false + val options = deploymentOptionsOf( + instances = Properties.EVENT_LOOP_POOL_SIZE, + ) - vertx.deployVerticle( - { if (hasDb) PostgresVerticle() else BasicVerticle() }, - deploymentOptionsOf( - instances = eventLoopPoolSize, - ) + val deployment = when (Properties.TYPE) { + "basic" -> vertx.deployVerticle( + BasicVerticle::class.java, + options ) - - logger.info("$SERVER_NAME started.") + "postgres" -> vertx.deployVerticle( + PostgresVerticle::class.java, + options + ) + "all" -> vertx.deployVerticle( + ServerVerticle::class.java, + options + ) + else -> throw IllegalStateException("Unknown deployment type: ${Properties.TYPE}") } -} \ No newline at end of file + + deployment.coAwait() + + LOGGER.info("${Properties.SERVER_NAME} started.") +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/BasicVerticle.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/BasicVerticle.kt index 7870a146c78..0a20956558e 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/BasicVerticle.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/BasicVerticle.kt @@ -2,55 +2,45 @@ package com.example.starter import com.example.starter.handlers.DefaultHandler import com.example.starter.handlers.MessageHandler -import com.example.starter.io.JsonResource +import com.example.starter.helpers.Properties import com.example.starter.utils.isConnectionReset -import io.vertx.core.AbstractVerticle -import io.vertx.core.Promise -import io.vertx.core.http.HttpServerOptions -import io.vertx.ext.web.Router +import io.vertx.kotlin.coroutines.CoroutineVerticle +import io.vertx.kotlin.coroutines.coAwait import org.apache.logging.log4j.kotlin.Logging -class BasicVerticle : AbstractVerticle() { - override fun start(startPromise: Promise) { +class BasicVerticle : CoroutineVerticle() { + override suspend fun start() { val defaultHandler = DefaultHandler() val messageHandler = MessageHandler() - val router = Router.router(vertx) - - router - .get("/plaintext") - .handler(defaultHandler::plaintext) - - router - .get("/json") - .handler(messageHandler::readDefaultMessage) - val server = vertx - .createHttpServer(HTTP_SERVER_OPTIONS) - .requestHandler(router) + .createHttpServer(Properties.HTTP) + .requestHandler { + val path = it.path() + val code = when (path.length) { + 10 -> if (path == PLAINTEXT_PATH) 1 else 0 + 5 -> if (path == JSON_PATH) 2 else 0 + else -> 0 + } + when (code) { + 1 -> defaultHandler.plaintext(it) + 2 -> messageHandler.readDefaultMessage(it) + else -> it.response().setStatusCode(404).end() + } + } .exceptionHandler { - if (it.isConnectionReset()) return@exceptionHandler - logger.error(it) { "Exception in HttpServer" } + if (!it.isConnectionReset()) { + logger.error("Exception in HttpServer", it) + } } - - server .listen() - .onSuccess { - logger.info { "HTTP server started on port 8080" } - startPromise.complete() - } - .onFailure { - logger.error(it.cause) { "Failed to start" } - startPromise.fail(it.cause) - } + .coAwait() + + logger.info("HTTP server started on port ${server.actualPort()}") } companion object : Logging { - private const val HTTP_SERVER_OPTIONS_RESOURCE = "http-server-options.json" - - private val HTTP_SERVER_OPTIONS: HttpServerOptions by lazy { - val json = JsonResource.of(HTTP_SERVER_OPTIONS_RESOURCE) - HttpServerOptions(json) - } + private const val PLAINTEXT_PATH = "/plaintext" + private const val JSON_PATH = "/json" } } diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/PostgresVerticle.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/PostgresVerticle.kt index 4caa057b488..5d31eb03bc4 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/PostgresVerticle.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/PostgresVerticle.kt @@ -4,78 +4,60 @@ import com.example.starter.db.FortuneRepository import com.example.starter.db.WorldRepository import com.example.starter.handlers.FortuneHandler import com.example.starter.handlers.WorldHandler -import com.example.starter.io.JsonResource +import com.example.starter.helpers.Properties import com.example.starter.utils.isConnectionReset -import io.vertx.core.AbstractVerticle -import io.vertx.core.Promise -import io.vertx.core.http.HttpServerOptions -import io.vertx.ext.web.Router -import io.vertx.pgclient.PgConnectOptions +import io.vertx.kotlin.coroutines.CoroutineVerticle +import io.vertx.kotlin.coroutines.coAwait import io.vertx.pgclient.PgConnection import org.apache.logging.log4j.kotlin.Logging -class PostgresVerticle : AbstractVerticle() { - override fun start(startPromise: Promise) { - PgConnection.connect(vertx, PG_CONNECT_OPTIONS) - .onSuccess { conn -> - val fortuneHandler = FortuneHandler(FortuneRepository(conn)) - val worldHandler = WorldHandler(WorldRepository(conn)) - - val router = Router.router(vertx) - - router - .get("/fortunes") - .handler(fortuneHandler::templateFortunes) - - router - .get("/db") - .handler(worldHandler::readRandomWorld) - - router - .get("/queries") - .handler(worldHandler::readRandomWorlds) - - router - .get("/updates") - .handler(worldHandler::updateRandomWorlds) - - val server = vertx - .createHttpServer(HTTP_SERVER_OPTIONS) - .requestHandler(router) - .exceptionHandler { - if (it.isConnectionReset()) return@exceptionHandler - logger.error(it) { "Exception in HttpServer" } - } - - server - .listen() - .onSuccess { - logger.info { "HTTP server started on port 8080" } - startPromise.complete() - } - .onFailure { - logger.error(it) { "Failed to start" } - startPromise.fail(it) +class PostgresVerticle : CoroutineVerticle() { + override suspend fun start() { + val conn = PgConnection.connect(vertx, Properties.PG_CONNECT).coAwait() + + val fortuneRepository = FortuneRepository.init(conn) + val worldRepository = WorldRepository.init(conn) + + val fortuneHandler = FortuneHandler(fortuneRepository.coAwait()) + val worldHandler = WorldHandler(worldRepository.coAwait()) + + val server = vertx + .createHttpServer(Properties.HTTP) + .requestHandler { + val path = it.path() + val code = when (path.length) { + 9 -> if (path == FORTUNES_PATH) 1 else 0 + 3 -> if (path == DB_PATH) 2 else 0 + 8 -> when (path) { + QUERIES_PATH -> 3 + UPDATES_PATH -> 4 + else -> 0 } + else -> 0 + } + when (code) { + 1 -> fortuneHandler.templateFortunes(it) + 2 -> worldHandler.readRandomWorld(it) + 3 -> worldHandler.readRandomWorlds(it) + 4 -> worldHandler.updateRandomWorlds(it) + else -> it.response().setStatusCode(404).end() + } } - .onFailure { - logger.error(it) { "Failed to start" } - startPromise.fail(it) + .exceptionHandler { + if (!it.isConnectionReset()) { + logger.error("Exception in HttpServer", it) + } } + .listen() + .coAwait() + + logger.info("HTTP server started on port ${server.actualPort()}") } companion object : Logging { - private const val HTTP_SERVER_OPTIONS_RESOURCE = "http-server-options.json" - private const val PG_CONNECT_OPTIONS_RESOURCE = "pg-connect-options.json" - - private val HTTP_SERVER_OPTIONS: HttpServerOptions by lazy { - val json = JsonResource.of(HTTP_SERVER_OPTIONS_RESOURCE) - HttpServerOptions(json) - } - - private val PG_CONNECT_OPTIONS: PgConnectOptions by lazy { - val json = JsonResource.of(PG_CONNECT_OPTIONS_RESOURCE) - PgConnectOptions(json) - } + private const val FORTUNES_PATH = "/fortunes" + private const val DB_PATH = "/db" + private const val QUERIES_PATH = "/queries" + private const val UPDATES_PATH = "/updates" } } diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/ServerVerticle.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/ServerVerticle.kt new file mode 100644 index 00000000000..c86ea244774 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/ServerVerticle.kt @@ -0,0 +1,91 @@ +package com.example.starter + +import com.example.starter.db.FortuneRepository +import com.example.starter.db.WorldRepository +import com.example.starter.handlers.DefaultHandler +import com.example.starter.handlers.FortuneHandler +import com.example.starter.handlers.MessageHandler +import com.example.starter.handlers.WorldHandler +import com.example.starter.helpers.Properties +import com.example.starter.utils.isConnectionReset +import io.micrometer.prometheusmetrics.PrometheusMeterRegistry +import io.vertx.core.Handler +import io.vertx.core.http.HttpHeaders.CONTENT_TYPE +import io.vertx.core.http.HttpServerRequest +import io.vertx.kotlin.coroutines.CoroutineVerticle +import io.vertx.kotlin.coroutines.coAwait +import io.vertx.micrometer.backends.BackendRegistries +import io.vertx.pgclient.PgConnection +import org.apache.logging.log4j.kotlin.Logging + +class ServerVerticle() : CoroutineVerticle() { + override suspend fun start() { + val conn = PgConnection.connect(vertx, Properties.PG_CONNECT).coAwait() + + val fortuneRepository = FortuneRepository.init(conn) + val worldRepository = WorldRepository.init(conn) + + val fortuneHandler = FortuneHandler(fortuneRepository.coAwait()) + val worldHandler = WorldHandler(worldRepository.coAwait()) + + val defaultHandler = DefaultHandler() + val messageHandler = MessageHandler() + + val metricsHandler = if (Properties.METRICS_ENABLED) { + val registry = BackendRegistries.getDefaultNow() as PrometheusMeterRegistry + Handler { + it.response() + .putHeader(CONTENT_TYPE, "text/plain; version=0.0.4; charset=utf-8") + .end(registry.scrape()) + } + } else null + + val server = vertx + .createHttpServer(Properties.HTTP) + .requestHandler { + val path = it.path() + val code = when (path.length) { + 10 -> if (path == PLAINTEXT_PATH) 1 else 0 + 5 -> if (path == JSON_PATH) 2 else 0 + 9 -> if (path == FORTUNES_PATH) 3 else 0 + 3 -> if (path == DB_PATH) 4 else 0 + 8 -> when (path) { + QUERIES_PATH -> 5 + UPDATES_PATH -> 6 + METRICS_PATH -> 7 + else -> 0 + } + else -> 0 + } + when (code) { + 1 -> defaultHandler.plaintext(it) + 2 -> messageHandler.readDefaultMessage(it) + 3 -> fortuneHandler.templateFortunes(it) + 4 -> worldHandler.readRandomWorld(it) + 5 -> worldHandler.readRandomWorlds(it) + 6 -> worldHandler.updateRandomWorlds(it) + 7 -> metricsHandler?.handle(it) ?: it.response().setStatusCode(404).end() + else -> it.response().setStatusCode(404).end() + } + } + .exceptionHandler { + if (!it.isConnectionReset()) { + logger.error("Exception in HttpServer", it) + } + } + .listen() + .coAwait() + + logger.info("HTTP server started on port ${server.actualPort()}") + } + + companion object : Logging { + private const val METRICS_PATH = "/metrics" + private const val PLAINTEXT_PATH = "/plaintext" + private const val JSON_PATH = "/json" + private const val FORTUNES_PATH = "/fortunes" + private const val DB_PATH = "/db" + private const val QUERIES_PATH = "/queries" + private const val UPDATES_PATH = "/updates" + } +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/FortuneRepository.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/FortuneRepository.kt index b9e4b9ab784..a3c0831f3aa 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/FortuneRepository.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/FortuneRepository.kt @@ -5,19 +5,35 @@ import com.example.starter.utils.mapToArray import io.vertx.core.Future import io.vertx.pgclient.PgConnection +import io.vertx.sqlclient.PreparedQuery import io.vertx.sqlclient.Row +import io.vertx.sqlclient.RowSet -class FortuneRepository(conn: PgConnection) : AbstractRepository(conn) { - private val selectFortuneQuery = this.conn.preparedQuery(SELECT_FORTUNE_SQL) +@Suppress("NOTHING_TO_INLINE") +class FortuneRepository( + conn: PgConnection, + private val selectFortunesQuery: PreparedQuery>, +) : AbstractRepository(conn) { - fun selectFortunes(): Future> = selectFortuneQuery + fun selectFortunes(): Future> = selectFortunesQuery .execute() .map { it.mapToArray(FortuneRepository::map) } companion object { - private const val SELECT_FORTUNE_SQL = "SELECT id, message FROM fortune" + private const val SELECT_FORTUNES_SQL = "SELECT id, message FROM fortune" - @Suppress("NOTHING_TO_INLINE") - private inline fun map(row: Row): Fortune = Fortune(row.getInteger(0), row.getString(1)) + private inline fun map(row: Row): Fortune = Fortune( + row.getInteger(0), + row.getString(1), + ) + + fun init(conn: PgConnection): Future = conn.let { conn -> + conn.prepare(SELECT_FORTUNES_SQL).map { ps -> + FortuneRepository( + conn, + ps.query(), + ) + } + } } } \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt index 74823141453..e12717e7228 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt @@ -3,38 +3,48 @@ package com.example.starter.db import com.example.starter.models.World import io.vertx.core.Future import io.vertx.core.Promise +import io.vertx.core.impl.future.CompositeFutureImpl import io.vertx.pgclient.PgConnection import io.vertx.sqlclient.PreparedQuery import io.vertx.sqlclient.Row import io.vertx.sqlclient.RowSet import io.vertx.sqlclient.Tuple -import io.vertx.sqlclient.impl.ArrayTuple import io.vertx.sqlclient.impl.SqlClientInternal +import io.vertx.sqlclient.internal.ArrayTuple import java.util.concurrent.ThreadLocalRandom import java.util.concurrent.atomic.AtomicInteger @Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST") -class WorldRepository(conn: PgConnection) : AbstractRepository(conn) { - private val selectWorldQuery = this.conn.preparedQuery(SELECT_WORLD_SQL) - private val updateWorldQueries = generateQueries(this.conn) - +class WorldRepository private constructor( + conn: PgConnection, + private val selectWorldQuery: PreparedQuery>, + private val updateWorldQueries: Array>>, +) : AbstractRepository(conn) { fun selectRandomWorld(): Future = selectWorldQuery .execute(Tuple.of(randomWorld())) - .map { map(it.iterator().next()) } + .map { map(it.first()) } fun selectRandomWorlds(numWorlds: Int): Future> { val promise = Promise.promise>() val arr = arrayOfNulls(numWorlds) val count = AtomicInteger(0) (this.conn as SqlClientInternal).group { c -> - repeat(numWorlds) { - c.preparedQuery(SELECT_WORLD_SQL).execute(Tuple.of(randomWorld())) { ar -> - val index = count.getAndIncrement() - arr[index] = map(ar.result().iterator().next()) - if (index == numWorlds - 1) { - promise.complete(arr as Array) + val query = c.preparedQuery(SELECT_WORLD_SQL) + repeat(numWorlds) { _ -> + query.execute(Tuple.of(randomWorld())) + .onComplete { ar -> + when { + ar.succeeded() -> { + val result = ar.result() + val index = count.getAndIncrement() + arr[index] = map(result.iterator().next()) + if (index == numWorlds - 1) { + promise.complete(arr as Array) + } + } + else -> promise.fail(ar.cause()) + } } - } } } return promise.future() @@ -57,28 +67,49 @@ class WorldRepository(conn: PgConnection) : AbstractRepository(conn) { companion object { private const val SELECT_WORLD_SQL = "SELECT id, randomnumber FROM world WHERE id = $1" - private inline fun randomWorld(): Int = 1 + ThreadLocalRandom.current().nextInt(10000) - private inline fun map(row: Row): World = World(row.getInteger(0), row.getInteger(1)) + private inline fun randomWorld(): Int = 1 + ThreadLocalRandom.current().nextInt(10_000) + private inline fun map(row: Row): World = World( + row.getInteger(0), + row.getInteger(1), + ) - private fun generateQueries(conn: PgConnection): Array>> { - val arr = arrayOfNulls>>(500) - for (num in 1..500) { - var paramIndex = 1 - val sb = StringBuilder() - sb.append("UPDATE world SET randomnumber = CASE id ") - for (i in 1..num) { - sb.append("WHEN \$$paramIndex THEN \$${paramIndex + 1} ") - paramIndex += 2 - } - sb.append("ELSE randomnumber END WHERE id IN (") - for (i in 1..num) { - sb.append("\$$paramIndex,") - paramIndex += 1 + fun init(conn: PgConnection): Future = conn.let { conn -> + val selectWorldQuery = conn.prepare(SELECT_WORLD_SQL).map { ps -> ps.query() } + val updateWorldQueries = run { + val queries = arrayOfNulls>>(500) + Array(500) { num -> + val count = num + 1 + var paramIndex = 1 + val sb = StringBuilder() + sb.append("UPDATE world SET randomnumber = CASE id ") + repeat(count) { + sb.append("WHEN $${paramIndex++} THEN $${paramIndex++} ") + } + sb.append("ELSE randomnumber END WHERE id IN (") + repeat(count) { + sb.append("$${paramIndex++},") + } + sb[sb.length - 1] = ')' + + conn + .prepare(sb.toString()) + .map { ps -> + queries[num] = ps.query() + } + }.let { + CompositeFutureImpl.all(*it).map { + queries as Array>> + } } - sb[sb.length - 1] = ')' - arr[num - 1] = conn.preparedQuery(sb.toString()) } - return arr as Array>> + + CompositeFutureImpl.all(selectWorldQuery, updateWorldQueries).map { + WorldRepository( + conn, + selectWorldQuery.result(), + updateWorldQueries.result(), + ) + } } } } diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/AbstractHandler.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/AbstractHandler.kt index cb29d630167..d34e72b5598 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/AbstractHandler.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/AbstractHandler.kt @@ -1,57 +1,52 @@ package com.example.starter.handlers -import com.example.starter.utils.PeriodicDateResolver -import io.vertx.core.AsyncResult -import io.vertx.core.Handler +import com.example.starter.helpers.PeriodicResolver +import com.example.starter.helpers.Properties +import io.netty.handler.codec.http.HttpHeaderNames +import io.netty.handler.codec.http.HttpHeaderValues +import io.vertx.core.Future import io.vertx.core.MultiMap +import io.vertx.core.buffer.Buffer import io.vertx.core.http.HttpHeaders +import io.vertx.core.http.HttpServerRequest import io.vertx.core.http.HttpServerResponse -import io.vertx.ext.web.RoutingContext +import io.vertx.core.internal.buffer.BufferInternal @Suppress("NOTHING_TO_INLINE") abstract class AbstractHandler { protected companion object { - val NULL_HANDLER: Handler>? = null - - const val SOMETHING_WENT_WRONG = "Something went wrong" + val SOMETHING_WENT_WRONG: Buffer = BufferInternal.buffer("Something went wrong") // Headers - val SERVER: CharSequence = HttpHeaders.createOptimized("Vert.x-Web") - val APPLICATION_JSON: CharSequence = HttpHeaders.createOptimized("application/json") - val TEXT_PLAIN: CharSequence = HttpHeaders.createOptimized("text/plain") - val TEXT_HTML: CharSequence = HttpHeaders.createOptimized("text/html; charset=utf-8") + val SERVER: CharSequence = HttpHeaders.createOptimized(Properties.SERVER_NAME) inline fun MultiMap.common(): MultiMap = this - .add(HttpHeaders.SERVER, SERVER) - .add(HttpHeaders.DATE, PeriodicDateResolver.current) - - inline fun RoutingContext.json(): HttpServerResponse { - val response = this.response() - val headers = response.headers() - headers - .common() - .add(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) - return response - } - - inline fun RoutingContext.text(): HttpServerResponse { - val response = this.response() - val headers = response.headers() - headers - .common() - .add(HttpHeaders.CONTENT_TYPE, TEXT_PLAIN) - return response - } - - inline fun RoutingContext.html(): HttpServerResponse { - val response = this.response() - val headers = response.headers() - headers - .common() - .add(HttpHeaders.CONTENT_TYPE, TEXT_HTML) - return response - } - - inline fun RoutingContext.error(): Unit = this.text().end(SOMETHING_WENT_WRONG, NULL_HANDLER) + .add(HttpHeaderNames.SERVER, SERVER) + .add(HttpHeaderNames.DATE, PeriodicResolver.current) + + inline fun HttpServerRequest.json(): HttpServerResponse = response() + .apply { + headers() + .common() + .add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON) + } + + inline fun HttpServerRequest.plaintext(): HttpServerResponse = response() + .apply { + headers() + .common() + .add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN) + } + + inline fun HttpServerRequest.html(): HttpServerResponse = response() + .apply { + headers() + .common() + .add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_HTML) + } + + inline fun HttpServerRequest.error(): Future = plaintext() + .setStatusCode(500) + .end(SOMETHING_WENT_WRONG) } } \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt index 8311474177e..7f981320192 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt @@ -1,15 +1,19 @@ package com.example.starter.handlers +import com.example.starter.helpers.PeriodicResolver +import io.vertx.core.Future import io.vertx.core.buffer.Buffer -import io.vertx.ext.web.RoutingContext +import io.vertx.core.http.HttpServerRequest class DefaultHandler : AbstractHandler() { - fun plaintext(ctx: RoutingContext) { - ctx.text().end(MESSAGE_BUFFER, NULL_HANDLER) - } + fun plaintext(req: HttpServerRequest): Future = req + .response().apply { + headers().setAll(PeriodicResolver.plaintext) + } + .end(MESSAGE_BUFFER) companion object { - private const val MESSAGE = "Hello, World!" - private val MESSAGE_BUFFER = Buffer.buffer(MESSAGE, "UTF-8") + const val MESSAGE: String = "Hello, World!" + val MESSAGE_BUFFER: Buffer = Buffer.buffer(MESSAGE, "UTF-8") } } diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/FortuneHandler.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/FortuneHandler.kt index 5e60c04cfeb..029026dab4c 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/FortuneHandler.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/FortuneHandler.kt @@ -2,56 +2,39 @@ package com.example.starter.handlers import com.example.starter.db.FortuneRepository import com.example.starter.models.Fortune -import htmlflow.HtmlFlow -import htmlflow.HtmlView -import io.vertx.ext.web.RoutingContext +import io.vertx.core.http.HttpServerRequest +import java.lang.Exception import org.apache.logging.log4j.kotlin.Logging class FortuneHandler(private val repository: FortuneRepository) : AbstractHandler() { - fun templateFortunes(ctx: RoutingContext) { + fun templateFortunes(req: HttpServerRequest) { repository .selectFortunes() - .onSuccess { - val updatedFortunes = it.plus(Fortune(0, "Additional fortune added at request time.")) - updatedFortunes.sort() - ctx.html().end(TEMPLATE.render(updatedFortunes), NULL_HANDLER) - } - .onFailure { - logger.error(it) { SOMETHING_WENT_WRONG } - ctx.error() + .onComplete { ar -> + when { + ar.succeeded() -> { + try { + val updatedFortunes = ar.result().plus(Fortune(0, "Additional fortune added at request time.")) + updatedFortunes.sort() + + val html = renderFortunes(updatedFortunes) + req.html().end(html) + } catch (ex: Exception) { + logger.error(SOMETHING_WENT_WRONG, ex) + req.error() + } + } + else -> { + logger.error(SOMETHING_WENT_WRONG, ar.cause()) + req.error() + } + } } } - companion object : Logging { - private val TEMPLATE: HtmlView = HtmlFlow - .view { page -> - page - .html() - .head() - .title() - .text("Fortunes") - .`__`() // title - .`__`() // head - .body() - .table() - .tr() - .th().text("id").`__`() - .th().text("message").`__`() - .`__`() // tr - .dynamic> { container, fortunes -> - fortunes.forEach { - container - .tr() - .td().text(it.id.toString()).`__`() - .td().text(it.message).`__`() - .`__`() // tr - } - } - .`__`() // table - .`__`() // body - .`__`() // html - } - .setIndented(false) - .threadSafe() + private companion object : Logging { + private fun renderFortunes(fortunes: Array): String { + throw NotImplementedError("Not implemented") + } } -} \ No newline at end of file +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/MessageHandler.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/MessageHandler.kt index 1fa432ef313..0a91afea21e 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/MessageHandler.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/MessageHandler.kt @@ -1,15 +1,20 @@ package com.example.starter.handlers +import com.example.starter.helpers.PeriodicResolver import com.example.starter.models.Message import com.example.starter.utils.serialize -import io.vertx.ext.web.RoutingContext +import io.vertx.core.Future +import io.vertx.core.http.HttpServerRequest class MessageHandler : AbstractHandler() { - fun readDefaultMessage(ctx: RoutingContext) { - ctx.json().end(DEFAULT_MESSAGE.serialize(), NULL_HANDLER) - } + fun readDefaultMessage(req: HttpServerRequest): Future = req + .response().apply { + headers().setAll(PeriodicResolver.json) + } + .end(Message(MESSAGE).serialize()) companion object { - private val DEFAULT_MESSAGE = Message("Hello, World!") + const val MESSAGE: String = "Hello, World!" + val DEFAULT_MESSAGE = Message(MESSAGE) } } diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/WorldHandler.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/WorldHandler.kt index 1226361d71b..c8152dda51f 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/WorldHandler.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/WorldHandler.kt @@ -2,55 +2,58 @@ package com.example.starter.handlers import com.example.starter.db.WorldRepository import com.example.starter.utils.serialize -import io.vertx.ext.web.RoutingContext +import io.vertx.core.http.HttpServerRequest import org.apache.logging.log4j.kotlin.Logging class WorldHandler(private val repository: WorldRepository) : AbstractHandler() { - fun readRandomWorld(ctx: RoutingContext) { + fun readRandomWorld(req: HttpServerRequest) { repository .selectRandomWorld() - .onSuccess { - ctx.json().end(it.serialize(), NULL_HANDLER) - } - .onFailure { - logger.error(it) { SOMETHING_WENT_WRONG } - ctx.error() + .onComplete { ar -> + when { + ar.succeeded() -> req.json().end(ar.result().serialize()) + else -> { + logger.error(SOMETHING_WENT_WRONG, ar.cause()) + req.error() + } + } } } - fun readRandomWorlds(ctx: RoutingContext) { - val queries = ctx.queries() + fun readRandomWorlds(req: HttpServerRequest) { repository - .selectRandomWorlds(queries) - .onSuccess { - ctx.json().end(it.serialize(), NULL_HANDLER) - } - .onFailure { - logger.error(it) { SOMETHING_WENT_WRONG } - ctx.error() + .selectRandomWorlds(req.queries()) + .onComplete { ar -> + when { + ar.succeeded() -> req.json().end(ar.result().serialize()) + else -> { + logger.error(SOMETHING_WENT_WRONG, ar.cause()) + req.error() + } + } } } - fun updateRandomWorlds(ctx: RoutingContext) { - val queries = ctx.queries() + fun updateRandomWorlds(req: HttpServerRequest) { repository - .updateRandomWorlds(queries) - .onSuccess { - ctx.json().end(it.serialize(), NULL_HANDLER) - } - .onFailure { - logger.error(it) { SOMETHING_WENT_WRONG } - ctx.error() + .updateRandomWorlds(req.queries()) + .onComplete { ar -> + when { + ar.succeeded() -> req.json().end(ar.result().serialize()) + else -> { + logger.error(SOMETHING_WENT_WRONG, ar.cause()) + req.error() + } + } } } - companion object : Logging { + private companion object : Logging { private const val QUERIES_PARAM_NAME = "queries" @Suppress("NOTHING_TO_INLINE") - private inline fun RoutingContext.queries(): Int { - val queriesParam = this.request().getParam(QUERIES_PARAM_NAME) - return queriesParam?.toIntOrNull()?.coerceIn(1, 500) ?: 1 - } + private inline fun HttpServerRequest.queries(): Int = getParam(QUERIES_PARAM_NAME) + ?.toIntOrNull() + ?.coerceIn(1, 500) ?: 1 } } \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/BufferOutputStream.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/BufferOutputStream.kt similarity index 52% rename from frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/BufferOutputStream.kt rename to frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/BufferOutputStream.kt index d82b31fb6ee..162feef9cd6 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/BufferOutputStream.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/BufferOutputStream.kt @@ -1,7 +1,8 @@ -package com.example.starter.io +package com.example.starter.helpers import io.netty.buffer.ByteBuf import io.vertx.core.buffer.Buffer +import io.vertx.core.internal.buffer.BufferInternal import io.vertx.core.json.JsonArray import io.vertx.core.json.JsonObject import java.io.IOException @@ -9,8 +10,8 @@ import java.io.OutputStream import java.nio.ByteBuffer import java.nio.charset.Charset -class BufferOutputStream(initialSizeHint: Int = 0) : Buffer, OutputStream() { - private val buffer: Buffer = Buffer.buffer(initialSizeHint) +class BufferOutputStream(initialSizeHint: Int = 256) : BufferInternal, OutputStream() { + private val buffer: BufferInternal = BufferInternal.buffer(initialSizeHint) @Throws(IOException::class) override fun write(b: Int) { @@ -27,23 +28,15 @@ class BufferOutputStream(initialSizeHint: Int = 0) : Buffer, OutputStream() { buffer.appendBytes(bytes, offset, len) } - override fun toString(enc: String?): String { + override fun toString(enc: String): String { return buffer.toString(enc) } - override fun toString(enc: Charset?): String { + override fun toString(enc: Charset): String { return buffer.toString(enc) } - override fun writeToBuffer(other: Buffer?) { - buffer.writeToBuffer(other) - } - - override fun readFromBuffer(pos: Int, other: Buffer?): Int { - return buffer.readFromBuffer(pos, other) - } - - override fun copy(): Buffer { + override fun copy(): BufferInternal { return buffer.copy() } @@ -91,10 +84,18 @@ class BufferOutputStream(initialSizeHint: Int = 0) : Buffer, OutputStream() { return buffer.getDouble(pos) } + override fun getDoubleLE(pos: Int): Double { + return buffer.getDoubleLE(pos) + } + override fun getFloat(pos: Int): Float { return buffer.getFloat(pos) } + override fun getFloatLE(pos: Int): Float { + return buffer.getFloatLE(pos) + } + override fun getShort(pos: Int): Short { return buffer.getShort(pos) } @@ -135,19 +136,19 @@ class BufferOutputStream(initialSizeHint: Int = 0) : Buffer, OutputStream() { return buffer.getBytes(start, end) } - override fun getBytes(dst: ByteArray?): Buffer { + override fun getBytes(dst: ByteArray): Buffer { return buffer.getBytes(dst) } - override fun getBytes(dst: ByteArray?, dstIndex: Int): Buffer { + override fun getBytes(dst: ByteArray, dstIndex: Int): Buffer { return buffer.getBytes(dst, dstIndex) } - override fun getBytes(start: Int, end: Int, dst: ByteArray?): Buffer { + override fun getBytes(start: Int, end: Int, dst: ByteArray): Buffer { return buffer.getBytes(start, end, dst) } - override fun getBytes(start: Int, end: Int, dst: ByteArray?, dstIndex: Int): Buffer { + override fun getBytes(start: Int, end: Int, dst: ByteArray, dstIndex: Int): Buffer { return buffer.getBytes(start, end, dst, dstIndex) } @@ -155,7 +156,7 @@ class BufferOutputStream(initialSizeHint: Int = 0) : Buffer, OutputStream() { return buffer.getBuffer(start, end) } - override fun getString(start: Int, end: Int, enc: String?): String { + override fun getString(start: Int, end: Int, enc: String): String { return buffer.getString(start, end, enc) } @@ -163,183 +164,199 @@ class BufferOutputStream(initialSizeHint: Int = 0) : Buffer, OutputStream() { return buffer.getString(start, end) } - override fun appendBuffer(buff: Buffer?): Buffer { - return buffer.appendBuffer(buff) + override fun appendBuffer(b: Buffer): BufferInternal { + return buffer.appendBuffer(b) } - override fun appendBuffer(buff: Buffer?, offset: Int, len: Int): Buffer { - return buffer.appendBuffer(buff, offset, len) + override fun appendBuffer(b: Buffer, offset: Int, len: Int): BufferInternal { + return buffer.appendBuffer(b, offset, len) } - override fun appendBytes(bytes: ByteArray?): Buffer { + override fun appendBytes(bytes: ByteArray): BufferInternal { return buffer.appendBytes(bytes) } - override fun appendBytes(bytes: ByteArray?, offset: Int, len: Int): Buffer { + override fun appendBytes(bytes: ByteArray, offset: Int, len: Int): BufferInternal { return buffer.appendBytes(bytes, offset, len) } - override fun appendByte(b: Byte): Buffer { + override fun appendByte(b: Byte): BufferInternal { return buffer.appendByte(b) } - override fun appendUnsignedByte(b: Short): Buffer { + override fun appendUnsignedByte(b: Short): BufferInternal { return buffer.appendUnsignedByte(b) } - override fun appendInt(i: Int): Buffer { + override fun appendInt(i: Int): BufferInternal { return buffer.appendInt(i) } - override fun appendIntLE(i: Int): Buffer { + override fun appendIntLE(i: Int): BufferInternal { return buffer.appendIntLE(i) } - override fun appendUnsignedInt(i: Long): Buffer { + override fun appendUnsignedInt(i: Long): BufferInternal { return buffer.appendUnsignedInt(i) } - override fun appendUnsignedIntLE(i: Long): Buffer { + override fun appendUnsignedIntLE(i: Long): BufferInternal { return buffer.appendUnsignedIntLE(i) } - override fun appendMedium(i: Int): Buffer { + override fun appendMedium(i: Int): BufferInternal { return buffer.appendMedium(i) } - override fun appendMediumLE(i: Int): Buffer { + override fun appendMediumLE(i: Int): BufferInternal { return buffer.appendMediumLE(i) } - override fun appendLong(l: Long): Buffer { + override fun appendLong(l: Long): BufferInternal { return buffer.appendLong(l) } - override fun appendLongLE(l: Long): Buffer { + override fun appendLongLE(l: Long): BufferInternal { return buffer.appendLongLE(l) } - override fun appendShort(s: Short): Buffer { + override fun appendShort(s: Short): BufferInternal { return buffer.appendShort(s) } - override fun appendShortLE(s: Short): Buffer { + override fun appendShortLE(s: Short): BufferInternal { return buffer.appendShortLE(s) } - override fun appendUnsignedShort(s: Int): Buffer { + override fun appendUnsignedShort(s: Int): BufferInternal { return buffer.appendUnsignedShort(s) } - override fun appendUnsignedShortLE(s: Int): Buffer { + override fun appendUnsignedShortLE(s: Int): BufferInternal { return buffer.appendUnsignedShortLE(s) } - override fun appendFloat(f: Float): Buffer { + override fun appendFloat(f: Float): BufferInternal { return buffer.appendFloat(f) } - override fun appendDouble(d: Double): Buffer { + override fun appendFloatLE(f: Float): BufferInternal { + return buffer.appendFloatLE(f) + } + + override fun appendDouble(d: Double): BufferInternal { return buffer.appendDouble(d) } - override fun appendString(str: String?, enc: String?): Buffer { + override fun appendDoubleLE(d: Double): BufferInternal { + return buffer.appendDoubleLE(d) + } + + override fun appendString(str: String, enc: String): BufferInternal { return buffer.appendString(str, enc) } - override fun appendString(str: String?): Buffer { + override fun appendString(str: String): BufferInternal { return buffer.appendString(str) } - override fun setByte(pos: Int, b: Byte): Buffer { + override fun setByte(pos: Int, b: Byte): BufferInternal { return buffer.setByte(pos, b) } - override fun setUnsignedByte(pos: Int, b: Short): Buffer { + override fun setUnsignedByte(pos: Int, b: Short): BufferInternal { return buffer.setUnsignedByte(pos, b) } - override fun setInt(pos: Int, i: Int): Buffer { + override fun setInt(pos: Int, i: Int): BufferInternal { return buffer.setInt(pos, i) } - override fun setIntLE(pos: Int, i: Int): Buffer { + override fun setIntLE(pos: Int, i: Int): BufferInternal { return buffer.setIntLE(pos, i) } - override fun setUnsignedInt(pos: Int, i: Long): Buffer { + override fun setUnsignedInt(pos: Int, i: Long): BufferInternal { return buffer.setUnsignedInt(pos, i) } - override fun setUnsignedIntLE(pos: Int, i: Long): Buffer { + override fun setUnsignedIntLE(pos: Int, i: Long): BufferInternal { return buffer.setUnsignedIntLE(pos, i) } - override fun setMedium(pos: Int, i: Int): Buffer { + override fun setMedium(pos: Int, i: Int): BufferInternal { return buffer.setMedium(pos, i) } - override fun setMediumLE(pos: Int, i: Int): Buffer { + override fun setMediumLE(pos: Int, i: Int): BufferInternal { return buffer.setMediumLE(pos, i) } - override fun setLong(pos: Int, l: Long): Buffer { + override fun setLong(pos: Int, l: Long): BufferInternal { return buffer.setLong(pos, l) } - override fun setLongLE(pos: Int, l: Long): Buffer { + override fun setLongLE(pos: Int, l: Long): BufferInternal { return buffer.setLongLE(pos, l) } - override fun setDouble(pos: Int, d: Double): Buffer { + override fun setDouble(pos: Int, d: Double): BufferInternal { return buffer.setDouble(pos, d) } - override fun setFloat(pos: Int, f: Float): Buffer { + override fun setDoubleLE(pos: Int, d: Double): BufferInternal { + return buffer.setDoubleLE(pos, d) + } + + override fun setFloat(pos: Int, f: Float): BufferInternal { return buffer.setFloat(pos, f) } - override fun setShort(pos: Int, s: Short): Buffer { + override fun setFloatLE(pos: Int, f: Float): BufferInternal { + return buffer.setFloatLE(pos, f) + } + + override fun setShort(pos: Int, s: Short): BufferInternal { return buffer.setShort(pos, s) } - override fun setShortLE(pos: Int, s: Short): Buffer { + override fun setShortLE(pos: Int, s: Short): BufferInternal { return buffer.setShortLE(pos, s) } - override fun setUnsignedShort(pos: Int, s: Int): Buffer { + override fun setUnsignedShort(pos: Int, s: Int): BufferInternal { return buffer.setUnsignedShort(pos, s) } - override fun setUnsignedShortLE(pos: Int, s: Int): Buffer { + override fun setUnsignedShortLE(pos: Int, s: Int): BufferInternal { return buffer.setUnsignedShortLE(pos, s) } - override fun setBuffer(pos: Int, b: Buffer?): Buffer { + override fun setBuffer(pos: Int, b: Buffer): BufferInternal { return buffer.setBuffer(pos, b) } - override fun setBuffer(pos: Int, b: Buffer?, offset: Int, len: Int): Buffer { + override fun setBuffer(pos: Int, b: Buffer, offset: Int, len: Int): BufferInternal { return buffer.setBuffer(pos, b, offset, len) } - override fun setBytes(pos: Int, b: ByteBuffer?): Buffer { + override fun setBytes(pos: Int, b: ByteBuffer): BufferInternal { return buffer.setBytes(pos, b) } - override fun setBytes(pos: Int, b: ByteArray?): Buffer { + override fun setBytes(pos: Int, b: ByteArray): BufferInternal { return buffer.setBytes(pos, b) } - override fun setBytes(pos: Int, b: ByteArray?, offset: Int, len: Int): Buffer { + override fun setBytes(pos: Int, b: ByteArray, offset: Int, len: Int): BufferInternal { return buffer.setBytes(pos, b, offset, len) } - override fun setString(pos: Int, str: String?): Buffer { + override fun setString(pos: Int, str: String): BufferInternal { return buffer.setString(pos, str) } - override fun setString(pos: Int, str: String?, enc: String?): Buffer { + override fun setString(pos: Int, str: String, enc: String): BufferInternal { return buffer.setString(pos, str, enc) } @@ -347,16 +364,23 @@ class BufferOutputStream(initialSizeHint: Int = 0) : Buffer, OutputStream() { return buffer.length() } - override fun slice(): Buffer { + override fun slice(): BufferInternal { return buffer.slice() } - override fun slice(start: Int, end: Int): Buffer { + override fun slice(start: Int, end: Int): BufferInternal { return buffer.slice(start, end) } - @Deprecated("Deprecated in Java") override fun getByteBuf(): ByteBuf { return buffer.byteBuf } + + override fun writeToBuffer(b: Buffer) { + return buffer.writeToBuffer(b) + } + + override fun readFromBuffer(pos: Int, b: Buffer): Int { + return buffer.readFromBuffer(pos, b) + } } \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/PeriodicResolver.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/PeriodicResolver.kt new file mode 100644 index 00000000000..4e08f883e23 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/PeriodicResolver.kt @@ -0,0 +1,61 @@ +package com.example.starter.helpers + +import com.example.starter.handlers.DefaultHandler +import com.example.starter.handlers.MessageHandler +import com.example.starter.utils.serialize +import io.vertx.core.MultiMap +import io.vertx.core.Vertx +import io.vertx.core.http.HttpHeaders +import java.time.Instant +import java.time.ZoneOffset +import java.time.format.DateTimeFormatter + +private val FORMATTER = DateTimeFormatter.RFC_1123_DATE_TIME.withZone(ZoneOffset.UTC) +private val SERVER: CharSequence = HttpHeaders.createOptimized(Properties.SERVER_NAME) +private val CONTENT_TYPE_TEXT_PLAIN: CharSequence = HttpHeaders.createOptimized("text/plain") +private val CONTENT_TYPE_APPLICATION_JSON: CharSequence = HttpHeaders.createOptimized("application/json") +private val PLAINTEXT_CONTENT_LENGTH: CharSequence= HttpHeaders.createOptimized(DefaultHandler.MESSAGE.length.toString()) +private val JSON_CONTENT_LENGTH: CharSequence = HttpHeaders.createOptimized(MessageHandler.DEFAULT_MESSAGE.serialize().length().toString()) + +@Suppress("NOTHING_TO_INLINE") +object PeriodicResolver { + @Volatile + var current: CharSequence = next() + private set + + @Volatile + var plaintext: MultiMap = nextPlaintext() + private set + + @Volatile + var json: MultiMap = nextJson() + private set + + fun init(vertx: Vertx) { + vertx.setPeriodic(1_000L) { + current = next() + plaintext = nextPlaintext() + json = nextJson() + } + } + + private fun next(): CharSequence = HttpHeaders.createOptimized( + FORMATTER.format(Instant.now()) + ) + + private fun nextPlaintext(): MultiMap = HttpHeaders + .headers() + .add(HttpHeaders.SERVER, SERVER) + .add(HttpHeaders.DATE, current) + .add(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_TEXT_PLAIN) + .add(HttpHeaders.CONTENT_LENGTH, PLAINTEXT_CONTENT_LENGTH) + .copy(false) + + private fun nextJson(): MultiMap = HttpHeaders + .headers() + .add(HttpHeaders.SERVER, SERVER) + .add(HttpHeaders.DATE, current) + .add(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_APPLICATION_JSON) + .add(HttpHeaders.CONTENT_LENGTH, JSON_CONTENT_LENGTH) + .copy(false) +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/Properties.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/Properties.kt new file mode 100644 index 00000000000..ca72dd8a61c --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/Properties.kt @@ -0,0 +1,171 @@ +package com.example.starter.helpers + +import io.netty.util.internal.SystemPropertyUtil +import io.vertx.core.impl.cpu.CpuCoreSensor +import io.vertx.core.tracing.TracingPolicy +import io.vertx.kotlin.core.http.httpServerOptionsOf +import io.vertx.kotlin.pgclient.pgConnectOptionsOf + +object Properties { + + /** + * The server name (used in headers and logging). + * Default: `Vert.x-Web` + */ + val SERVER_NAME: String = SystemPropertyUtil.get("tfb.serverName", "Vert.x-Web") + + /** + * Type of verticle to deploy. + * Default: all ([com.example.starter.ServerVerticle]) + */ + val TYPE: String = SystemPropertyUtil.get("tfb.type", "all") + + /** + * Number of event loop threads. + * Default: [io.vertx.core.impl.cpu.CpuCoreSensor.availableProcessors] + */ + val EVENT_LOOP_POOL_SIZE: Int = SystemPropertyUtil.getInt("tfb.eventLoopPoolSize", CpuCoreSensor.availableProcessors()) + + /** + * Whether metrics are enabled. + * Default: Reverse of `vertx.disableMetrics` (defaults to false) + */ + val METRICS_ENABLED: Boolean = SystemPropertyUtil.getBoolean("vertx.disableMetrics", false).not() + + /** + * Port the HTTP server listens on. + * Default: 8080 (tfb.http.port) + */ + val HTTP_PORT: Int = SystemPropertyUtil.getInt("tfb.http.port", 8080) + + /** + * Size of TCP send buffer for HTTP connections, in bytes. + * Default: 32768 (tfb.http.sendBufferSize) + */ + val HTTP_SEND_BUFFER_SIZE: Int = SystemPropertyUtil.getInt("tfb.http.sendBufferSize", 16 * 1024) + + /** + * Size of TCP receive buffer for HTTP connections, in bytes. + * Default: 32768 (tfb.http.receiveBufferSize) + */ + val HTTP_RECEIVE_BUFFER_SIZE: Int = SystemPropertyUtil.getInt("tfb.http.receiveBufferSize", 16 * 1024) + + /** + * Enables TCP Fast Open on the HTTP server. + * Default: true (tfb.http.tcpFastOpen) + */ + val HTTP_TCP_FASTOPEN: Boolean = SystemPropertyUtil.getBoolean("tfb.http.tcpFastOpen", true) + + /** + * Enables TCP_NODELAY (disables Nagle) on HTTP connections. + * Default: true (tfb.http.tcpNoDelay) + */ + val HTTP_TCP_NODELAY: Boolean = SystemPropertyUtil.getBoolean("tfb.http.tcpNoDelay", true) + + /** + * Idle timeout for HTTP connections in seconds. + * 0 disables idle timeout. + * Default: 0 (tfb.http.idleTimeout) + */ + val HTTP_IDLE_TIMEOUT: Int = SystemPropertyUtil.getInt("tfb.http.idleTimeout", 0) + + /** + * Enables SO_REUSEADDR on the HTTP server socket. + * Default: true (tfb.http.reuseAddress) + */ + val HTTP_REUSE_ADDRESS: Boolean = SystemPropertyUtil.getBoolean("tfb.http.reuseAddress", true) + + /** + * Enables SO_REUSEPORT on the HTTP server socket. + * Default: true (tfb.http.reusePort) + */ + val HTTP_REUSE_PORT: Boolean = SystemPropertyUtil.getBoolean("tfb.http.reusePort", true) + + /** + * Size of the TCP accept backlog for the HTTP server. + * Default: 8192 (tfb.http.acceptBacklog) + */ + val HTTP_ACCEPT_BACKLOG: Int = SystemPropertyUtil.getInt("tfb.http.acceptBacklog", 8192) + + /** + * PostgreSQL username used for connections. + * Default: benchmarkdbuser (tfb.pg.user) + */ + val PG_USER: String = SystemPropertyUtil.get("tfb.pg.user", "benchmarkdbuser") + + /** + * PostgreSQL password used for connections. + * Default: benchmarkdbpass (tfb.pg.password) + */ + val PG_PASSWORD: String = SystemPropertyUtil.get("tfb.pg.password", "benchmarkdbpass") + + /** + * PostgreSQL host used for connections. + * Default: tfb.pgHostOverride system property, otherwise "tfb-database". + * Property: tfb.pg.host + */ + val PG_HOST: String = SystemPropertyUtil.get("tfb.pg.host", System.getProperty("tfb.pgHostOverride") ?: "tfb-database") + + /** + * PostgreSQL port used for connections. + * Default: 5432 (tfb.pg.port) + */ + val PG_PORT: Int = SystemPropertyUtil.getInt("tfb.pg.port", 5432) + + /** + * PostgreSQL database name used for connections. + * Default: hello_world (tfb.pg.database) + */ + val PG_DATABASE: String = SystemPropertyUtil.get("tfb.pg.database", "hello_world") + + /** + * Enables prepared statement caching on the PostgreSQL client. + * Default: true (tfb.pg.cachePreparedStatements) + */ + val PG_CACHE_PREPARED_STATEMENTS: Boolean = SystemPropertyUtil.getBoolean("tfb.pg.cachePreparedStatements", true) + + /** + * Maximum size of the prepared statement cache. + * Default: 1024 (tfb.pg.preparedStatementCacheMaxSize) + */ + val PG_PREPARED_STATEMENT_CACHE_MAX_SIZE: Int = + SystemPropertyUtil.getInt("tfb.pg.preparedStatementCacheMaxSize", 1024) + + /** + * Max number of in-flight pipelined requests per connection. + * Default: 1024 (tfb.pg.pipeliningLimit) + */ + val PG_PIPELINING_LIMIT: Int = SystemPropertyUtil.getInt("tfb.pg.pipeliningLimit", 1024) + + val HTTP by lazy { + httpServerOptionsOf( + port = HTTP_PORT, + sendBufferSize = HTTP_SEND_BUFFER_SIZE, + receiveBufferSize = HTTP_RECEIVE_BUFFER_SIZE, + tcpFastOpen = HTTP_TCP_FASTOPEN, + tcpNoDelay = HTTP_TCP_NODELAY, + idleTimeout = HTTP_IDLE_TIMEOUT, + reuseAddress = HTTP_REUSE_ADDRESS, + reusePort = HTTP_REUSE_PORT, + acceptBacklog = HTTP_ACCEPT_BACKLOG, + compressionSupported = false, + tracingPolicy = TracingPolicy.IGNORE, + http2ClearTextEnabled = false, + strictThreadMode = true, + ) + } + + val PG_CONNECT by lazy { + pgConnectOptionsOf( + user = PG_USER, + password = PG_PASSWORD, + host = PG_HOST, + port = PG_PORT, + database = PG_DATABASE, + cachePreparedStatements = PG_CACHE_PREPARED_STATEMENTS, + preparedStatementCacheMaxSize = PG_PREPARED_STATEMENT_CACHE_MAX_SIZE, + tracingPolicy = TracingPolicy.IGNORE, + pipeliningLimit = PG_PIPELINING_LIMIT + ) + } +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/JsonResource.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/JsonResource.kt deleted file mode 100644 index fbf355e66a9..00000000000 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/JsonResource.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.example.starter.io - -import io.vertx.core.json.JsonObject - -object JsonResource { - fun of(resource: String): JsonObject { - val classLoader = ClassLoader.getSystemClassLoader() - classLoader.getResourceAsStream(resource)?.use { input -> - val output = BufferOutputStream() - output.write(input.readAllBytes()) - return output.toJsonObject() - } - throw IllegalStateException("$resource not found") - } -} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Fortune.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Fortune.kt index 4b832526750..f9293258ed9 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Fortune.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Fortune.kt @@ -5,8 +5,8 @@ import com.dslplatform.json.JsonAttribute @CompiledJson class Fortune( - @JsonAttribute(nullable = false) val id: Int, - @JsonAttribute(nullable = false) val message: String + @field:JsonAttribute(nullable = false) val id: Int, + @field:JsonAttribute(nullable = false) val message: String, ) : Comparable { override fun compareTo(other: Fortune): Int { return message.compareTo(other.message) diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Message.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Message.kt index eb7fc6250a3..1953c10cfcb 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Message.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Message.kt @@ -4,4 +4,4 @@ import com.dslplatform.json.CompiledJson import com.dslplatform.json.JsonAttribute @CompiledJson -class Message(@JsonAttribute(nullable = false) val message: String) +class Message(@field:JsonAttribute(nullable = false) val message: String) diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/World.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/World.kt index 5011a2bb2e0..030f96ed314 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/World.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/World.kt @@ -5,10 +5,8 @@ import com.dslplatform.json.JsonAttribute @CompiledJson class World( - @JsonAttribute(nullable = false) val id: Int, - @JsonAttribute(nullable = false) var randomNumber: Int + @field:JsonAttribute(nullable = false) val id: Int, + @field:JsonAttribute(nullable = false) var randomNumber: Int, ) : Comparable { - override fun compareTo(other: World): Int { - return id.compareTo(other.id) - } + override fun compareTo(other: World): Int = id - other.id } diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/FutureExtensions.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/FutureExtensions.kt index 03d5a018575..1b9ce713000 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/FutureExtensions.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/FutureExtensions.kt @@ -1,14 +1,14 @@ package com.example.starter.utils -import io.vertx.core.CompositeFuture import io.vertx.core.Future -import java.util.concurrent.TimeUnit +import io.vertx.kotlin.coroutines.coAwait import kotlin.time.Duration - -inline fun CompositeFuture.array(): Array = Array(this.size()) { this.resultAt(it) } +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout @Suppress("NOTHING_TO_INLINE") -inline fun > T.block(duration: Duration): R = this - .toCompletionStage() - .toCompletableFuture() - .get(duration.inWholeMilliseconds, TimeUnit.MILLISECONDS) \ No newline at end of file +inline fun > T.block(duration: Duration): R = runBlocking { + withTimeout(duration) { + coAwait() + } +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/JsonExtensions.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/JsonExtensions.kt index 264be5a7323..f7793af1509 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/JsonExtensions.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/JsonExtensions.kt @@ -2,17 +2,16 @@ package com.example.starter.utils import com.dslplatform.json.DslJson import com.dslplatform.json.runtime.Settings -import com.example.starter.io.BufferOutputStream +import com.example.starter.helpers.BufferOutputStream import io.vertx.core.buffer.Buffer val DSL_JSON: DslJson = DslJson( Settings.withRuntime() .includeServiceLoader() - .useStringValuesCache(DslJson.SimpleStringCache()) ) @Suppress("NOTHING_TO_INLINE") -inline fun T.serialize(initialSizeHint: Int = 0): Buffer { +inline fun T.serialize(initialSizeHint: Int = 128): Buffer { val output = BufferOutputStream(initialSizeHint) DSL_JSON.serialize(this, output) return output diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/PeriodicDateResolver.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/PeriodicDateResolver.kt deleted file mode 100644 index 23786587569..00000000000 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/PeriodicDateResolver.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.example.starter.utils - -import io.vertx.core.Vertx -import io.vertx.core.http.HttpHeaders -import java.time.ZonedDateTime -import java.time.format.DateTimeFormatter - -object PeriodicDateResolver { - var current: CharSequence = next() - - fun init(vertx: Vertx) { - vertx.setPeriodic(1000L) { current = next() } - } - - @Suppress("NOTHING_TO_INLINE") - private inline fun next(): CharSequence = HttpHeaders.createOptimized( - DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now()) - ) -} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/RowSetExtensions.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/RowSetExtensions.kt index 3959ba8d9a0..7f7fcc84ab4 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/RowSetExtensions.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/RowSetExtensions.kt @@ -5,11 +5,8 @@ import io.vertx.sqlclient.RowSet // This extension relies on the assumption the mapper never returns null, as it is defined. Otherwise, // we prevent the overhead from having to do another iteration over the loop for a `filterNotNull` check. -@Suppress("UNCHECKED_CAST") +@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") inline fun RowSet.mapToArray(mapper: (Row) -> U): Array { - val arr = arrayOfNulls(this.size()) - val iterator = this.iterator() - var index = 0 - while (iterator.hasNext()) arr[index++] = mapper(iterator.next()) - return arr as Array + val iterator = iterator() + return Array(size()) { mapper(iterator.next()) } } diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/ThrowableExtensions.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/ThrowableExtensions.kt index 00cf1463297..3f31f9720a9 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/ThrowableExtensions.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/ThrowableExtensions.kt @@ -7,10 +7,8 @@ import java.net.SocketException const val CONNECTION_RESET_MESSAGE = "Connection reset" @Suppress("NOTHING_TO_INLINE") -inline fun Throwable.isConnectionReset(): Boolean { - return when { - this is NativeIoException && this.expectedErr() == Errors.ERRNO_ECONNRESET_NEGATIVE -> true - this is SocketException && this.message == CONNECTION_RESET_MESSAGE -> true - else -> false - } +inline fun Throwable.isConnectionReset(): Boolean = when (this) { + is NativeIoException if this.expectedErr() == Errors.ERRNO_ECONNRESET_NEGATIVE -> true + is SocketException if this.message == CONNECTION_RESET_MESSAGE -> true + else -> false } diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/http-server-options.json b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/http-server-options.json deleted file mode 100644 index a790bc93043..00000000000 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/http-server-options.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "port": 8080, - "tcpFastOpen": true, - "receiveBufferSize": 262144, - "sendBufferSize": 262144 -} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/pg-connect-options.json b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/pg-connect-options.json deleted file mode 100644 index 3cf43317687..00000000000 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/pg-connect-options.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "user": "benchmarkdbuser", - "password": "benchmarkdbpass", - "host": "tfb-database", - "port": 5432, - "database": "hello_world", - "cachePreparedStatements": true, - "preparedStatementCacheMaxSize": 1024, - "pipeliningLimit": 100000, - "receiveBufferSize": 262144, - "sendBufferSize": 262144 -} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson-postgresql.dockerfile b/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson-postgresql.dockerfile index 50152d8df30..e75d7fbdb8a 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson-postgresql.dockerfile +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson-postgresql.dockerfile @@ -1,39 +1,56 @@ -FROM gradle:8.9-jdk21 as gradle +# --- Build stage with JDK 25 --- +FROM gradle:9.2-jdk25-corretto AS builder WORKDIR /vertx-web-kotlin-dsljson COPY src src +COPY buildSrc buildSrc COPY build.gradle.kts build.gradle.kts -COPY gradle.properties gradle.properties COPY settings.gradle.kts settings.gradle.kts +COPY gradle.properties gradle.properties +COPY gradle/libs.versions.toml gradle/libs.versions.toml + +RUN gradle shadowJar --no-daemon + +# --- Runtime stage using Amazon Corretto 25 --- +FROM amazoncorretto:25 + +WORKDIR /app -RUN gradle shadowJar +COPY --from=builder \ + /vertx-web-kotlin-dsljson/build/libs/vertx-web-kotlin-dsljson-benchmark-1.0.0-SNAPSHOT-fat.jar \ + vertx-web-kotlin-dsljson.jar EXPOSE 8080 CMD java \ - -server \ - -Xms2G \ - -Xmx2G \ - -XX:+AlwaysPreTouch \ - -XX:+UseParallelGC \ - -XX:InitialCodeCacheSize=512m \ - -XX:ReservedCodeCacheSize=512m \ - -XX:MaxInlineLevel=20 \ - -XX:+UseNUMA \ - -Djava.lang.Integer.IntegerCache.high=10000 \ - -Dvertx.disableMetrics=true \ - -Dvertx.disableH2c=true \ - -Dvertx.disableWebsockets=true \ - -Dvertx.flashPolicyHandler=false \ - -Dvertx.threadChecks=false \ - -Dvertx.disableContextTimings=true \ - -Dvertx.disableTCCL=true \ - -Dvertx.disableHttpHeadersValidation=true \ - -Dvertx.eventLoopPoolSize=$((`grep --count ^processor /proc/cpuinfo`)) \ - -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \ - -Dio.netty.buffer.checkBounds=false \ - -Dio.netty.buffer.checkAccessible=false \ - -Dtfb.hasDB=true \ - -jar \ - build/libs/vertx-web-kotlin-dsljson-benchmark-1.0.0-SNAPSHOT-fat.jar + -server \ + --enable-native-access=ALL-UNNAMED \ + --add-opens=java.base/java.lang=ALL-UNNAMED \ + --sun-misc-unsafe-memory-access=allow \ + -Xms2G \ + -Xmx2G \ + -XX:+AlwaysPreTouch \ + -XX:+UseParallelGC \ + -XX:InitialCodeCacheSize=512m \ + -XX:ReservedCodeCacheSize=512m \ + -XX:MaxInlineLevel=20 \ + -XX:+UseNUMA \ + -XX:-UseCodeCacheFlushing \ + -XX:AutoBoxCacheMax=10001 \ + -XX:+UseCompactObjectHeaders \ + -Djava.net.preferIPv4Stack=true \ + -Dvertx.disableMetrics=true \ + -Dvertx.disableWebsockets=true \ + -Dvertx.disableContextTimings=true \ + -Dvertx.cacheImmutableHttpResponseHeaders=true \ + -Dvertx.internCommonHttpRequestHeadersToLowerCase=true \ + -Dvertx.disableHttpHeadersValidation=true \ + -Dio.netty.noUnsafe=false \ + -Dio.netty.buffer.checkBounds=false \ + -Dio.netty.buffer.checkAccessible=false \ + -Dio.netty.leakDetection.level=disabled \ + -Dio.netty.iouring.ringSize=4096 \ + -Dio.netty.iouring.ringSize=16384 \ + -Dtfb.type=postgres \ + -jar /app/vertx-web-kotlin-dsljson.jar diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson.dockerfile b/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson.dockerfile index 568f19f79dd..d1548a76ae9 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson.dockerfile +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson.dockerfile @@ -1,39 +1,55 @@ -FROM gradle:8.9-jdk21 as gradle +# --- Build stage with JDK 25 --- +FROM gradle:9.2-jdk25-corretto AS builder WORKDIR /vertx-web-kotlin-dsljson COPY src src +COPY buildSrc buildSrc COPY build.gradle.kts build.gradle.kts -COPY gradle.properties gradle.properties COPY settings.gradle.kts settings.gradle.kts +COPY gradle.properties gradle.properties +COPY gradle/libs.versions.toml gradle/libs.versions.toml + +RUN gradle shadowJar --no-daemon + +# --- Runtime stage using Amazon Corretto 25 --- +FROM amazoncorretto:25 + +WORKDIR /app -RUN gradle shadowJar +COPY --from=builder \ + /vertx-web-kotlin-dsljson/build/libs/vertx-web-kotlin-dsljson-benchmark-1.0.0-SNAPSHOT-fat.jar \ + vertx-web-kotlin-dsljson.jar EXPOSE 8080 CMD java \ - -server \ - -Xms2G \ - -Xmx2G \ - -XX:+AlwaysPreTouch \ - -XX:+UseParallelGC \ - -XX:InitialCodeCacheSize=512m \ - -XX:ReservedCodeCacheSize=512m \ - -XX:MaxInlineLevel=20 \ - -XX:+UseNUMA \ - -Djava.lang.Integer.IntegerCache.high=10000 \ - -Dvertx.disableMetrics=true \ - -Dvertx.disableH2c=true \ - -Dvertx.disableWebsockets=true \ - -Dvertx.flashPolicyHandler=false \ - -Dvertx.threadChecks=false \ - -Dvertx.disableContextTimings=true \ - -Dvertx.disableTCCL=true \ - -Dvertx.disableHttpHeadersValidation=true \ - -Dvertx.eventLoopPoolSize=$((`grep --count ^processor /proc/cpuinfo`)) \ - -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \ - -Dio.netty.buffer.checkBounds=false \ - -Dio.netty.buffer.checkAccessible=false \ - -Dtfb.hasDB=false \ - -jar \ - build/libs/vertx-web-kotlin-dsljson-benchmark-1.0.0-SNAPSHOT-fat.jar + -server \ + --enable-native-access=ALL-UNNAMED \ + --add-opens=java.base/java.lang=ALL-UNNAMED \ + --sun-misc-unsafe-memory-access=allow \ + -Xms2G \ + -Xmx2G \ + -XX:+AlwaysPreTouch \ + -XX:+UseParallelGC \ + -XX:InitialCodeCacheSize=512m \ + -XX:ReservedCodeCacheSize=512m \ + -XX:MaxInlineLevel=20 \ + -XX:+UseNUMA \ + -XX:-UseCodeCacheFlushing \ + -XX:AutoBoxCacheMax=10001 \ + -XX:+UseCompactObjectHeaders \ + -Djava.net.preferIPv4Stack=true \ + -Dvertx.disableMetrics=true \ + -Dvertx.disableWebsockets=true \ + -Dvertx.disableContextTimings=true \ + -Dvertx.cacheImmutableHttpResponseHeaders=true \ + -Dvertx.internCommonHttpRequestHeadersToLowerCase=true \ + -Dvertx.disableHttpHeadersValidation=true \ + -Dio.netty.noUnsafe=false \ + -Dio.netty.buffer.checkBounds=false \ + -Dio.netty.buffer.checkAccessible=false \ + -Dio.netty.leakDetection.level=disabled \ + -Dio.netty.iouring.ringSize=16384 \ + -Dtfb.type=basic \ + -jar /app/vertx-web-kotlin-dsljson.jar diff --git a/frameworks/Kotlin/vertx-web-kotlinx/README.md b/frameworks/Kotlin/vertx-web-kotlinx/README.md index b9fe8d87eef..f3134cb1b35 100755 --- a/frameworks/Kotlin/vertx-web-kotlinx/README.md +++ b/frameworks/Kotlin/vertx-web-kotlinx/README.md @@ -2,7 +2,7 @@ Vert.x-Web in Kotlin with request handling implemented as much with official kotlinx libraries as possible. -Code is written from scratch to be as concise as possible with common code extracted into common (possibly inline) functions. SQL client implementation details and JVM Options are adapted referring to [the vertx-web portion](../../Java/vertx-web) and [the vertx portion](../../Java/vertx). All requests are handled in coroutines and suspend `await`s are used instead of future compositions. Compared to [the vertx-web-kotlin-coroutines portion](../vertx-web-kotlin-coroutines), besides adopting the Kotlinx libraries, this project simplifies the code by using more built-in Coroutine functions and avoids mutability as much as possible. JSON serialization is implemented with kotlinx.serialization and Fortunes with kotlinx.html. The benchmark is run on the latest LTS version of JVM, 21. +Code is written from scratch to be as concise as possible with common code extracted into common (possibly inline) functions. SQL client implementation details and JVM Options are adapted referring to [the vertx-web portion](../../Java/vertx-web) and [the vertx portion](../../Java/vertx). All requests are handled in coroutines and suspend `await`s are used instead of future compositions. Compared to [the vertx-web-kotlin-coroutines portion](../vertx-web-kotlin-coroutines), besides adopting the Kotlinx libraries, this project simplifies the code by using more built-in Coroutine functions and avoids mutability as much as possible. JSON serialization is implemented with kotlinx.serialization and Fortunes with kotlinx.html. The benchmark is run on the latest LTS version of JVM, 25. ## Test Type Implementation Source Code @@ -13,7 +13,6 @@ Code is written from scratch to be as concise as possible with common code extra * [PLAINTEXT](src/main/kotlin/MainVerticle.kt) * [DB](src/main/kotlin/MainVerticle.kt) * [QUERY](src/main/kotlin/MainVerticle.kt) -* [CACHED QUERY](src/main/kotlin/MainVerticle.kt) * [UPDATE](src/main/kotlin/MainVerticle.kt) * [FORTUNES](src/main/kotlin/MainVerticle.kt) @@ -48,10 +47,6 @@ http://localhost:8080/db http://localhost:8080/query?queries= -### CACHED QUERY - -http://localhost:8080/cached_query?queries= - ### UPDATE http://localhost:8080/update?queries= diff --git a/frameworks/Kotlin/vertx-web-kotlinx/benchmark_config.json b/frameworks/Kotlin/vertx-web-kotlinx/benchmark_config.json index 970a9f80b46..826470e61f9 100755 --- a/frameworks/Kotlin/vertx-web-kotlinx/benchmark_config.json +++ b/frameworks/Kotlin/vertx-web-kotlinx/benchmark_config.json @@ -40,7 +40,7 @@ "database_os": "Linux", "display_name": "vertx-web-kotlinx-postgresql", "notes": "", - "versus": "vertx-web" + "versus": "vertx-web-postgres" } } ] diff --git a/frameworks/Kotlin/vertx-web-kotlinx/build.gradle.kts b/frameworks/Kotlin/vertx-web-kotlinx/build.gradle.kts index 2e0035ab3e7..57ecdf9e59a 100644 --- a/frameworks/Kotlin/vertx-web-kotlinx/build.gradle.kts +++ b/frameworks/Kotlin/vertx-web-kotlinx/build.gradle.kts @@ -3,7 +3,7 @@ tasks.wrapper { } plugins { - val kotlinVersion = "2.0.21" + val kotlinVersion = "2.3.0-RC2" kotlin("jvm") version kotlinVersion kotlin("plugin.serialization") version kotlinVersion application @@ -13,29 +13,27 @@ repositories { mavenCentral() } -val vertxVersion = "4.5.10" -val kotlinxSerializationVersion = "1.7.3" +val vertxVersion = "5.0.5" +val kotlinxSerializationVersion = "1.9.0" dependencies { implementation(platform("io.vertx:vertx-stack-depchain:$vertxVersion")) implementation("io.vertx:vertx-web") implementation("io.vertx:vertx-pg-client") - implementation("io.netty", "netty-transport-native-epoll", classifier = "linux-x86_64") + //implementation("io.netty", "netty-transport-native-epoll", classifier = "linux-x86_64") + implementation("io.netty", "netty-transport-native-io_uring", classifier = "linux-x86_64") implementation("io.vertx:vertx-lang-kotlin") implementation("io.vertx:vertx-lang-kotlin-coroutines") - runtimeOnly("io.vertx:vertx-io_uring-incubator") - // This dependency has to be added for io_uring to work. - runtimeOnly("io.netty.incubator:netty-incubator-transport-native-io_uring:0.0.25.Final:linux-x86_64") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-io:$kotlinxSerializationVersion") - implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.5.4") + implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.8.2") - implementation("org.jetbrains.kotlinx:kotlinx-html:0.11.0") - //implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") // the latest version is 0.6.1 + implementation("org.jetbrains.kotlinx:kotlinx-html:0.12.0") + implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1") } -kotlin.jvmToolchain(21) +kotlin.jvmToolchain(25) application.mainClass.set("MainKt") diff --git a/frameworks/Kotlin/vertx-web-kotlinx/gradle/wrapper/gradle-wrapper.jar b/frameworks/Kotlin/vertx-web-kotlinx/gradle/wrapper/gradle-wrapper.jar index a4b76b9530d..f8e1ee3125f 100644 Binary files a/frameworks/Kotlin/vertx-web-kotlinx/gradle/wrapper/gradle-wrapper.jar and b/frameworks/Kotlin/vertx-web-kotlinx/gradle/wrapper/gradle-wrapper.jar differ diff --git a/frameworks/Kotlin/vertx-web-kotlinx/gradle/wrapper/gradle-wrapper.properties b/frameworks/Kotlin/vertx-web-kotlinx/gradle/wrapper/gradle-wrapper.properties index 79eb9d003fe..4eac4a84cc3 100644 --- a/frameworks/Kotlin/vertx-web-kotlinx/gradle/wrapper/gradle-wrapper.properties +++ b/frameworks/Kotlin/vertx-web-kotlinx/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/frameworks/Kotlin/vertx-web-kotlinx/gradlew b/frameworks/Kotlin/vertx-web-kotlinx/gradlew index f5feea6d6b1..adff685a034 100755 --- a/frameworks/Kotlin/vertx-web-kotlinx/gradlew +++ b/frameworks/Kotlin/vertx-web-kotlinx/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -173,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -206,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/frameworks/Kotlin/vertx-web-kotlinx/gradlew.bat b/frameworks/Kotlin/vertx-web-kotlinx/gradlew.bat index 9d21a21834d..c4bdd3ab8e3 100644 --- a/frameworks/Kotlin/vertx-web-kotlinx/gradlew.bat +++ b/frameworks/Kotlin/vertx-web-kotlinx/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/Main.kt b/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/Main.kt index 987c22162b3..52864f79f16 100644 --- a/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/Main.kt +++ b/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/Main.kt @@ -3,9 +3,11 @@ import io.vertx.core.impl.cpu.CpuCoreSensor import io.vertx.kotlin.core.deploymentOptionsOf import io.vertx.kotlin.core.vertxOptionsOf import io.vertx.kotlin.coroutines.coAwait +import java.util.function.Supplier import java.util.logging.Logger const val SERVER_NAME = "Vert.x-Web Kotlinx Benchmark server" +val numProcessors = CpuCoreSensor.availableProcessors() val logger = Logger.getLogger("Vert.x-Web Kotlinx Benchmark") suspend fun main(args: Array) { @@ -13,12 +15,18 @@ suspend fun main(args: Array) { ?: throw IllegalArgumentException("Specify the first `hasDb` Boolean argument") logger.info("$SERVER_NAME starting...") - val vertx = Vertx.vertx(vertxOptionsOf(preferNativeTransport = true)) + val vertx = Vertx.vertx( + vertxOptionsOf( + eventLoopPoolSize = numProcessors, preferNativeTransport = true, disableTCCL = true + ) + ) vertx.exceptionHandler { logger.info("Vertx exception caught: $it") it.printStackTrace() } - vertx.deployVerticle({ MainVerticle(hasDb) }, deploymentOptionsOf(instances = CpuCoreSensor.availableProcessors())) - .coAwait() + vertx.deployVerticle( + Supplier { MainVerticle(hasDb) }, + deploymentOptionsOf(instances = numProcessors) + ).coAwait() logger.info("$SERVER_NAME started.") } diff --git a/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/MainVerticle.kt b/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/MainVerticle.kt index 4dce51388ae..d12330de363 100644 --- a/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/MainVerticle.kt +++ b/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/MainVerticle.kt @@ -1,4 +1,6 @@ +import io.netty.channel.unix.Errors import io.netty.channel.unix.Errors.NativeIoException +import io.vertx.core.MultiMap import io.vertx.core.buffer.Buffer import io.vertx.core.http.HttpHeaders import io.vertx.core.http.HttpServer @@ -18,6 +20,9 @@ import io.vertx.sqlclient.Row import io.vertx.sqlclient.RowSet import io.vertx.sqlclient.Tuple import kotlinx.coroutines.Dispatchers +import kotlinx.datetime.UtcOffset +import kotlinx.datetime.format.DateTimeComponents +import kotlinx.datetime.format.format import kotlinx.html.* import kotlinx.html.stream.appendHTML import kotlinx.io.buffered @@ -26,10 +31,17 @@ import kotlinx.serialization.Serializable import kotlinx.serialization.SerializationStrategy import kotlinx.serialization.json.Json import kotlinx.serialization.json.io.encodeToSink -import java.time.ZonedDateTime -import java.time.format.DateTimeFormatter +import java.net.SocketException +import kotlin.time.Clock class MainVerticle(val hasDb: Boolean) : CoroutineVerticle(), CoroutineRouterSupport { + object HttpHeaderValues { + val vertxWeb = HttpHeaders.createOptimized("Vert.x-Web") + val applicationJson = HttpHeaders.createOptimized("application/json") + val textHtmlCharsetUtf8 = HttpHeaders.createOptimized("text/html; charset=utf-8") + val textPlain = HttpHeaders.createOptimized("text/plain") + } + // `PgConnection`s as used in the "vertx" portion offers better performance than `PgPool`s. lateinit var pgConnection: PgConnection lateinit var date: String @@ -37,12 +49,13 @@ class MainVerticle(val hasDb: Boolean) : CoroutineVerticle(), CoroutineRouterSup lateinit var selectWorldQuery: PreparedQuery> lateinit var selectFortuneQuery: PreparedQuery> - lateinit var updateWordQuery: PreparedQuery> + lateinit var updateWorldQuery: PreparedQuery> fun setCurrentDate() { - // kotlinx-datetime doesn't support the format yet. - //date = Clock.System.now().toString() - date = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now()) + date = DateTimeComponents.Formats.RFC_1123.format { + // We don't need a more complicated system `TimeZone` here (whose offset depends dynamically on the actual time due to DST) since UTC works. + setDateTimeOffset(Clock.System.now(), UtcOffset.ZERO) + } } override suspend fun start() { @@ -56,27 +69,25 @@ class MainVerticle(val hasDb: Boolean) : CoroutineVerticle(), CoroutineRouterSup user = "benchmarkdbuser", password = "benchmarkdbpass", cachePreparedStatements = true, - pipeliningLimit = 100000 + pipeliningLimit = 256 ) ).coAwait() selectWorldQuery = pgConnection.preparedQuery(SELECT_WORLD_SQL) selectFortuneQuery = pgConnection.preparedQuery(SELECT_FORTUNE_SQL) - updateWordQuery = pgConnection.preparedQuery(UPDATE_WORLD_SQL) + updateWorldQuery = pgConnection.preparedQuery(UPDATE_WORLD_SQL) } setCurrentDate() vertx.setPeriodic(1000) { setCurrentDate() } - httpServer = vertx.createHttpServer(httpServerOptionsOf(port = 8080)) + httpServer = vertx.createHttpServer( + httpServerOptionsOf(port = 8080, http2ClearTextEnabled = false, strictThreadMode = true) + ) .requestHandler(Router.router(vertx).apply { routes() }) .exceptionHandler { // wrk resets the connections when benchmarking is finished. - if ( - // for epoll - /*(it is NativeIoException && it.message == "recvAddress(..) failed: Connection reset by peer") - || (it is SocketException && it.message == "Connection reset")*/ - // for io_uring - it is NativeIoException && it.message == "io_uring read(..) failed: Connection reset by peer" + if ((/* for native transport */it is NativeIoException && it.expectedErr() == Errors.ERRNO_ECONNRESET_NEGATIVE) || + (/* for Java NIO */ it is SocketException && it.message == "Connection reset") ) return@exceptionHandler @@ -93,15 +104,17 @@ class MainVerticle(val hasDb: Boolean) : CoroutineVerticle(), CoroutineRouterSup } @Suppress("NOTHING_TO_INLINE") - inline fun HttpServerResponse.putCommonHeaders() { - putHeader(HttpHeaders.SERVER, "Vert.x-Web") - putHeader(HttpHeaders.DATE, date) + inline fun MultiMap.addCommonHeaders() { + add(HttpHeaders.SERVER, HttpHeaderValues.vertxWeb) + add(HttpHeaders.DATE, date) } @Suppress("NOTHING_TO_INLINE") - inline fun HttpServerResponse.putJsonResponseHeader() { - putCommonHeaders() - putHeader(HttpHeaders.CONTENT_TYPE, "application/json") + inline fun HttpServerResponse.addJsonResponseHeaders() { + headers().run { + addCommonHeaders() + add(HttpHeaders.CONTENT_TYPE, HttpHeaderValues.applicationJson) + } } @@ -117,15 +130,15 @@ class MainVerticle(val hasDb: Boolean) : CoroutineVerticle(), CoroutineRouterSup ) = coHandlerUnconfined { it.response().run { - putJsonResponseHeader() + addJsonResponseHeaders() /* - // approach 1 + // Approach 1 end(Json.encodeToString(serializer, requestHandler(it)))/*.coAwait()*/ */ /* - // approach 2 + // Approach 2 // java.lang.IllegalStateException: You must set the Content-Length header to be the total size of the message body BEFORE sending any data if you are not using HTTP chunked encoding. toRawSink().buffered().use { bufferedSink -> @OptIn(ExperimentalSerializationApi::class) @@ -133,7 +146,7 @@ class MainVerticle(val hasDb: Boolean) : CoroutineVerticle(), CoroutineRouterSup } */ - // approach 3 + // Approach 3 end(Buffer.buffer().apply { toRawSink().buffered().use { bufferedSink -> @OptIn(ExperimentalSerializationApi::class) @@ -197,12 +210,15 @@ class MainVerticle(val hasDb: Boolean) : CoroutineVerticle(), CoroutineRouterSup } it.response().run { - putCommonHeaders() - putHeader(HttpHeaders.CONTENT_TYPE, "text/html; charset=utf-8") + headers().run { + addCommonHeaders() + add(HttpHeaders.CONTENT_TYPE, HttpHeaderValues.textHtmlCharsetUtf8) + } end(htmlString)/*.coAwait()*/ } } + // Some changes to this part in the `vertx` portion in #9142 are not ported. get("/updates").jsonResponseCoHandler(Serializers.worlds) { val queries = it.request().getQueries() val worlds = selectRandomWorlds(queries) @@ -210,7 +226,7 @@ class MainVerticle(val hasDb: Boolean) : CoroutineVerticle(), CoroutineRouterSup // Approach 1 // The updated worlds need to be sorted first to avoid deadlocks. - updateWordQuery + updateWorldQuery .executeBatch(updatedWorlds.sortedBy { it.id }.map { Tuple.of(it.randomNumber, it.id) }).coAwait() /* @@ -225,8 +241,10 @@ class MainVerticle(val hasDb: Boolean) : CoroutineVerticle(), CoroutineRouterSup get("/plaintext").coHandlerUnconfined { it.response().run { - putCommonHeaders() - putHeader(HttpHeaders.CONTENT_TYPE, "text/plain") + headers().run { + addCommonHeaders() + add(HttpHeaders.CONTENT_TYPE, HttpHeaderValues.textPlain) + } end("Hello, World!")/*.coAwait()*/ } } diff --git a/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/VertxCoroutine.kt b/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/VertxCoroutine.kt index d6230fef7f7..88240185856 100644 --- a/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/VertxCoroutine.kt +++ b/frameworks/Kotlin/vertx-web-kotlinx/src/main/kotlin/VertxCoroutine.kt @@ -2,4 +2,4 @@ import io.vertx.core.Future import io.vertx.kotlin.coroutines.coAwait suspend fun List>.awaitAll(): List = - Future.all(this).coAwait().list() + Future.all(this).coAwait().list() diff --git a/frameworks/Kotlin/vertx-web-kotlinx/vertx-web-kotlinx-postgresql.dockerfile b/frameworks/Kotlin/vertx-web-kotlinx/vertx-web-kotlinx-postgresql.dockerfile index 17b43ebcb5c..148962d7948 100644 --- a/frameworks/Kotlin/vertx-web-kotlinx/vertx-web-kotlinx-postgresql.dockerfile +++ b/frameworks/Kotlin/vertx-web-kotlinx/vertx-web-kotlinx-postgresql.dockerfile @@ -1,4 +1,4 @@ -FROM gradle:8.10.2-jdk21 +FROM gradle:9.2.1-jdk25 WORKDIR /vertx-web-kotlinx COPY build.gradle.kts build.gradle.kts @@ -10,18 +10,24 @@ RUN gradle --no-daemon installDist EXPOSE 8080 CMD export JAVA_OPTS=" \ + --enable-native-access=ALL-UNNAMED \ + --sun-misc-unsafe-memory-access=allow \ + --add-opens=java.base/java.lang=ALL-UNNAMED \ -server \ -XX:+UseNUMA \ -XX:+UseParallelGC \ + -XX:+UnlockDiagnosticVMOptions \ + -XX:+DebugNonSafepoints \ + -Djava.lang.Integer.IntegerCache.high=10000 \ -Dvertx.disableMetrics=true \ - -Dvertx.disableH2c=true \ -Dvertx.disableWebsockets=true \ - -Dvertx.flashPolicyHandler=false \ - -Dvertx.threadChecks=false \ -Dvertx.disableContextTimings=true \ - -Dvertx.disableTCCL=true \ -Dvertx.disableHttpHeadersValidation=true \ + -Dvertx.cacheImmutableHttpResponseHeaders=true \ + -Dvertx.internCommonHttpRequestHeadersToLowerCase=true \ + -Dio.netty.noUnsafe=false \ -Dio.netty.buffer.checkBounds=false \ -Dio.netty.buffer.checkAccessible=false \ + -Dio.netty.iouring.ringSize=16384 \ " && \ build/install/vertx-web-kotlinx-benchmark/bin/vertx-web-kotlinx-benchmark true diff --git a/frameworks/Kotlin/vertx-web-kotlinx/vertx-web-kotlinx.dockerfile b/frameworks/Kotlin/vertx-web-kotlinx/vertx-web-kotlinx.dockerfile index 4bdc993707d..86382573446 100644 --- a/frameworks/Kotlin/vertx-web-kotlinx/vertx-web-kotlinx.dockerfile +++ b/frameworks/Kotlin/vertx-web-kotlinx/vertx-web-kotlinx.dockerfile @@ -1,4 +1,4 @@ -FROM gradle:8.10.2-jdk21 +FROM gradle:9.2.1-jdk25 WORKDIR /vertx-web-kotlinx COPY build.gradle.kts build.gradle.kts @@ -10,18 +10,24 @@ RUN gradle --no-daemon installDist EXPOSE 8080 CMD export JAVA_OPTS=" \ + --enable-native-access=ALL-UNNAMED \ + --sun-misc-unsafe-memory-access=allow \ + --add-opens=java.base/java.lang=ALL-UNNAMED \ -server \ -XX:+UseNUMA \ -XX:+UseParallelGC \ + -XX:+UnlockDiagnosticVMOptions \ + -XX:+DebugNonSafepoints \ + -Djava.lang.Integer.IntegerCache.high=10000 \ -Dvertx.disableMetrics=true \ - -Dvertx.disableH2c=true \ -Dvertx.disableWebsockets=true \ - -Dvertx.flashPolicyHandler=false \ - -Dvertx.threadChecks=false \ -Dvertx.disableContextTimings=true \ - -Dvertx.disableTCCL=true \ -Dvertx.disableHttpHeadersValidation=true \ + -Dvertx.cacheImmutableHttpResponseHeaders=true \ + -Dvertx.internCommonHttpRequestHeadersToLowerCase=true \ + -Dio.netty.noUnsafe=false \ -Dio.netty.buffer.checkBounds=false \ -Dio.netty.buffer.checkAccessible=false \ + -Dio.netty.iouring.ringSize=16384 \ " && \ build/install/vertx-web-kotlinx-benchmark/bin/vertx-web-kotlinx-benchmark false diff --git a/frameworks/Lua/openresty/benchmark_config.json b/frameworks/Lua/openresty/benchmark_config.json index 6b32f71f3de..7fa51aa4a95 100644 --- a/frameworks/Lua/openresty/benchmark_config.json +++ b/frameworks/Lua/openresty/benchmark_config.json @@ -20,6 +20,7 @@ "database_os": "Linux", "display_name": "openresty", "notes": "", + "tags": ["broken"], "versus": "openresty" } }] diff --git a/frameworks/Nim/basolato/benchmark_config.json b/frameworks/Nim/basolato/benchmark_config.json index 1bb2d11484e..e0f90c90dcc 100755 --- a/frameworks/Nim/basolato/benchmark_config.json +++ b/frameworks/Nim/basolato/benchmark_config.json @@ -23,6 +23,7 @@ "database_os": "Linux", "display_name": "Basolato", "notes": "", + "tags": ["broken"], "versus": "httpbeast, prologue" } } diff --git a/frameworks/Nim/httpbeast/benchmark_config.json b/frameworks/Nim/httpbeast/benchmark_config.json index be0ab4480b8..7aa8ac8fc19 100755 --- a/frameworks/Nim/httpbeast/benchmark_config.json +++ b/frameworks/Nim/httpbeast/benchmark_config.json @@ -19,6 +19,7 @@ "database_os": "Linux", "display_name": "HttpBeast", "notes": "", + "tags": ["broken"], "versus": "None" } } diff --git a/frameworks/Nim/jester/benchmark_config.json b/frameworks/Nim/jester/benchmark_config.json index b5795fba053..61499a79da1 100644 --- a/frameworks/Nim/jester/benchmark_config.json +++ b/frameworks/Nim/jester/benchmark_config.json @@ -19,6 +19,7 @@ "database_os": "Linux", "display_name": "Jester", "notes": "", + "tags": ["broken"], "versus": "httpbeast" } } diff --git a/frameworks/Nim/nim-stdlib/benchmark_config.json b/frameworks/Nim/nim-stdlib/benchmark_config.json index acd5712689a..710cb9996ea 100644 --- a/frameworks/Nim/nim-stdlib/benchmark_config.json +++ b/frameworks/Nim/nim-stdlib/benchmark_config.json @@ -23,6 +23,7 @@ "database_os": "Linux", "display_name": "nim-stdlib", "notes": "", + "tags": ["broken"], "versus": "httpbeast" } } diff --git a/frameworks/Nim/scorper/benchmark_config.json b/frameworks/Nim/scorper/benchmark_config.json index 77669f6cad2..6a365398a14 100755 --- a/frameworks/Nim/scorper/benchmark_config.json +++ b/frameworks/Nim/scorper/benchmark_config.json @@ -19,6 +19,7 @@ "database_os": "Linux", "display_name": "scorper", "notes": "", + "tags": ["broken"], "versus": "httpbeast" } } diff --git a/frameworks/PHP/amp/amp.dockerfile b/frameworks/PHP/amp/amp.dockerfile index 240db763cec..ced0e578009 100644 --- a/frameworks/PHP/amp/amp.dockerfile +++ b/frameworks/PHP/amp/amp.dockerfile @@ -6,19 +6,19 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ apt-get install -yqq git unzip wget curl build-essential \ - php8.4-cli php8.4-mbstring php8.4-dev php8.4-xml php8.4-curl > /dev/null + php8.5-cli php8.5-mbstring php8.5-dev php8.5-xml php8.5-curl > /dev/null # An extension is required! # We deal with concurrencies over 1k, which stream_select doesn't support. RUN wget http://pear.php.net/go-pear.phar --quiet && php go-pear.phar #RUN apt-get install -y libuv1-dev > /dev/null RUN apt-get install -y libevent-dev > /dev/null -#RUN pecl install uv-0.2.4 > /dev/null && echo "extension=uv.so" > /etc/php/8.4/cli/conf.d/uv.ini -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +#RUN pecl install uv-0.2.4 > /dev/null && echo "extension=uv.so" > /etc/php/8.5/cli/conf.d/uv.ini +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini WORKDIR /amp COPY --link . . -COPY deploy/conf/* /etc/php/8.4/cli/conf.d/ +COPY deploy/conf/* /etc/php/8.5/cli/conf.d/ COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer diff --git a/frameworks/PHP/cakephp/benchmark_config.json b/frameworks/PHP/cakephp/benchmark_config.json index 351a5d119b4..723b55e35b0 100644 --- a/frameworks/PHP/cakephp/benchmark_config.json +++ b/frameworks/PHP/cakephp/benchmark_config.json @@ -43,9 +43,10 @@ "webserver": "none", "os": "Linux", "database_os": "Linux", - "display_name": "CakePHP-workerman", + "display_name": "CakePHP [workerman]", "notes": "", "versus": "php" } }] } + diff --git a/frameworks/PHP/cakephp/cakephp-workerman.dockerfile b/frameworks/PHP/cakephp/cakephp-workerman.dockerfile index ce77247eb6c..776e55f1252 100644 --- a/frameworks/PHP/cakephp/cakephp-workerman.dockerfile +++ b/frameworks/PHP/cakephp/cakephp-workerman.dockerfile @@ -7,24 +7,25 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq git unzip \ - php8.4-cli php8.4-mysql php8.4-mbstring php8.4-intl php8.4-xml php8.4-curl > /dev/null + php8.5-cli php8.5-mysql php8.5-mbstring php8.5-intl php8.5-xml php8.5-curl > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini EXPOSE 8080 ADD ./ /cakephp WORKDIR /cakephp -RUN composer require joanhey/adapterman:^0.7 -RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet +RUN composer require joanhey/adapterman:^0.7 --quiet +RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet RUN chmod -R 777 /cakephp -#COPY deploy/conf/cli-php.ini /etc/php/8.4/cli/php.ini +#COPY deploy/conf/cli-php.ini /etc/php/8.5/cli/php.ini CMD php -c deploy/conf/cli-php.ini \ server.php start + diff --git a/frameworks/PHP/cakephp/cakephp.dockerfile b/frameworks/PHP/cakephp/cakephp.dockerfile index d5d39a7ea65..efd5894a928 100644 --- a/frameworks/PHP/cakephp/cakephp.dockerfile +++ b/frameworks/PHP/cakephp/cakephp.dockerfile @@ -7,22 +7,22 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq nginx git unzip \ - php8.4-fpm php8.4-mysql php8.4-xml php8.4-mbstring php8.4-intl php8.4-dev php8.4-curl > /dev/null + php8.5-fpm php8.5-mysql php8.5-xml php8.5-mbstring php8.5-intl php8.5-dev php8.5-curl > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY deploy/conf/* /etc/php/8.4/fpm/ -COPY deploy/conf/* /etc/php/8.4/cli/ +COPY deploy/conf/* /etc/php/8.5/fpm/ +COPY deploy/conf/* /etc/php/8.5/cli/ ADD ./ /cakephp WORKDIR /cakephp -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet RUN chmod -R 777 /cakephp -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /cakephp/deploy/nginx.conf diff --git a/frameworks/PHP/cakephp/deploy/conf/cli-php.ini b/frameworks/PHP/cakephp/deploy/conf/cli-php.ini index e03b6e352a9..d2c550c65ee 100644 --- a/frameworks/PHP/cakephp/deploy/conf/cli-php.ini +++ b/frameworks/PHP/cakephp/deploy/conf/cli-php.ini @@ -14,3 +14,6 @@ opcache.jit_buffer_size = 128M opcache.jit = tracing disable_functions=header,header_remove,headers_sent,headers_list,http_response_code,setcookie,session_create_id,session_id,session_name,session_save_path,session_status,session_start,session_write_close,session_regenerate_id,session_unset,session_get_cookie_params,session_set_cookie_params,set_time_limit + +#php 8.5 +error_reporting = E_ALL & ~E_DEPRECATED diff --git a/frameworks/PHP/cakephp/server.php b/frameworks/PHP/cakephp/server.php index 820e178205d..ce502ed9bee 100644 --- a/frameworks/PHP/cakephp/server.php +++ b/frameworks/PHP/cakephp/server.php @@ -26,7 +26,7 @@ class HeaderDate { - const NAME = 'Date: '; + const DATE_FORMAT = 'D, d M Y H:i:s \G\M\T'; /** * Date header @@ -37,9 +37,9 @@ class HeaderDate public static function init(): void { - self::$date = self::NAME.gmdate(DATE_RFC7231); + self::$date = 'Date: '.gmdate(self::DATE_FORMAT); Timer::add(1, static function () { - self::$date = self::NAME.gmdate(DATE_RFC7231); + self::$date = 'Date: '.gmdate(self::DATE_FORMAT); }); } } diff --git a/frameworks/PHP/codeigniter/codeigniter.dockerfile b/frameworks/PHP/codeigniter/codeigniter.dockerfile index 097ea60514d..0737e1eeed9 100644 --- a/frameworks/PHP/codeigniter/codeigniter.dockerfile +++ b/frameworks/PHP/codeigniter/codeigniter.dockerfile @@ -7,16 +7,16 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get update > /dev/null && apt-get install -yqq nginx git unzip \ - php8.4-cli php8.4-fpm php8.4-mysql php8.4-mbstring php8.4-intl php8.4-curl > /dev/null + php8.5-cli php8.5-fpm php8.5-mysql php8.5-mbstring php8.5-intl php8.5-curl > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ ADD ./ /codeigniter WORKDIR /codeigniter -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN composer install --optimize-autoloader --classmap-authoritative --no-dev #--quiet @@ -25,5 +25,5 @@ RUN chmod -R 777 writable EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /codeigniter/deploy/nginx.conf diff --git a/frameworks/PHP/comet/app.php b/frameworks/PHP/comet/app.php index 857853bc9ec..f0ef91fbece 100644 --- a/frameworks/PHP/comet/app.php +++ b/frameworks/PHP/comet/app.php @@ -24,9 +24,9 @@ $app->init( function() { ORM::init(); - Storage::$date = gmdate(DATE_RFC7231); + Storage::$date = gmdate('D, d M Y H:i:s \G\M\T'); Timer::add(1, function() { - Storage::$date = gmdate(DATE_RFC7231); + Storage::$date = gmdate('D, d M Y H:i:s \G\M\T'); }); }); diff --git a/frameworks/PHP/comet/comet-mysql.dockerfile b/frameworks/PHP/comet/comet-mysql.dockerfile index 2adc4d70f81..778b6d3c276 100644 --- a/frameworks/PHP/comet/comet-mysql.dockerfile +++ b/frameworks/PHP/comet/comet-mysql.dockerfile @@ -6,14 +6,14 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null -RUN apt-get install -yqq php8.3-cli php8.3-xml php8.3-mysql php8.3-mbstring > /dev/null +RUN apt-get install -yqq php8.5-cli php8.5-xml php8.5-mysql php8.5-mbstring > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.3-dev libevent-dev git > /dev/null -RUN pecl install event-3.1.3 > /dev/null && echo "extension=event.so" > /etc/php/8.3/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev git > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini -COPY php.ini /etc/php/8.3/cli/php.ini +COPY php.ini /etc/php/8.5/cli/php.ini ADD ./ /comet WORKDIR /comet diff --git a/frameworks/PHP/comet/comet.dockerfile b/frameworks/PHP/comet/comet.dockerfile index 2cfbc0935c6..f7a98ab36aa 100644 --- a/frameworks/PHP/comet/comet.dockerfile +++ b/frameworks/PHP/comet/comet.dockerfile @@ -6,14 +6,14 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null -RUN apt-get install -yqq php8.4-cli php8.4-pgsql php8.4-xml php8.4-mbstring > /dev/null +RUN apt-get install -yqq php8.5-cli php8.5-pgsql php8.5-xml php8.5-mbstring > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev git > /dev/null -RUN pecl install event-3.1.3 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev git > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini -COPY php.ini /etc/php/8.4/cli/php.ini +COPY php.ini /etc/php/8.5/cli/php.ini ADD ./ /comet WORKDIR /comet diff --git a/frameworks/PHP/duckphp/duckphp.dockerfile b/frameworks/PHP/duckphp/duckphp.dockerfile index ae97dfc8cf6..b2de21fa9dc 100644 --- a/frameworks/PHP/duckphp/duckphp.dockerfile +++ b/frameworks/PHP/duckphp/duckphp.dockerfile @@ -6,18 +6,18 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ apt-get install -yqq nginx git unzip \ - php8.4-cli php8.4-fpm php8.4-mysql php8.4-dev > /dev/null + php8.5-cli php8.5-fpm php8.5-mysql php8.5-dev > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /duckphp COPY --link . . -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /duckphp/deploy/nginx.conf diff --git a/frameworks/PHP/fat-free/fat-free-raw.dockerfile b/frameworks/PHP/fat-free/fat-free-raw.dockerfile index 9038161bb87..c6d2550de7b 100644 --- a/frameworks/PHP/fat-free/fat-free-raw.dockerfile +++ b/frameworks/PHP/fat-free/fat-free-raw.dockerfile @@ -5,9 +5,9 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq nginx git unzip php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql > /dev/null + apt-get install -yqq nginx git unzip php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /fat-free COPY --link . . @@ -18,11 +18,11 @@ COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /fat-free EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /fat-free/deploy/nginx.conf diff --git a/frameworks/PHP/fat-free/fat-free.dockerfile b/frameworks/PHP/fat-free/fat-free.dockerfile index 3a91f8cc194..522e778a998 100644 --- a/frameworks/PHP/fat-free/fat-free.dockerfile +++ b/frameworks/PHP/fat-free/fat-free.dockerfile @@ -5,9 +5,9 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq nginx git unzip php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql > /dev/null + apt-get install -yqq nginx git unzip php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /fat-free COPY --link . . @@ -19,11 +19,11 @@ COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /fat-free EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /fat-free/deploy/nginx.conf diff --git a/frameworks/PHP/fat-free/index.php b/frameworks/PHP/fat-free/index.php index 761ca19ebbb..d25faf51e31 100644 --- a/frameworks/PHP/fat-free/index.php +++ b/frameworks/PHP/fat-free/index.php @@ -9,7 +9,7 @@ /** @var Base $f3 */ $f3 = \Base::instance(); -error_reporting(-1); +error_reporting(E_ALL ^ E_DEPRECATED); $f3->set('DEBUG', 0); $f3->set('HIGHLIGHT', false); diff --git a/frameworks/PHP/flight/benchmark_config.json b/frameworks/PHP/flight/benchmark_config.json index 5a2cb9f89fb..64d12cac7b4 100644 --- a/frameworks/PHP/flight/benchmark_config.json +++ b/frameworks/PHP/flight/benchmark_config.json @@ -45,6 +45,7 @@ "database_os": "Linux", "display_name": "flight [workerman]", "notes": "", + "tags": [ "broken" ], "versus": "php" } }] diff --git a/frameworks/PHP/flight/flight-workerman.dockerfile b/frameworks/PHP/flight/flight-workerman.dockerfile index ebaa2098243..ec9f644e16f 100644 --- a/frameworks/PHP/flight/flight-workerman.dockerfile +++ b/frameworks/PHP/flight/flight-workerman.dockerfile @@ -5,9 +5,9 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq nginx git unzip php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql > /dev/null + apt-get install -yqq nginx git unzip php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /flight COPY . . @@ -16,8 +16,8 @@ ENV FLIGHT_DIR="/flight/src" COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev php8.4-xml > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev php8.5-xml > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini RUN composer require joanhey/adapterman:^0.7 RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet diff --git a/frameworks/PHP/flight/flight.dockerfile b/frameworks/PHP/flight/flight.dockerfile index 60b2b3ebc7a..51f64fb97b5 100644 --- a/frameworks/PHP/flight/flight.dockerfile +++ b/frameworks/PHP/flight/flight.dockerfile @@ -5,9 +5,9 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq nginx git unzip php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql > /dev/null + apt-get install -yqq nginx git unzip php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /flight COPY --link . . @@ -18,11 +18,11 @@ COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /flight EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /flight/deploy/nginx.conf diff --git a/frameworks/PHP/flight/server.php b/frameworks/PHP/flight/server.php index 826e74e38ec..06f562cd98a 100644 --- a/frameworks/PHP/flight/server.php +++ b/frameworks/PHP/flight/server.php @@ -37,9 +37,9 @@ class HeaderDate public static function init(): void { - self::$date = self::NAME . gmdate(DATE_RFC7231); + self::$date = self::NAME . gmdate('D, d M Y H:i:s \G\M\T'); Timer::add(1, static function () { - self::$date = self::NAME . gmdate(DATE_RFC7231); + self::$date = self::NAME . gmdate('D, d M Y H:i:s \G\M\T'); }); } } diff --git a/frameworks/PHP/fomo/benchmark_config.json b/frameworks/PHP/fomo/benchmark_config.json index f79f7905e7e..817107d03d2 100755 --- a/frameworks/PHP/fomo/benchmark_config.json +++ b/frameworks/PHP/fomo/benchmark_config.json @@ -23,9 +23,9 @@ "database_os": "Linux", "display_name": "Fomo", "notes": "", + "tags": ["broken"], "versus": "swoole" } } ] } - \ No newline at end of file diff --git a/frameworks/PHP/fuel/benchmark_config.json b/frameworks/PHP/fuel/benchmark_config.json index d831c427cc3..98761b3a7a4 100644 --- a/frameworks/PHP/fuel/benchmark_config.json +++ b/frameworks/PHP/fuel/benchmark_config.json @@ -20,6 +20,7 @@ "database_os": "Linux", "display_name": "fuel", "notes": "", + "tags": ["broken"], "versus": "php" } }] diff --git a/frameworks/PHP/kumbiaphp/kumbiaphp-raw.dockerfile b/frameworks/PHP/kumbiaphp/kumbiaphp-raw.dockerfile index f97c728e4c9..1814858f0bf 100644 --- a/frameworks/PHP/kumbiaphp/kumbiaphp-raw.dockerfile +++ b/frameworks/PHP/kumbiaphp/kumbiaphp-raw.dockerfile @@ -7,17 +7,17 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq nginx git unzip \ - php8.4-fpm php8.4-mysql > /dev/null + php8.5-fpm php8.5-mysql > /dev/null -COPY --link deploy/conf/* /etc/php/8.4/fpm/ +COPY --link deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /kumbiaphp COPY --link . . RUN git clone -b v1.2.1 --single-branch --depth 1 -q https://github.com/KumbiaPHP/KumbiaPHP.git vendor/Kumbia -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /kumbiaphp/deploy/nginx.conf diff --git a/frameworks/PHP/kumbiaphp/kumbiaphp-workerman-mysql.dockerfile b/frameworks/PHP/kumbiaphp/kumbiaphp-workerman-mysql.dockerfile index 775a825d187..6389a637c2c 100644 --- a/frameworks/PHP/kumbiaphp/kumbiaphp-workerman-mysql.dockerfile +++ b/frameworks/PHP/kumbiaphp/kumbiaphp-workerman-mysql.dockerfile @@ -6,14 +6,14 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null -RUN apt-get install -yqq git php8.4-cli php8.4-mysql php8.4-xml > /dev/null +RUN apt-get install -yqq git php8.5-cli php8.5-mysql php8.5-xml > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini -COPY deploy/conf/cliphp.ini /etc/php/8.4/cli/conf.d/20-adapterman.ini +COPY deploy/conf/cliphp.ini /etc/php/8.5/cli/conf.d/20-adapterman.ini ADD ./ /kumbiaphp WORKDIR /kumbiaphp diff --git a/frameworks/PHP/kumbiaphp/kumbiaphp-workerman.dockerfile b/frameworks/PHP/kumbiaphp/kumbiaphp-workerman.dockerfile index 9342ce03dbc..a5eb7d5e0af 100644 --- a/frameworks/PHP/kumbiaphp/kumbiaphp-workerman.dockerfile +++ b/frameworks/PHP/kumbiaphp/kumbiaphp-workerman.dockerfile @@ -3,16 +3,16 @@ FROM ubuntu:24.04 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null -RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php +RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq git php8.4-cli php8.4-pgsql php8.4-xml > /dev/null + apt-get install -yqq git php8.5-cli php8.5-pgsql php8.5-xml > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini -COPY deploy/conf/cliphp.ini /etc/php/8.4/cli/conf.d/20-adapterman.ini +COPY deploy/conf/cliphp.ini /etc/php/8.5/cli/conf.d/20-adapterman.ini ADD ./ /kumbiaphp WORKDIR /kumbiaphp diff --git a/frameworks/PHP/kumbiaphp/kumbiaphp.dockerfile b/frameworks/PHP/kumbiaphp/kumbiaphp.dockerfile index 960100a6347..db4eee13b45 100644 --- a/frameworks/PHP/kumbiaphp/kumbiaphp.dockerfile +++ b/frameworks/PHP/kumbiaphp/kumbiaphp.dockerfile @@ -7,18 +7,18 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq nginx git unzip \ - php8.4-fpm php8.4-mysql > /dev/null + php8.5-fpm php8.5-mysql > /dev/null -COPY --link deploy/conf/* /etc/php/8.4/fpm/ +COPY --link deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /kumbiaphp COPY --link . . RUN git clone -b v1.2.1 --single-branch --depth 1 https://github.com/KumbiaPHP/KumbiaPHP.git vendor/Kumbia RUN git clone -b master --single-branch --depth 1 https://github.com/KumbiaPHP/ActiveRecord.git vendor/Kumbia/ActiveRecord -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /kumbiaphp/deploy/nginx.conf diff --git a/frameworks/PHP/laravel/composer.json b/frameworks/PHP/laravel/composer.json index 391fa9a1106..be731270c67 100644 --- a/frameworks/PHP/laravel/composer.json +++ b/frameworks/PHP/laravel/composer.json @@ -25,6 +25,22 @@ "App\\": "app/" } }, + "replace": { + "symfony/polyfill-ctype": "*", + "symfony/polyfill-mbstring":"*", + "symfony/polyfill-intl-idn": "*", + "symfony/polyfill-intl-normalizer": "*", + "symfony/polyfill-intl-grapheme": "*", + "symfony/polyfill-iconv": "*", + "symfony/polyfill-php72": "*", + "symfony/polyfill-php73": "*", + "symfony/polyfill-php74": "*", + "symfony/polyfill-php80": "*", + "symfony/polyfill-php81": "*", + "symfony/polyfill-php82": "*", + "symfony/polyfill-php83": "*", + "symfony/polyfill-php84": "*" + }, "minimum-stability": "stable", "prefer-stable": true, "scripts": { diff --git a/frameworks/PHP/laravel/laravel-octane-frankenphp.dockerfile b/frameworks/PHP/laravel/laravel-octane-frankenphp.dockerfile index b483b396d10..dc2e4724395 100644 --- a/frameworks/PHP/laravel/laravel-octane-frankenphp.dockerfile +++ b/frameworks/PHP/laravel/laravel-octane-frankenphp.dockerfile @@ -1,12 +1,15 @@ -FROM dunglas/frankenphp - +FROM dunglas/frankenphp:php8.5 + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update -yqq && apt-get install libicu-dev unzip -y > /dev/null RUN install-php-extensions \ + intl \ pcntl \ pdo_mysql \ zip > /dev/null - -COPY --link . /app/ +COPY --link . /app/ COPY --from=composer --link /usr/bin/composer /usr/local/bin/composer RUN mkdir -p bootstrap/cache \ diff --git a/frameworks/PHP/laravel/laravel-ripple.dockerfile b/frameworks/PHP/laravel/laravel-ripple.dockerfile index 2fc4a480716..101b458a051 100644 --- a/frameworks/PHP/laravel/laravel-ripple.dockerfile +++ b/frameworks/PHP/laravel/laravel-ripple.dockerfile @@ -1,21 +1,24 @@ -FROM php:8.3-cli +FROM php:8.5-cli + +ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq >> /dev/null RUN apt-get install -y libevent-dev \ libssl-dev \ pkg-config \ + libicu-dev \ build-essential \ unzip >> /dev/null RUN docker-php-ext-install pdo_mysql \ - opcache \ + intl \ posix \ pcntl \ sockets >> /dev/null RUN pecl install event >> /dev/null -RUN docker-php-ext-enable pdo_mysql opcache posix pcntl sockets +RUN docker-php-ext-enable intl pdo_mysql posix pcntl sockets RUN docker-php-ext-enable --ini-name zz-event.ini event RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini RUN echo "opcache.jit=1205" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini diff --git a/frameworks/PHP/laravel/laravel-roadrunner.dockerfile b/frameworks/PHP/laravel/laravel-roadrunner.dockerfile index 9a0c3aed98b..44c97267c12 100644 --- a/frameworks/PHP/laravel/laravel-roadrunner.dockerfile +++ b/frameworks/PHP/laravel/laravel-roadrunner.dockerfile @@ -1,6 +1,10 @@ -FROM php:8.4-cli +FROM php:8.5-cli -RUN docker-php-ext-install pdo_mysql pcntl opcache sockets > /dev/null +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update -yqq && \ + apt-get install -yqq libpq-dev libicu-dev > /dev/null && \ +docker-php-ext-install intl pdo_mysql pcntl sockets > /dev/null RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini RUN echo "opcache.jit=1205" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini @@ -23,9 +27,11 @@ RUN pecl install protobuf > /dev/null && echo "extension=protobuf.so" > /usr/loc COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer RUN composer require laravel/octane --update-no-dev --no-scripts --quiet -RUN php artisan octane:install --server="roadrunner" +RUN php artisan octane:install --server="roadrunner" > /dev/null RUN php artisan optimize +RUN export WORKERS=$((1*$(nproc))) +RUN if [ $(nproc) > 2 ]; then export WORKERS=$((1*$(nproc) -1)) ; fi; EXPOSE 8080 # https://artisan.page/12.x/ diff --git a/frameworks/PHP/laravel/laravel-swoole.dockerfile b/frameworks/PHP/laravel/laravel-swoole.dockerfile index de27380656d..ae51b9d0ad1 100644 --- a/frameworks/PHP/laravel/laravel-swoole.dockerfile +++ b/frameworks/PHP/laravel/laravel-swoole.dockerfile @@ -1,7 +1,7 @@ FROM phpswoole/swoole:php8.4 -RUN docker-php-ext-install pcntl opcache curl > /dev/null - +RUN apt-get update -yqq && apt-get install libicu-dev -y > /dev/null +RUN docker-php-ext-install intl pcntl opcache > /dev/null RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini RUN echo "opcache.jit=1205" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini RUN echo "opcache.jit_buffer_size=128M" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini diff --git a/frameworks/PHP/laravel/laravel-workerman.dockerfile b/frameworks/PHP/laravel/laravel-workerman.dockerfile index 8b016a50626..a9cd1313cc7 100644 --- a/frameworks/PHP/laravel/laravel-workerman.dockerfile +++ b/frameworks/PHP/laravel/laravel-workerman.dockerfile @@ -6,12 +6,12 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null && \ apt-get install -yqq git unzip \ - php8.4-cli php8.4-mysql php8.4-mbstring php8.4-xml php8.4-curl > /dev/null + php8.5-cli php8.5-mysql php8.5-mbstring php8.5-xml php8.5-intl php8.5-curl > /dev/null COPY --from=composer --link /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini WORKDIR /laravel COPY --link . . @@ -25,7 +25,7 @@ RUN mkdir -p bootstrap/cache \ RUN composer require joanhey/adapterman --update-no-dev --no-scripts --quiet RUN php artisan optimize -COPY --link deploy/conf/cli-php.ini /etc/php/8.4/cli/conf.d/20-adapterman.ini +COPY --link deploy/conf/cli-php.ini /etc/php/8.5/cli/conf.d/20-adapterman.ini EXPOSE 8080 diff --git a/frameworks/PHP/laravel/laravel.dockerfile b/frameworks/PHP/laravel/laravel.dockerfile index 13ca827c6d3..46d5aca59cc 100644 --- a/frameworks/PHP/laravel/laravel.dockerfile +++ b/frameworks/PHP/laravel/laravel.dockerfile @@ -7,15 +7,15 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq nginx git unzip \ - php8.4-bcmath php8.4-cli php8.4-fpm php8.4-mysql php8.4-mbstring php8.4-xml php8.4-curl php8.4-intl > /dev/null + php8.5-bcmath php8.5-cli php8.5-fpm php8.5-mysql php8.5-mbstring php8.5-xml php8.5-curl php8.5-intl > /dev/null COPY --from=composer --link /usr/bin/composer /usr/local/bin/composer -COPY --link deploy/conf/* /etc/php/8.4/fpm/ +COPY --link deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /laravel COPY --link . . -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN mkdir -p bootstrap/cache \ storage/logs \ @@ -29,7 +29,7 @@ RUN php artisan optimize EXPOSE 8080 # Uncomment next line for Laravel console error logging to be viewable in docker logs -# RUN echo "catch_workers_output = yes" >> /etc/php/8.4/fpm/php-fpm.conf +# RUN echo "catch_workers_output = yes" >> /etc/php/8.5/fpm/php-fpm.conf -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /laravel/deploy/nginx.conf diff --git a/frameworks/PHP/laravel/server-man.php b/frameworks/PHP/laravel/server-man.php index 6aa249cce8f..1816cd90c29 100644 --- a/frameworks/PHP/laravel/server-man.php +++ b/frameworks/PHP/laravel/server-man.php @@ -13,9 +13,9 @@ $http_worker->reusePort = true; $http_worker->name = 'AdapterMan-Laravel'; $http_worker->onWorkerStart = static function () { - Header::$date = gmdate(DATE_RFC7231); + Header::$date = gmdate('D, d M Y H:i:s \G\M\T'); Timer::add(1, function() { - Header::$date = gmdate(DATE_RFC7231); + Header::$date = gmdate('D, d M Y H:i:s \G\M\T'); }); //init(); require __DIR__.'/start.php'; diff --git a/frameworks/PHP/leaf/composer.json b/frameworks/PHP/leaf/composer.json index 25dd1d1aa6e..f391f601d71 100644 --- a/frameworks/PHP/leaf/composer.json +++ b/frameworks/PHP/leaf/composer.json @@ -1,5 +1,5 @@ { "require": { - "leafs/leaf": "^3.11" + "leafs/leaf": "^4" } } diff --git a/frameworks/PHP/leaf/leaf-workerman.dockerfile b/frameworks/PHP/leaf/leaf-workerman.dockerfile index c98f11f5c84..ec7038b780d 100644 --- a/frameworks/PHP/leaf/leaf-workerman.dockerfile +++ b/frameworks/PHP/leaf/leaf-workerman.dockerfile @@ -7,15 +7,15 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get update -yqq > /dev/null && apt-get install -yqq git \ - php8.4-cli php8.4-mysql php8.4-mbstring php8.4-xml php8.4-curl php8.4-zip > /dev/null + php8.5-cli php8.5-mysql php8.5-mbstring php8.5-xml php8.5-curl php8.5-zip > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y libevent-dev php8.4-dev > /dev/null \ +RUN apt-get install -y libevent-dev php8.5-dev > /dev/null \ && pecl install event-3.1.4 > /dev/null \ - && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini + && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini -COPY --link deploy/conf/cli-php.ini /etc/php/8.4/cli/conf.d/20-adapterman.ini +COPY --link deploy/conf/cli-php.ini /etc/php/8.5/cli/conf.d/20-adapterman.ini WORKDIR /leaf COPY --link . . diff --git a/frameworks/PHP/leaf/leaf.dockerfile b/frameworks/PHP/leaf/leaf.dockerfile index 1ebe23e5735..c9d1d8a88e5 100644 --- a/frameworks/PHP/leaf/leaf.dockerfile +++ b/frameworks/PHP/leaf/leaf.dockerfile @@ -7,16 +7,16 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq nginx git unzip \ - php8.4-cli php8.4-fpm php8.4-mysql php8.4-xml php8.4-curl php8.4-zip > /dev/null + php8.5-cli php8.5-fpm php8.5-mysql php8.5-xml php8.5-curl php8.5-zip > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY --link deploy/conf/* /etc/php/8.4/fpm/ +COPY --link deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /leaf COPY --link . . -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet @@ -24,5 +24,5 @@ RUN chmod -R 777 /leaf EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /leaf/deploy/nginx.conf diff --git a/frameworks/PHP/leaf/server.php b/frameworks/PHP/leaf/server.php index 4e931b07e33..91ac664aabb 100644 --- a/frameworks/PHP/leaf/server.php +++ b/frameworks/PHP/leaf/server.php @@ -39,9 +39,9 @@ class HeaderDate public static function init(): void { - self::$date = self::NAME . gmdate(DATE_RFC7231); + self::$date = self::NAME . gmdate('D, d M Y H:i:s \G\M\T'); Timer::add(1, static function() { - self::$date = self::NAME . gmdate(DATE_RFC7231); + self::$date = self::NAME . gmdate('D, d M Y H:i:s \G\M\T'); }); } } \ No newline at end of file diff --git a/frameworks/PHP/mako/app/controllers/Index.php b/frameworks/PHP/mako/app/http/controllers/Index.php similarity index 98% rename from frameworks/PHP/mako/app/controllers/Index.php rename to frameworks/PHP/mako/app/http/controllers/Index.php index 701da352c36..d5ec3eecebc 100644 --- a/frameworks/PHP/mako/app/controllers/Index.php +++ b/frameworks/PHP/mako/app/http/controllers/Index.php @@ -1,6 +1,6 @@ =7.4.0", - "mako/framework": "^9.0" + "mako/framework": "^11.0" }, "autoload": { "psr-4": { diff --git a/frameworks/PHP/mako/mako.dockerfile b/frameworks/PHP/mako/mako.dockerfile index 07010604204..837761967b1 100644 --- a/frameworks/PHP/mako/mako.dockerfile +++ b/frameworks/PHP/mako/mako.dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 ARG DEBIAN_FRONTEND=noninteractive @@ -7,16 +7,16 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq nginx git unzip \ - php8.3-cli php8.3-fpm php8.3-mysql php8.3-mbstring php8.3-xml php8.3-curl > /dev/null + php8.5-cli php8.5-fpm php8.5-mysql php8.5-mbstring php8.5-xml php8.5-curl > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY deploy/conf/* /etc/php/8.3/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ ADD ./ /mako WORKDIR /mako -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.3/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --ignore-platform-reqs --quiet @@ -24,5 +24,5 @@ RUN chmod -R 777 app EXPOSE 8080 -CMD service php8.3-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /mako/deploy/nginx.conf diff --git a/frameworks/PHP/mako/public/index.php b/frameworks/PHP/mako/public/index.php index 8f0116fb5dc..b7e7748bb18 100644 --- a/frameworks/PHP/mako/public/index.php +++ b/frameworks/PHP/mako/public/index.php @@ -1,5 +1,6 @@ run(); +CurrentApplication::set(new Application(MAKO_APPLICATION_PATH))->run(); diff --git a/frameworks/PHP/mark/mark.dockerfile b/frameworks/PHP/mark/mark.dockerfile index 7f6b8180969..05400be1cfa 100644 --- a/frameworks/PHP/mark/mark.dockerfile +++ b/frameworks/PHP/mark/mark.dockerfile @@ -5,20 +5,20 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq php8.4-cli php8.4-pgsql php8.4-xml > /dev/null + apt-get install -yqq php8.5-cli php8.5-pgsql php8.5-xml > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev git > /dev/null -RUN pecl install event-3.1.3 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev git > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini -COPY php.ini /etc/php/8.4/cli/php.ini +COPY php.ini /etc/php/8.5/cli/php.ini ADD ./ /mark WORKDIR /mark RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -RUN sed -i "s|opcache.jit=off|opcache.jit=tracing|g" /etc/php/8.4/cli/conf.d/10-opcache.ini +#RUN sed -i "s|opcache.jit=off|opcache.jit=tracing|g" /etc/php/8.5/cli/conf.d/10-opcache.ini EXPOSE 8080 diff --git a/frameworks/PHP/mark/start.php b/frameworks/PHP/mark/start.php index b1f96ce9ffd..b785005e679 100644 --- a/frameworks/PHP/mark/start.php +++ b/frameworks/PHP/mark/start.php @@ -27,12 +27,12 @@ ], \json_encode(['message' => 'Hello, World!'])); }); -$date = gmdate(DATE_RFC7231); +$date = gmdate('D, d M Y H:i:s \G\M\T'); $api->onWorkerStart = static function () { Timer::add(1, function () { global $date; - $date = gmdate(DATE_RFC7231); + $date = gmdate('D, d M Y H:i:s \G\M\T'); }); }; diff --git a/frameworks/PHP/nette/nette.dockerfile b/frameworks/PHP/nette/nette.dockerfile index 0e66d630510..dde675a0e1e 100644 --- a/frameworks/PHP/nette/nette.dockerfile +++ b/frameworks/PHP/nette/nette.dockerfile @@ -5,9 +5,9 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get install -yqq nginx git unzip \ - php8.4-fpm php8.4-mysql php8.4-xml php8.4-mbstring php8.4-intl php8.4-dev php8.4-curl > /dev/null + php8.5-fpm php8.5-mysql php8.5-xml php8.5-mbstring php8.5-intl php8.5-dev php8.5-curl > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /nette COPY --link . . @@ -17,11 +17,11 @@ COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /nette EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /nette/deploy/nginx.conf 2>&1 > /dev/stderr diff --git a/frameworks/PHP/php/apc.php b/frameworks/PHP/php/apc.php index 78e01fb4430..1ed4e7e4d1c 100644 --- a/frameworks/PHP/php/apc.php +++ b/frameworks/PHP/php/apc.php @@ -70,11 +70,11 @@ function defaults($d,$v) { } // operation constants -define('OB_HOST_STATS',1); -define('OB_SYS_CACHE',2); -define('OB_USER_CACHE',3); -define('OB_SYS_CACHE_DIR',4); -define('OB_VERSION_CHECK',9); +const OB_HOST_STATS = 1; +const OB_SYS_CACHE = 2; +const OB_USER_CACHE = 3; +const OB_SYS_CACHE_DIR = 4; +const OB_VERSION_CHECK = 9; // check validity of input variables $vardom=array( diff --git a/frameworks/PHP/php/deploy/eloquent/composer.json b/frameworks/PHP/php/deploy/eloquent/composer.json index e75de3f79ad..ebb6a48c6c9 100644 --- a/frameworks/PHP/php/deploy/eloquent/composer.json +++ b/frameworks/PHP/php/deploy/eloquent/composer.json @@ -1,7 +1,20 @@ { "require": { - "illuminate/database": "8.16.*", - "illuminate/events": "8.16.*", - "illuminate/container": "8.16.*" + "illuminate/database": "11.*", + "illuminate/events": "11.*", + "illuminate/container": "11.*" + }, + "replace": { + "symfony/polyfill-ctype": "*", + "symfony/polyfill-iconv": "*", + "symfony/polyfill-mbstring":"*", + "symfony/polyfill-php72": "*", + "symfony/polyfill-php73": "*", + "symfony/polyfill-php74": "*", + "symfony/polyfill-php80": "*", + "symfony/polyfill-php81": "*", + "symfony/polyfill-php82": "*", + "symfony/polyfill-php83": "*", + "symfony/polyfill-php84": "*" } } \ No newline at end of file diff --git a/frameworks/PHP/php/php-caddy.dockerfile b/frameworks/PHP/php/php-caddy.dockerfile index 3be7ccf8b61..34b48756849 100644 --- a/frameworks/PHP/php/php-caddy.dockerfile +++ b/frameworks/PHP/php/php-caddy.dockerfile @@ -7,9 +7,9 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq RUN apt-get install -yqq git unzip curl \ - php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql > /dev/null + php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ # Install Caddyserver RUN apt-get install -y debian-keyring debian-archive-keyring apt-transport-https > /dev/null \ @@ -20,11 +20,11 @@ RUN apt-get install -y debian-keyring debian-archive-keyring apt-transport-https ADD ./ /php WORKDIR /php -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /php EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ caddy run --config deploy/caddy/Caddyfile diff --git a/frameworks/PHP/php/php-eloquent.dockerfile b/frameworks/PHP/php/php-eloquent.dockerfile index ea2e74e1c9a..b912febd2a1 100644 --- a/frameworks/PHP/php/php-eloquent.dockerfile +++ b/frameworks/PHP/php/php-eloquent.dockerfile @@ -5,16 +5,17 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq nginx git unzip php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql php8.4-mbstring php8.4-dev > /dev/null + apt-get install -yqq nginx git unzip \ + php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql php8.5-mbstring php8.5-curl > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ ADD ./ /php WORKDIR /php -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; COPY deploy/eloquent/composer* ./ RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet @@ -23,5 +24,5 @@ RUN chmod -R 777 /php EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /php/deploy/nginx7.conf -g "daemon off;" diff --git a/frameworks/PHP/php/php-franken.dockerfile b/frameworks/PHP/php/php-franken.dockerfile index 747a3722169..26157202e87 100644 --- a/frameworks/PHP/php/php-franken.dockerfile +++ b/frameworks/PHP/php/php-franken.dockerfile @@ -1,10 +1,9 @@ -FROM dunglas/frankenphp +FROM dunglas/frankenphp:php8.5 # add additional extensions here: RUN install-php-extensions \ pdo_mysql \ - zip \ - opcache > /dev/null + zip > /dev/null COPY --link deploy/franken/Caddyfile /etc/frankenphp/Caddyfile diff --git a/frameworks/PHP/php/php-h2o.dockerfile b/frameworks/PHP/php/php-h2o.dockerfile index a722b660011..013c6de55c0 100644 --- a/frameworks/PHP/php/php-h2o.dockerfile +++ b/frameworks/PHP/php/php-h2o.dockerfile @@ -41,7 +41,7 @@ RUN apt-get install \ FROM "ubuntu:${UBUNTU_VERSION}" -ARG PHP_VERSION=8.4 +ARG PHP_VERSION=8.5 ENV TZ=America/Los_Angeles @@ -75,5 +75,5 @@ ARG TFB_TEST_DATABASE ARG TFB_TEST_NAME CMD sed -i "s/num-threads: x/num-threads: $((2 * $(nproc)))/g" /opt/h2o/etc/h2o.conf && \ - service php8.4-fpm start && \ + service php8.5-fpm start && \ /opt/h2o/bin/h2o -c /opt/h2o/etc/h2o.conf diff --git a/frameworks/PHP/php/php-laravel-query-builder.dockerfile b/frameworks/PHP/php/php-laravel-query-builder.dockerfile index ea2e74e1c9a..0edff7f49e0 100644 --- a/frameworks/PHP/php/php-laravel-query-builder.dockerfile +++ b/frameworks/PHP/php/php-laravel-query-builder.dockerfile @@ -5,16 +5,16 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq nginx git unzip php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql php8.4-mbstring php8.4-dev > /dev/null + apt-get install -yqq nginx git unzip php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql php8.5-mbstring php8.5-dev > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ ADD ./ /php WORKDIR /php -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; COPY deploy/eloquent/composer* ./ RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet @@ -23,5 +23,5 @@ RUN chmod -R 777 /php EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /php/deploy/nginx7.conf -g "daemon off;" diff --git a/frameworks/PHP/php/php-pgsql-raw.dockerfile b/frameworks/PHP/php/php-pgsql-raw.dockerfile index c3d3c922718..2f149f52fb0 100644 --- a/frameworks/PHP/php/php-pgsql-raw.dockerfile +++ b/frameworks/PHP/php/php-pgsql-raw.dockerfile @@ -5,9 +5,9 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq nginx git unzip php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-pgsql > /dev/null + apt-get install -yqq nginx git unzip php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-pgsql > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ ADD ./ /php WORKDIR /php @@ -17,11 +17,11 @@ RUN sed -i "s|PDO('mysql:|PDO('pgsql:|g" dbquery.php RUN sed -i "s|PDO('mysql:|PDO('pgsql:|g" fortune.php RUN sed -i "s|PDO('mysql:|PDO('pgsql:|g" updateraw.php -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /php EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /php/deploy/nginx7.conf -g "daemon off;" diff --git a/frameworks/PHP/php/php-pools.dockerfile b/frameworks/PHP/php/php-pools.dockerfile index e217f448e88..4da9000d414 100644 --- a/frameworks/PHP/php/php-pools.dockerfile +++ b/frameworks/PHP/php/php-pools.dockerfile @@ -5,19 +5,19 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq nginx git unzip php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql > /dev/null + apt-get install -yqq nginx git unzip php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ ADD ./ /php WORKDIR /php -COPY deploy/conf/php-fpm-pools.conf /etc/php/8.4/fpm/php-fpm.conf -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 512|pm.max_children = 256|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +COPY deploy/conf/php-fpm-pools.conf /etc/php/8.5/fpm/php-fpm.conf +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 512|pm.max_children = 256|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /php EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /php/deploy/nginx-pools.conf -g "daemon off;" diff --git a/frameworks/PHP/php/php-raw7-tcp.dockerfile b/frameworks/PHP/php/php-raw7-tcp.dockerfile index 2dde7c65ee0..989a6a27e24 100644 --- a/frameworks/PHP/php/php-raw7-tcp.dockerfile +++ b/frameworks/PHP/php/php-raw7-tcp.dockerfile @@ -5,21 +5,21 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq nginx git unzip php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql > /dev/null + apt-get install -yqq nginx git unzip php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ ADD ./ /php WORKDIR /php -RUN sed -i "s|listen = /run/php/php-fpm.sock|listen = 127.0.0.1:9001|g" /etc/php/8.4/fpm/php-fpm.conf +RUN sed -i "s|listen = /run/php/php-fpm.sock|listen = 127.0.0.1:9001|g" /etc/php/8.5/fpm/php-fpm.conf RUN sed -i "s|server unix:/var/run/php/php-fpm.sock;|server 127.0.0.1:9001;|g" deploy/nginx7.conf -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /php EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /php/deploy/nginx7.conf -g "daemon off;" diff --git a/frameworks/PHP/php/php-workerman.dockerfile b/frameworks/PHP/php/php-workerman.dockerfile index 40ce5e187af..ac049780535 100644 --- a/frameworks/PHP/php/php-workerman.dockerfile +++ b/frameworks/PHP/php/php-workerman.dockerfile @@ -7,12 +7,12 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq RUN apt-get install -yqq git unzip \ - php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql > /dev/null + php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql > /dev/null -RUN apt-get install -y php-pear php8.4-dev php8.4-xml libevent-dev > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev php8.5-xml libevent-dev > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini -COPY deploy/workerman/cli-php.ini /etc/php/8.4/cli/conf.d/20-adapterman.ini +COPY deploy/workerman/cli-php.ini /etc/php/8.5/cli/conf.d/20-adapterman.ini COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer diff --git a/frameworks/PHP/php/php.dockerfile b/frameworks/PHP/php/php.dockerfile index 495e54b5631..cdf703dddfd 100644 --- a/frameworks/PHP/php/php.dockerfile +++ b/frameworks/PHP/php/php.dockerfile @@ -6,19 +6,18 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq RUN apt-get install -yqq nginx git unzip \ - php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql > /dev/null + php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ ADD ./ /php WORKDIR /php -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; -RUN sed -i "s|opcache.jit=off|;opcache.jit=off|g" /etc/php/8.4/fpm/conf.d/10-opcache.ini +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /php EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /php/deploy/nginx7.conf -g "daemon off;" diff --git a/frameworks/PHP/piko/piko-postgres.dockerfile b/frameworks/PHP/piko/piko-postgres.dockerfile index 6f9b970d864..a274ebaea63 100644 --- a/frameworks/PHP/piko/piko-postgres.dockerfile +++ b/frameworks/PHP/piko/piko-postgres.dockerfile @@ -6,9 +6,9 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php -RUN apt-get install -yqq nginx git unzip php8.4-fpm php8.4-pgsql > /dev/null +RUN apt-get install -yqq nginx git unzip php8.5-fpm php8.5-pgsql > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /piko COPY --link . . @@ -17,7 +17,7 @@ COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /piko @@ -25,4 +25,4 @@ EXPOSE 8080 CMD set -e; \ /usr/sbin/nginx -c /piko/deploy/nginx.conf 2>&1 > /dev/stderr & \ - exec /usr/sbin/php-fpm8.4 --nodaemonize --fpm-config /etc/php/8.4/fpm/php-fpm.conf + exec /usr/sbin/php-fpm8.5 --nodaemonize --fpm-config /etc/php/8.5/fpm/php-fpm.conf diff --git a/frameworks/PHP/piko/piko.dockerfile b/frameworks/PHP/piko/piko.dockerfile index e525d2b64d7..88bcfac4682 100644 --- a/frameworks/PHP/piko/piko.dockerfile +++ b/frameworks/PHP/piko/piko.dockerfile @@ -4,9 +4,9 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php -RUN apt-get install -yqq nginx git unzip php8.4-fpm php8.4-mysql > /dev/null +RUN apt-get install -yqq nginx git unzip php8.5-fpm php8.5-mysql > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /piko COPY --link . . @@ -15,11 +15,11 @@ COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /piko EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /piko/deploy/nginx.conf 2>&1 > /dev/stderr diff --git a/frameworks/PHP/reactphp/reactphp-libuv.dockerfile b/frameworks/PHP/reactphp/reactphp-libuv.dockerfile index 48126b5c59c..96040a738ca 100644 --- a/frameworks/PHP/reactphp/reactphp-libuv.dockerfile +++ b/frameworks/PHP/reactphp/reactphp-libuv.dockerfile @@ -6,23 +6,23 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null RUN apt-get update -yqq > /dev/null && \ apt-get install -yqq git unzip wget curl build-essential \ - php8.4-cli php8.4-mbstring php8.4-dev php8.4-xml > /dev/null + php8.5-cli php8.5-mbstring php8.5-dev php8.5-xml > /dev/null # An extension is required! # We deal with concurrencies over 1k, which stream_select doesn't support. # libuv RUN apt-get install -yqq libuv1-dev > /dev/null \ && pecl install uv-beta > /dev/null \ - && echo "extension=uv.so" > /etc/php/8.4/cli/conf.d/uv.ini + && echo "extension=uv.so" > /etc/php/8.5/cli/conf.d/uv.ini # libevent # RUN apt-get install -y libevent-dev > /dev/null \ # && pecl install event-3.1.4 > /dev/null \ -# && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +# && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY --link deploy/conf/* /etc/php/8.4/cli/conf.d/ +COPY --link deploy/conf/* /etc/php/8.5/cli/conf.d/ WORKDIR /reactphp COPY --link . . diff --git a/frameworks/PHP/reactphp/reactphp.dockerfile b/frameworks/PHP/reactphp/reactphp.dockerfile index 0ecb546a1c3..f6f3cacbd6f 100644 --- a/frameworks/PHP/reactphp/reactphp.dockerfile +++ b/frameworks/PHP/reactphp/reactphp.dockerfile @@ -6,23 +6,23 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null RUN apt-get update -yqq > /dev/null && \ apt-get install -yqq git unzip wget curl build-essential \ - php8.4-cli php8.4-mbstring php8.4-dev php8.4-xml > /dev/null + php8.5-cli php8.5-mbstring php8.5-dev php8.5-xml > /dev/null # An extension is required! # We deal with concurrencies over 1k, which stream_select doesn't support. # libuv # RUN apt-get install -yqq libuv1-dev > /dev/null \ # && pecl install uv-beta > /dev/null \ -# && echo "extension=uv.so" > /etc/php/8.4/cli/conf.d/uv.ini +# && echo "extension=uv.so" > /etc/php/8.5/cli/conf.d/uv.ini # libevent RUN apt-get install -y libevent-dev > /dev/null \ && pecl install event-3.1.4 > /dev/null \ - && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini + && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY --link deploy/conf/* /etc/php/8.4/cli/conf.d/ +COPY --link deploy/conf/* /etc/php/8.5/cli/conf.d/ WORKDIR /reactphp COPY --link . . diff --git a/frameworks/PHP/ripple/ripple.dockerfile b/frameworks/PHP/ripple/ripple.dockerfile index 138d91d0918..796dce5165f 100644 --- a/frameworks/PHP/ripple/ripple.dockerfile +++ b/frameworks/PHP/ripple/ripple.dockerfile @@ -1,4 +1,4 @@ -FROM php:8.3-cli +FROM php:8.5-cli RUN apt-get update -yqq >> /dev/null RUN apt-get install -y libevent-dev \ @@ -10,7 +10,6 @@ RUN apt-get install -y libevent-dev \ RUN docker-php-ext-install pdo_mysql \ ffi \ - opcache \ posix \ pcntl \ sockets >> /dev/null diff --git a/frameworks/PHP/ripple/server.php b/frameworks/PHP/ripple/server.php index 7d197c53a89..400e9fd574b 100644 --- a/frameworks/PHP/ripple/server.php +++ b/frameworks/PHP/ripple/server.php @@ -5,7 +5,7 @@ use Ripple\Database\Interface\AbstractResultSet; use Ripple\Database\MySQL\Client; use Ripple\Net\Http\Server; -use Ripple\Net\Http\Server\Request; +use Ripple\Net\Http\Request; use Ripple\Sync\Channel; use Ripple\Sync\WaitGroup; use Ripple\Worker; diff --git a/frameworks/PHP/slim/server.php b/frameworks/PHP/slim/server.php index 7eafd061037..1fb5665fe0d 100644 --- a/frameworks/PHP/slim/server.php +++ b/frameworks/PHP/slim/server.php @@ -39,9 +39,9 @@ class HeaderDate public static function init(): void { - self::$date = self::NAME . gmdate(DATE_RFC7231); + self::$date = self::NAME . gmdate('D, d M Y H:i:s \G\M\T'); Timer::add(1, static function() { - self::$date = self::NAME . gmdate(DATE_RFC7231); + self::$date = self::NAME . gmdate('D, d M Y H:i:s \G\M\T'); }); } } \ No newline at end of file diff --git a/frameworks/PHP/slim/slim-workerman-pgsql.dockerfile b/frameworks/PHP/slim/slim-workerman-pgsql.dockerfile index 8a06648dd86..aedf38ca656 100644 --- a/frameworks/PHP/slim/slim-workerman-pgsql.dockerfile +++ b/frameworks/PHP/slim/slim-workerman-pgsql.dockerfile @@ -8,14 +8,14 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ RUN apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq git \ - php8.4-cli php8.4-pgsql php8.4-mbstring php8.4-xml php8.4-curl > /dev/null + php8.5-cli php8.5-pgsql php8.5-mbstring php8.5-xml php8.5-curl > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini -COPY deploy/conf/cli-php.ini /etc/php/8.4/cli/conf.d/20-adapterman.ini +COPY deploy/conf/cli-php.ini /etc/php/8.5/cli/conf.d/20-adapterman.ini WORKDIR /slim COPY --link . . diff --git a/frameworks/PHP/slim/slim-workerman.dockerfile b/frameworks/PHP/slim/slim-workerman.dockerfile index a8c535bb05c..1795da7a5b7 100644 --- a/frameworks/PHP/slim/slim-workerman.dockerfile +++ b/frameworks/PHP/slim/slim-workerman.dockerfile @@ -7,14 +7,14 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get update -yqq > /dev/null && apt-get install -yqq git \ - php8.4-cli php8.4-mysql php8.4-mbstring php8.4-xml php8.4-curl > /dev/null + php8.5-cli php8.5-mysql php8.5-mbstring php8.5-xml php8.5-curl > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini -COPY deploy/conf/cli-php.ini /etc/php/8.4/cli/conf.d/20-adapterman.ini +COPY deploy/conf/cli-php.ini /etc/php/8.5/cli/conf.d/20-adapterman.ini WORKDIR /slim COPY --link . . diff --git a/frameworks/PHP/slim/slim.dockerfile b/frameworks/PHP/slim/slim.dockerfile index c81bf1e051f..496497d65ee 100644 --- a/frameworks/PHP/slim/slim.dockerfile +++ b/frameworks/PHP/slim/slim.dockerfile @@ -7,16 +7,16 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq nginx git unzip \ - php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql php8.4-xml php8.4-curl > /dev/null + php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql php8.5-xml php8.5-curl > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /slim COPY --link . . -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet @@ -24,5 +24,5 @@ RUN chmod -R 777 /slim EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /slim/deploy/nginx.conf diff --git a/frameworks/PHP/spiral/spiral.dockerfile b/frameworks/PHP/spiral/spiral.dockerfile index 22f390d0e49..5dc788a4e1d 100644 --- a/frameworks/PHP/spiral/spiral.dockerfile +++ b/frameworks/PHP/spiral/spiral.dockerfile @@ -1,10 +1,9 @@ -FROM php:8.4-cli +FROM php:8.5-cli RUN apt-get update -yqq > /dev/null && apt-get install -yqq git unzip > /dev/null COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer RUN docker-php-ext-install \ - opcache \ pdo_mysql \ sockets > /dev/null diff --git a/frameworks/PHP/symfony/composer.json b/frameworks/PHP/symfony/composer.json index f6bfbca31d6..9061d99d608 100644 --- a/frameworks/PHP/symfony/composer.json +++ b/frameworks/PHP/symfony/composer.json @@ -41,6 +41,7 @@ "replace": { "symfony/polyfill-ctype": "*", "symfony/polyfill-iconv": "*", + "symfony/polyfill-mbstring":"*", "symfony/polyfill-php72": "*", "symfony/polyfill-php73": "*", "symfony/polyfill-php74": "*", diff --git a/frameworks/PHP/symfony/config/packages/doctrine.yaml b/frameworks/PHP/symfony/config/packages/doctrine.yaml index 6d22e583379..4aea981408f 100644 --- a/frameworks/PHP/symfony/config/packages/doctrine.yaml +++ b/frameworks/PHP/symfony/config/packages/doctrine.yaml @@ -11,7 +11,6 @@ doctrine: !php/const \PDO::ATTR_PERSISTENT: true url: '%env(resolve:DATABASE_URL)%' orm: - auto_generate_proxy_classes: true naming_strategy: doctrine.orm.naming_strategy.default auto_mapping: true mappings: diff --git a/frameworks/PHP/symfony/config/packages/prod/doctrine.yaml b/frameworks/PHP/symfony/config/packages/prod/doctrine.yaml index 93d4ec59e8d..b9ce62903f1 100644 --- a/frameworks/PHP/symfony/config/packages/prod/doctrine.yaml +++ b/frameworks/PHP/symfony/config/packages/prod/doctrine.yaml @@ -1,6 +1,5 @@ doctrine: orm: - auto_generate_proxy_classes: false metadata_cache_driver: type: pool pool: doctrine.system_cache_pool diff --git a/frameworks/PHP/symfony/src/Controller/DbRawController.php b/frameworks/PHP/symfony/src/Controller/DbRawController.php index 098de3246ef..616d0218da4 100644 --- a/frameworks/PHP/symfony/src/Controller/DbRawController.php +++ b/frameworks/PHP/symfony/src/Controller/DbRawController.php @@ -3,7 +3,6 @@ namespace App\Controller; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\FetchMode; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; @@ -22,8 +21,7 @@ public function __construct(Connection $connection) public function db(): JsonResponse { - $statement = $this->connection->prepare('SELECT id,randomNumber FROM World WHERE id = ?'); - $world = $statement->execute([mt_rand(1, 10000)]); + $world = $this->connection->executeQuery('SELECT id,randomNumber FROM World WHERE id = ?', [mt_rand(1, 10000)]); return new JsonResponse($world->fetchAssociative()); } @@ -40,7 +38,8 @@ public function queries(Request $request): JsonResponse $statement = $this->connection->prepare('SELECT id,randomNumber FROM World WHERE id = ?'); for ($i = 0; $i < $queries; ++$i) { - $world = $statement->execute([mt_rand(1, 10000)]); + $statement->bindValue(1, mt_rand(1, 10000)); + $world = $statement->executeQuery(); $worlds[] = $world->fetchAssociative(); } @@ -61,11 +60,12 @@ public function updates(Request $request): JsonResponse for ($i = 0; $i < $queries; ++$i) { $id = mt_rand(1, 10000); - $world = $readStatement->execute([$id]); - $world = $world->fetchAssociative(); - $writeStatement->execute( - [$world['randomNumber'] = mt_rand(1, 10000), $id] - ); + $readStatement->bindValue(1, $id); + $world = $readStatement->executeQuery(); + $world = $world->fetchAssociative(); + $writeStatement->bindValue(1, mt_rand(1, 10000)); + $writeStatement->bindValue(2, $id); + $writeStatement->executeStatement(); $worlds[] = $world; } diff --git a/frameworks/PHP/symfony/symfony-franken.dockerfile b/frameworks/PHP/symfony/symfony-franken.dockerfile index a985294ab58..e20064e6a95 100644 --- a/frameworks/PHP/symfony/symfony-franken.dockerfile +++ b/frameworks/PHP/symfony/symfony-franken.dockerfile @@ -1,8 +1,7 @@ -FROM dunglas/frankenphp:php8.4 +FROM dunglas/frankenphp:php8.5 # add additional extensions here: RUN install-php-extensions \ - opcache \ pdo_pgsql \ zip > /dev/null diff --git a/frameworks/PHP/symfony/symfony-mysql.dockerfile b/frameworks/PHP/symfony/symfony-mysql.dockerfile index 157a9179660..6fa2403d108 100644 --- a/frameworks/PHP/symfony/symfony-mysql.dockerfile +++ b/frameworks/PHP/symfony/symfony-mysql.dockerfile @@ -7,27 +7,27 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq nginx git unzip curl \ - php8.4-cli php8.4-fpm php8.4-mysql \ - php8.4-mbstring php8.4-xml php8.4-curl php8.4-dev > /dev/null + php8.5-cli php8.5-fpm php8.5-mysql \ + php8.5-mbstring php8.5-xml php8.5-curl > /dev/null COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer -COPY --link deploy/conf/* /etc/php/8.4/fpm/ +COPY --link deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /symfony COPY --link . . -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --no-scripts --quiet RUN cp deploy/mysql/.env . && composer dump-env prod && bin/console cache:clear -RUN echo "opcache.preload=/symfony/var/cache/prod/App_KernelProdContainer.preload.php" >> /etc/php/8.4/fpm/php.ini +RUN echo "opcache.preload=/symfony/var/cache/prod/App_KernelProdContainer.preload.php" >> /etc/php/8.5/fpm/php.ini EXPOSE 8080 # Uncomment next line for Laravel console error logging to be viewable in docker logs -# RUN echo "catch_workers_output = yes" >> /etc/php/8.4/fpm/php-fpm.conf +# RUN echo "catch_workers_output = yes" >> /etc/php/8.5/fpm/php-fpm.conf RUN mkdir -p /run/php -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /symfony/deploy/nginx.conf \ No newline at end of file diff --git a/frameworks/PHP/symfony/symfony-raw.dockerfile b/frameworks/PHP/symfony/symfony-raw.dockerfile index a2622d5a397..130fe781d15 100644 --- a/frameworks/PHP/symfony/symfony-raw.dockerfile +++ b/frameworks/PHP/symfony/symfony-raw.dockerfile @@ -7,27 +7,27 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq nginx git unzip curl \ - php8.4-cli php8.4-fpm php8.4-pgsql \ - php8.4-mbstring php8.4-xml php8.4-curl > /dev/null + php8.5-cli php8.5-fpm php8.5-pgsql \ + php8.5-mbstring php8.5-xml php8.5-curl > /dev/null COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer -COPY --link deploy/conf/* /etc/php/8.4/fpm/ +COPY --link deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /symfony COPY --link . . -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --no-scripts --quiet RUN cp deploy/postgresql/.env . && composer dump-env prod && bin/console cache:clear -RUN echo "opcache.preload=/symfony/var/cache/prod/App_KernelProdContainer.preload.php" >> /etc/php/8.4/fpm/php.ini +RUN echo "opcache.preload=/symfony/var/cache/prod/App_KernelProdContainer.preload.php" >> /etc/php/8.5/fpm/php.ini EXPOSE 8080 # Uncomment next line for Laravel console error logging to be viewable in docker logs -# RUN echo "catch_workers_output = yes" >> /etc/php/8.4/fpm/php-fpm.conf +# RUN echo "catch_workers_output = yes" >> /etc/php/8.5/fpm/php-fpm.conf RUN mkdir -p /run/php -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /symfony/deploy/nginx.conf diff --git a/frameworks/PHP/symfony/symfony-react.dockerfile b/frameworks/PHP/symfony/symfony-react.dockerfile index e2a47c08f73..3b57b331e76 100644 --- a/frameworks/PHP/symfony/symfony-react.dockerfile +++ b/frameworks/PHP/symfony/symfony-react.dockerfile @@ -1,8 +1,8 @@ -FROM php:8.4-cli +FROM php:8.5-cli RUN apt-get update -yqq && \ apt-get install -yqq libpq-dev libicu-dev git > /dev/null && \ - docker-php-ext-install pdo_pgsql opcache intl pcntl > /dev/null + docker-php-ext-install pdo_pgsql intl pcntl > /dev/null COPY --link deploy/swoole/php.ini /usr/local/etc/php/ WORKDIR /symfony diff --git a/frameworks/PHP/symfony/symfony-roadrunner.dockerfile b/frameworks/PHP/symfony/symfony-roadrunner.dockerfile index a388570c60f..7fae6298c8b 100644 --- a/frameworks/PHP/symfony/symfony-roadrunner.dockerfile +++ b/frameworks/PHP/symfony/symfony-roadrunner.dockerfile @@ -1,4 +1,4 @@ -FROM php:8.4-cli +FROM php:8.5-cli COPY --from=ghcr.io/roadrunner-server/roadrunner:2025.1 --link /usr/bin/rr /usr/local/bin/rr COPY --from=mlocati/php-extension-installer --link /usr/bin/install-php-extensions /usr/local/bin/ @@ -6,7 +6,6 @@ COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/compose RUN install-php-extensions \ intl \ - opcache \ pdo_pgsql \ sockets \ zip > /dev/null diff --git a/frameworks/PHP/symfony/symfony-workerman.dockerfile b/frameworks/PHP/symfony/symfony-workerman.dockerfile index 480b734100a..fe5d5ce9ba6 100644 --- a/frameworks/PHP/symfony/symfony-workerman.dockerfile +++ b/frameworks/PHP/symfony/symfony-workerman.dockerfile @@ -7,12 +7,12 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq unzip \ - php8.4-cli php8.4-pgsql php8.4-mbstring php8.4-xml php8.4-curl > /dev/null + php8.5-cli php8.5-pgsql php8.5-mbstring php8.5-xml php8.5-curl > /dev/null COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev > /dev/null && \ - pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev > /dev/null && \ + pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini WORKDIR /symfony COPY --link . . @@ -20,7 +20,7 @@ COPY --link . . RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --no-scripts --quiet RUN cp deploy/postgresql/.env . && composer dump-env prod && bin/console cache:clear -COPY --link deploy/conf/cli-php.ini /etc/php/8.4/cli/conf.d/20-adapterman.ini +COPY --link deploy/conf/cli-php.ini /etc/php/8.5/cli/conf.d/20-adapterman.ini EXPOSE 8080 diff --git a/frameworks/PHP/symfony/symfony.dockerfile b/frameworks/PHP/symfony/symfony.dockerfile index 2ce94a53eb6..6d685dfb987 100644 --- a/frameworks/PHP/symfony/symfony.dockerfile +++ b/frameworks/PHP/symfony/symfony.dockerfile @@ -7,28 +7,28 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq nginx git unzip curl \ - php8.4-bcmath php8.4-cli php8.4-fpm php8.4-pgsql \ - php8.4-mbstring php8.4-xml php8.4-curl php8.4-dev php8.4-intl > /dev/null + php8.5-bcmath php8.5-cli php8.5-fpm php8.5-pgsql \ + php8.5-mbstring php8.5-xml php8.5-curl php8.5-intl > /dev/null COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer -COPY --link deploy/conf/* /etc/php/8.4/fpm/ +COPY --link deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /symfony COPY --link . . -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --no-scripts --quiet RUN cp deploy/postgresql/.env . && composer dump-env prod && bin/console cache:clear -RUN echo "opcache.preload=/symfony/var/cache/prod/App_KernelProdContainer.preload.php" >> /etc/php/8.4/fpm/php.ini +RUN echo "opcache.preload=/symfony/var/cache/prod/App_KernelProdContainer.preload.php" >> /etc/php/8.5/fpm/php.ini EXPOSE 8080 # Uncomment next line for Laravel console error logging to be viewable in docker logs -# RUN echo "catch_workers_output = yes" >> /etc/php/8.4/fpm/php-fpm.conf +# RUN echo "catch_workers_output = yes" >> /etc/php/8.5/fpm/php-fpm.conf RUN mkdir -p /run/php -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /symfony/deploy/nginx.conf \ No newline at end of file diff --git a/frameworks/PHP/webman/support/bootstrap/Date.php b/frameworks/PHP/webman/support/bootstrap/Date.php index 0101c5ad44f..31bfccbdaff 100644 --- a/frameworks/PHP/webman/support/bootstrap/Date.php +++ b/frameworks/PHP/webman/support/bootstrap/Date.php @@ -30,9 +30,9 @@ class Date implements Bootstrap { */ public static function start($worker) { - self::$date = gmdate(DATE_RFC7231); + self::$date = gmdate('D, d M Y H:i:s \G\M\T'); Timer::add(1, function() { - self::$date = gmdate(DATE_RFC7231); + self::$date = gmdate('D, d M Y H:i:s \G\M\T'); }); } diff --git a/frameworks/PHP/webman/webman-pgsql.dockerfile b/frameworks/PHP/webman/webman-pgsql.dockerfile index 2fe12ba3529..3db45c4aed2 100644 --- a/frameworks/PHP/webman/webman-pgsql.dockerfile +++ b/frameworks/PHP/webman/webman-pgsql.dockerfile @@ -8,18 +8,18 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null -RUN apt-get install -yqq php8.4-cli php8.4-pgsql php8.4-xml > /dev/null +RUN apt-get install -yqq php8.5-cli php8.5-pgsql php8.5-xml > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get update -yqq && apt-get install -y php-pear php8.4-dev libevent-dev git > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/30-event.ini +RUN apt-get update -yqq && apt-get install -y php-pear php8.5-dev libevent-dev git > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/30-event.ini WORKDIR /webman COPY --link . . RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -COPY php.ini /etc/php/8.4/cli/conf.d/10-opcache.ini +COPY php.ini /etc/php/8.5/cli/conf.d/10-opcache.ini EXPOSE 8080 diff --git a/frameworks/PHP/webman/webman.dockerfile b/frameworks/PHP/webman/webman.dockerfile index 6020fed75ed..83ff704032d 100644 --- a/frameworks/PHP/webman/webman.dockerfile +++ b/frameworks/PHP/webman/webman.dockerfile @@ -8,18 +8,18 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null -RUN apt-get install -yqq php8.4-cli php8.4-pgsql php8.4-xml > /dev/null +RUN apt-get install -yqq php8.5-cli php8.5-pgsql php8.5-xml > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get update -yqq && apt-get install -y php-pear php8.4-dev libevent-dev git > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/30-event.ini +RUN apt-get update -yqq && apt-get install -y php-pear php8.5-dev libevent-dev git > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/30-event.ini WORKDIR /webman COPY --link . . RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -COPY php.ini /etc/php/8.4/cli/conf.d/10-opcache.ini +COPY php.ini /etc/php/8.5/cli/conf.d/10-opcache.ini EXPOSE 8080 diff --git a/frameworks/PHP/wolff/server.php b/frameworks/PHP/wolff/server.php index 507f3df619f..af725b39df4 100644 --- a/frameworks/PHP/wolff/server.php +++ b/frameworks/PHP/wolff/server.php @@ -39,9 +39,9 @@ class HeaderDate public static function init(): void { - self::$date = self::NAME . gmdate(DATE_RFC7231); + self::$date = self::NAME . gmdate('D, d M Y H:i:s \G\M\T'); Timer::add(1, static function() { - self::$date = self::NAME . gmdate(DATE_RFC7231); + self::$date = self::NAME . gmdate('D, d M Y H:i:s \G\M\T'); }); } } \ No newline at end of file diff --git a/frameworks/PHP/wolff/wolff-workerman.dockerfile b/frameworks/PHP/wolff/wolff-workerman.dockerfile index 920de95b389..0895fe91c11 100644 --- a/frameworks/PHP/wolff/wolff-workerman.dockerfile +++ b/frameworks/PHP/wolff/wolff-workerman.dockerfile @@ -7,14 +7,14 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get update -yqq > /dev/null && apt-get install -yqq git \ - php8.4-cli php8.4-mysql php8.4-mbstring php8.4-xml php8.4-curl > /dev/null + php8.5-cli php8.5-mysql php8.5-mbstring php8.5-xml php8.5-curl > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini -COPY deploy/conf/adapterman-php.ini /etc/php/8.4/cli/conf.d/20-adapterman.ini +COPY deploy/conf/adapterman-php.ini /etc/php/8.5/cli/conf.d/20-adapterman.ini WORKDIR /wolff/bench COPY --link . . diff --git a/frameworks/PHP/wolff/wolff.dockerfile b/frameworks/PHP/wolff/wolff.dockerfile index d3dfc84bfad..a722286902e 100644 --- a/frameworks/PHP/wolff/wolff.dockerfile +++ b/frameworks/PHP/wolff/wolff.dockerfile @@ -5,9 +5,9 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get install -yqq nginx git unzip \ - php8.4-fpm php8.4-mysql php8.4-xml php8.4-mbstring php8.4-intl php8.4-dev php8.4-curl > /dev/null + php8.5-fpm php8.5-mysql php8.5-xml php8.5-mbstring php8.5-intl php8.5-dev php8.5-curl > /dev/null -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /wolff COPY --link . . @@ -16,11 +16,11 @@ COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN chmod -R 777 /wolff EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /wolff/deploy/nginx.conf 2>&1 > /dev/stderr diff --git a/frameworks/PHP/workerman/workerman-jit.dockerfile b/frameworks/PHP/workerman/workerman-jit.dockerfile index 47ae11800d2..5f9aa99ee81 100644 --- a/frameworks/PHP/workerman/workerman-jit.dockerfile +++ b/frameworks/PHP/workerman/workerman-jit.dockerfile @@ -10,18 +10,18 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null -RUN apt-get install -yqq php8.4-cli php8.4-mysql php8.4-xml > /dev/null +RUN apt-get install -yqq php8.5-cli php8.5-mysql php8.5-xml > /dev/null COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev git > /dev/null && \ - pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/30-event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev git > /dev/null && \ + pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/30-event.ini WORKDIR /workerman COPY --link . . RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -COPY php-jit.ini /etc/php/8.4/cli/conf.d/10-opcache.ini +COPY php-jit.ini /etc/php/8.5/cli/conf.d/10-opcache.ini EXPOSE 8080 diff --git a/frameworks/PHP/workerman/workerman-mysql-jit.dockerfile b/frameworks/PHP/workerman/workerman-mysql-jit.dockerfile index 8992f918a0d..913e46733f5 100644 --- a/frameworks/PHP/workerman/workerman-mysql-jit.dockerfile +++ b/frameworks/PHP/workerman/workerman-mysql-jit.dockerfile @@ -10,18 +10,18 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null -RUN apt-get install -yqq php8.4-cli php8.4-mysql php8.4-xml > /dev/null +RUN apt-get install -yqq php8.5-cli php8.5-mysql php8.5-xml > /dev/null COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev git > /dev/null && \ - pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/30-event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev git > /dev/null && \ + pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/30-event.ini WORKDIR /workerman COPY --link . . RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -COPY php-jit.ini /etc/php/8.4/cli/conf.d/10-opcache.ini +COPY php-jit.ini /etc/php/8.5/cli/conf.d/10-opcache.ini EXPOSE 8080 diff --git a/frameworks/PHP/workerman/workerman-pgsql-jit.dockerfile b/frameworks/PHP/workerman/workerman-pgsql-jit.dockerfile index f1e84f54011..0eda40a8b81 100644 --- a/frameworks/PHP/workerman/workerman-pgsql-jit.dockerfile +++ b/frameworks/PHP/workerman/workerman-pgsql-jit.dockerfile @@ -10,18 +10,18 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null -RUN apt-get install -yqq php8.4-cli php8.4-pgsql php8.4-xml > /dev/null +RUN apt-get install -yqq php8.5-cli php8.5-pgsql php8.5-xml > /dev/null COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev git > /dev/null && \ - pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/30-event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev git > /dev/null && \ + pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/30-event.ini WORKDIR /workerman COPY --link . . RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -COPY php-jit.ini /etc/php/8.4/cli/conf.d/10-opcache.ini +COPY php-jit.ini /etc/php/8.5/cli/conf.d/10-opcache.ini EXPOSE 8080 diff --git a/frameworks/PHP/workerman/workerman-pgsql.dockerfile b/frameworks/PHP/workerman/workerman-pgsql.dockerfile index f8209fb7d00..b96cc229d4e 100644 --- a/frameworks/PHP/workerman/workerman-pgsql.dockerfile +++ b/frameworks/PHP/workerman/workerman-pgsql.dockerfile @@ -10,18 +10,18 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null -RUN apt-get install -yqq php8.4-cli php8.4-pgsql php8.4-xml > /dev/null +RUN apt-get install -yqq php8.5-cli php8.5-pgsql php8.5-xml > /dev/null COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev git > /dev/null && \ - pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/30-event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev git > /dev/null && \ + pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/30-event.ini WORKDIR /workerman COPY --link . . RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -COPY php.ini /etc/php/8.4/cli/php.ini +COPY php.ini /etc/php/8.5/cli/php.ini EXPOSE 8080 diff --git a/frameworks/PHP/workerman/workerman.dockerfile b/frameworks/PHP/workerman/workerman.dockerfile index 8d93101166f..4ddb640e323 100644 --- a/frameworks/PHP/workerman/workerman.dockerfile +++ b/frameworks/PHP/workerman/workerman.dockerfile @@ -10,18 +10,18 @@ RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /de RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null -RUN apt-get install -yqq php8.4-cli php8.4-mysql php8.4-xml > /dev/null +RUN apt-get install -yqq php8.5-cli php8.5-mysql php8.5-xml > /dev/null COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev git > /dev/null && \ - pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/30-event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev git > /dev/null && \ + pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/30-event.ini WORKDIR /workerman COPY --link . . RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet -COPY php.ini /etc/php/8.4/cli/php.ini +COPY php.ini /etc/php/8.5/cli/php.ini EXPOSE 8080 diff --git a/frameworks/PHP/yii2/server.php b/frameworks/PHP/yii2/server.php index 59fe04b19f1..932124b2775 100644 --- a/frameworks/PHP/yii2/server.php +++ b/frameworks/PHP/yii2/server.php @@ -34,9 +34,9 @@ class WorkerTimer public static function init() { - self::$date = 'Date: ' . gmdate(DATE_RFC7231); + self::$date = 'Date: ' . gmdate('D, d M Y H:i:s \G\M\T'); Timer::add(1, function() { - WorkerTimer::$date = 'Date: ' . gmdate(DATE_RFC7231); + WorkerTimer::$date = 'Date: ' . gmdate('D, d M Y H:i:s \G\M\T'); }); } } diff --git a/frameworks/PHP/yii2/yii2-raw.dockerfile b/frameworks/PHP/yii2/yii2-raw.dockerfile index cfb0bf78a38..d826e74f4e1 100644 --- a/frameworks/PHP/yii2/yii2-raw.dockerfile +++ b/frameworks/PHP/yii2/yii2-raw.dockerfile @@ -5,20 +5,20 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq nginx git unzip php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql php8.4-mbstring php8.4-dev > /dev/null + apt-get install -yqq nginx git unzip php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql php8.5-mbstring php8.5-dev > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /yii2 COPY --link . . -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /yii2/deploy/nginx.conf diff --git a/frameworks/PHP/yii2/yii2-workerman.dockerfile b/frameworks/PHP/yii2/yii2-workerman.dockerfile index 204aeaf58a8..ec889ad9d97 100644 --- a/frameworks/PHP/yii2/yii2-workerman.dockerfile +++ b/frameworks/PHP/yii2/yii2-workerman.dockerfile @@ -5,14 +5,14 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq git php8.4-cli php8.4-mysql php8.4-mbstring php8.4-xml > /dev/null + apt-get install -yqq git php8.5-cli php8.5-mysql php8.5-mbstring php8.5-xml > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.4-dev libevent-dev > /dev/null -RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.4/cli/conf.d/event.ini +RUN apt-get install -y php-pear php8.5-dev libevent-dev > /dev/null +RUN pecl install event-3.1.4 > /dev/null && echo "extension=event.so" > /etc/php/8.5/cli/conf.d/event.ini -COPY --link deploy/conf/cli-php.ini /etc/php/8.4/cli/conf.d/20-adapterman.ini +COPY --link deploy/conf/cli-php.ini /etc/php/8.5/cli/conf.d/20-adapterman.ini WORKDIR /yii2 COPY --link . . diff --git a/frameworks/PHP/yii2/yii2.dockerfile b/frameworks/PHP/yii2/yii2.dockerfile index cfb0bf78a38..d826e74f4e1 100644 --- a/frameworks/PHP/yii2/yii2.dockerfile +++ b/frameworks/PHP/yii2/yii2.dockerfile @@ -5,20 +5,20 @@ ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq nginx git unzip php8.4 php8.4-common php8.4-cli php8.4-fpm php8.4-mysql php8.4-mbstring php8.4-dev > /dev/null + apt-get install -yqq nginx git unzip php8.5 php8.5-common php8.5-cli php8.5-fpm php8.5-mysql php8.5-mbstring php8.5-dev > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY deploy/conf/* /etc/php/8.4/fpm/ +COPY deploy/conf/* /etc/php/8.5/fpm/ WORKDIR /yii2 COPY --link . . -RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.4/fpm/php-fpm.conf ; fi; +RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.5/fpm/php-fpm.conf ; fi; RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet EXPOSE 8080 -CMD service php8.4-fpm start && \ +CMD service php8.5-fpm start && \ nginx -c /yii2/deploy/nginx.conf diff --git a/frameworks/Perl/plack/benchmark_config.json b/frameworks/Perl/plack/benchmark_config.json index 6cf3d2a19ff..d3b26a6f800 100644 --- a/frameworks/Perl/plack/benchmark_config.json +++ b/frameworks/Perl/plack/benchmark_config.json @@ -39,6 +39,7 @@ "database_os": "Linux", "display_name": "plack-async", "notes": "", + "tags": ["broken"], "versus": "plack" } }] diff --git a/frameworks/Python/cherrypy/app.py b/frameworks/Python/cherrypy/app.py index bf090cfd69b..d92177d379c 100755 --- a/frameworks/Python/cherrypy/app.py +++ b/frameworks/Python/cherrypy/app.py @@ -153,8 +153,8 @@ def fortunes(self): cherrypy.tools.db = SATool() cherrypy.server.socket_host = '0.0.0.0' cherrypy.server.socket_port = 8080 - cherrypy.server.thread_pool = workers - cherrypy.server.socket_queue_size = 25 + cherrypy.server.thread_pool = workers * 2 + cherrypy.server.socket_queue_size = 100 cherrypy.quickstart(CherryPyBenchmark(), '', { '/': { diff --git a/frameworks/Python/cherrypy/benchmark_config.json b/frameworks/Python/cherrypy/benchmark_config.json index 62e51834960..9d4f3c1c8ef 100644 --- a/frameworks/Python/cherrypy/benchmark_config.json +++ b/frameworks/Python/cherrypy/benchmark_config.json @@ -2,29 +2,6 @@ "framework": "cherrypy", "tests": [{ "default": { - "json_url": "/json", - "db_url": "/db", - "query_url": "/queries?queries=", - "fortune_url": "/fortunes", - "update_url": "/updates?queries=", - "plaintext_url": "/plaintext", - "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "database": "MySQL", - "framework": "None", - "language": "Python", - "flavor": "Python2", - "orm": "Full", - "platform": "None", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "CherryPy [py2]", - "notes": "CPython 2.7", - "tags": ["broken"] - }, - "py3": { "json_url": "/json", "db_url": "/db", "query_url": "/queries?queries=", @@ -44,7 +21,7 @@ "os": "Linux", "database_os": "Linux", "display_name": "CherryPy", - "notes": "CPython 3.9" + "notes": "CPython 3.13" } }] } diff --git a/frameworks/Python/cherrypy/cherrypy-py3.dockerfile b/frameworks/Python/cherrypy/cherrypy-py3.dockerfile deleted file mode 100644 index 8a8af2211d8..00000000000 --- a/frameworks/Python/cherrypy/cherrypy-py3.dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:3.9-bullseye - -ADD ./ /cherrypy - -WORKDIR /cherrypy - -RUN pip3 install -r /cherrypy/requirements.txt - -EXPOSE 8080 - -CMD python3 app.py diff --git a/frameworks/Python/cherrypy/cherrypy.dockerfile b/frameworks/Python/cherrypy/cherrypy.dockerfile index ccf988da6a6..eae3768b5fe 100644 --- a/frameworks/Python/cherrypy/cherrypy.dockerfile +++ b/frameworks/Python/cherrypy/cherrypy.dockerfile @@ -1,11 +1,11 @@ -FROM python:2.7.15-stretch +FROM python:3.13-bullseye ADD ./ /cherrypy WORKDIR /cherrypy -RUN pip install -r /cherrypy/requirements.txt +RUN pip3 install -r /cherrypy/requirements.txt EXPOSE 8080 -CMD python app.py +CMD python3 app.py diff --git a/frameworks/Python/cherrypy/requirements.txt b/frameworks/Python/cherrypy/requirements.txt index fc63cbf2a2a..f71069db433 100644 --- a/frameworks/Python/cherrypy/requirements.txt +++ b/frameworks/Python/cherrypy/requirements.txt @@ -1,10 +1,6 @@ -cheroot==8.6.0 -CherryPy==17.4.2 ; python_version=='2.7' CherryPy==18.8.0 ; python_version>'3.5' -more-itertools==4.1.0 -mysqlclient==1.3.12 -portend==2.2 -pytz==2017.3 -six==1.11.0 -SQLAlchemy==1.4.47 -tempora==1.10 +mysqlclient==2.2.4 +pytz==2024.1 +SQLAlchemy==1.4.53 +six==1.17.0 +legacy-cgi==2.6.4 \ No newline at end of file diff --git a/frameworks/Python/emmett55/app.py b/frameworks/Python/emmett55/app.py index e417e8f75fa..d24f7e98d62 100644 --- a/frameworks/Python/emmett55/app.py +++ b/frameworks/Python/emmett55/app.py @@ -3,12 +3,19 @@ from random import randint, sample import asyncpg -from emmett55 import App, Pipe, current, request, response +from emmett55 import App, Pipe, request, response from emmett55.extensions import Extension, Signals, listen_signal -from emmett55.tools import service +from emmett55.tools import ServicePipe from renoir import Renoir +class NoResetConnection(asyncpg.Connection): + __slots__ = () + + def get_reset_query(self): + return "" + + class AsyncPG(Extension): __slots__ = ["pool"] @@ -23,10 +30,9 @@ async def build_pool(self): database='hello_world', host='tfb-database', port=5432, - min_size=16, - max_size=16, - max_queries=64_000_000_000, - max_inactive_connection_lifetime=0 + min_size=4, + max_size=4, + connection_class=NoResetConnection, ) @listen_signal(Signals.after_loop) @@ -40,18 +46,32 @@ class AsyncPGPipe(Pipe): def __init__(self, ext): self.ext = ext - async def open(self): - conn = current._db_conn = self.ext.pool.acquire() - current.db = await conn.__aenter__() + async def pipe(self, next_pipe, **kwargs): + async with self.ext.pool.acquire() as conn: + kwargs['db'] = conn + return await next_pipe(**kwargs) + - async def close(self): - await current._db_conn.__aexit__() +class TemplatePipe(Pipe): + __slots__ = ["template"] + output = "str" + + def __init__(self, template): + self.template = f"templates/{template}" + + async def pipe(self, next_pipe, **kwargs): + response.content_type = "text/html; charset=utf-8" + ctx = await next_pipe(**kwargs) + return templates.render(self.template, ctx) app = App(__name__) app.config.handle_static = False templates = Renoir() +json_routes = app.module(__name__, 'json') +json_routes.pipeline = [ServicePipe('json')] + db_ext = app.use_extension(AsyncPG) SQL_SELECT = 'SELECT "randomnumber", "id" FROM "world" WHERE id = $1' @@ -60,17 +80,15 @@ async def close(self): sort_key = itemgetter(1) -@app.route() -@service.json +@json_routes.route() async def json(): return {'message': 'Hello, World!'} -@app.route("/db", pipeline=[db_ext.pipe]) -@service.json -async def get_random_world(): +@json_routes.route("/db", pipeline=[db_ext.pipe]) +async def get_random_world(db): row_id = randint(1, 10000) - number = await current.db.fetchval(SQL_SELECT, row_id) + number = await db.fetchval(SQL_SELECT, row_id) return {'id': row_id, 'randomNumber': number} @@ -86,41 +104,32 @@ def get_qparam(): return rv -@app.route("/queries", pipeline=[db_ext.pipe]) -@service.json -async def get_random_worlds(): +@json_routes.route("/queries", pipeline=[db_ext.pipe]) +async def get_random_worlds(db): num_queries = get_qparam() row_ids = sample(range(1, 10000), num_queries) - worlds = [] - statement = await current.db.prepare(SQL_SELECT) - for row_id in row_ids: - number = await statement.fetchval(row_id) - worlds.append({'id': row_id, 'randomNumber': number}) - return worlds + rows = await db.fetchmany(SQL_SELECT, [(v,) for v in row_ids]) + return [{'id': row_id, 'randomNumber': number[0]} for row_id, number in zip(row_ids, rows)] -@app.route(pipeline=[db_ext.pipe], output='str') -async def fortunes(): - response.content_type = "text/html; charset=utf-8" - fortunes = await current.db.fetch('SELECT * FROM Fortune') +@app.route(pipeline=[TemplatePipe("fortunes.html"), db_ext.pipe]) +async def fortunes(db): + fortunes = await db.fetch('SELECT * FROM Fortune') fortunes.append(ROW_ADD) fortunes.sort(key=sort_key) - return templates.render("templates/fortunes.html", {"fortunes": fortunes}) + return {"fortunes": fortunes} -@app.route(pipeline=[db_ext.pipe]) -@service.json -async def updates(): +@json_routes.route(pipeline=[db_ext.pipe]) +async def updates(db): num_queries = get_qparam() updates = list(zip( sample(range(1, 10000), num_queries), sorted(sample(range(1, 10000), num_queries)) )) worlds = [{'id': row_id, 'randomNumber': number} for row_id, number in updates] - statement = await current.db.prepare(SQL_SELECT) - for row_id, _ in updates: - await statement.fetchval(row_id) - await current.db.executemany(SQL_UPDATE, updates) + await db.executemany(SQL_SELECT, [(i[0],) for i in updates]) + await db.executemany(SQL_UPDATE, updates) return worlds diff --git a/frameworks/Python/emmett55/emmett55.dockerfile b/frameworks/Python/emmett55/emmett55.dockerfile index 49438fd442d..a3e5039a72f 100644 --- a/frameworks/Python/emmett55/emmett55.dockerfile +++ b/frameworks/Python/emmett55/emmett55.dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11-slim +FROM python:3.13-slim ADD ./ /emmett55 diff --git a/frameworks/Python/emmett55/requirements.txt b/frameworks/Python/emmett55/requirements.txt index 341cf834957..8641ee5f52f 100644 --- a/frameworks/Python/emmett55/requirements.txt +++ b/frameworks/Python/emmett55/requirements.txt @@ -1,3 +1,3 @@ -asyncpg==0.29.0 +asyncpg==0.30.0 emmett55[orjson,uvloop]>=1.2.0,<1.3.0 renoir==1.8.0 diff --git a/frameworks/Python/eve/benchmark_config.json b/frameworks/Python/eve/benchmark_config.json index 3e9e7cdc102..cb11c1586d1 100644 --- a/frameworks/Python/eve/benchmark_config.json +++ b/frameworks/Python/eve/benchmark_config.json @@ -18,6 +18,7 @@ "database_os": "Linux", "display_name": "Eve", "notes": "", + "tags": ["broken"], "versus": "" } }] diff --git a/frameworks/Python/eve/requirements.txt b/frameworks/Python/eve/requirements.txt index f054d6baf97..089a0d0836c 100644 --- a/frameworks/Python/eve/requirements.txt +++ b/frameworks/Python/eve/requirements.txt @@ -5,4 +5,4 @@ gunicorn==19.9.0 itsdangerous==0.24 meinheld==1.0.2 uWSGI==2.0.22 -Werkzeug==0.15.5 +Werkzeug==3.1.4 diff --git a/frameworks/Python/flask/benchmark_config.json b/frameworks/Python/flask/benchmark_config.json index dad6b8ef11a..ee505a984c0 100644 --- a/frameworks/Python/flask/benchmark_config.json +++ b/frameworks/Python/flask/benchmark_config.json @@ -45,7 +45,7 @@ "display_name": "Flask [Meinheld] [Raw]", "notes": "", "versus": "wsgi", - "tags": [ ] + "tags": [ "broken" ] }, "socketify-wsgi": { "json_url": "/json-raw", @@ -83,6 +83,7 @@ "database_os": "Linux", "display_name": "Flask [socketify.py] [PyPy3]", "notes": "PyPy", + "tags": ["broken"], "versus": "wsgi" }, "pypy": { diff --git a/frameworks/Python/granian/app_asgi.py b/frameworks/Python/granian/app_asgi.py index d7c7b732c27..b6a727e8b0e 100644 --- a/frameworks/Python/granian/app_asgi.py +++ b/frameworks/Python/granian/app_asgi.py @@ -106,7 +106,6 @@ async def route_db(scope, receive, send): async def route_queries(scope, receive, send): num_queries = get_num_queries(scope) row_ids = sample(range(1, 10000), num_queries) - worlds = [] async with pool.acquire() as connection: rows = await connection.fetchmany(SQL_SELECT, [(v,) for v in row_ids]) diff --git a/frameworks/Python/granian/granian-nogil.dockerfile b/frameworks/Python/granian/granian-nogil.dockerfile index 5f0e4045f40..566ac8cca40 100644 --- a/frameworks/Python/granian/granian-nogil.dockerfile +++ b/frameworks/Python/granian/granian-nogil.dockerfile @@ -13,4 +13,4 @@ RUN uv pip install -r requirements-nogil.txt EXPOSE 8080 -CMD uv run python run_nogil.py rsgi st +CMD uv run python run_nogil.py rsgi mt diff --git a/frameworks/Python/granian/granian-rsgi.dockerfile b/frameworks/Python/granian/granian-rsgi.dockerfile index 1eb5066dfeb..a7616266d84 100644 --- a/frameworks/Python/granian/granian-rsgi.dockerfile +++ b/frameworks/Python/granian/granian-rsgi.dockerfile @@ -8,4 +8,4 @@ RUN pip install -r /granian/requirements.txt EXPOSE 8080 -CMD python run.py rsgi st +CMD python run.py rsgi mt diff --git a/frameworks/Python/granian/requirements-nogil.txt b/frameworks/Python/granian/requirements-nogil.txt index c49d8ced726..828e24cd711 100644 --- a/frameworks/Python/granian/requirements-nogil.txt +++ b/frameworks/Python/granian/requirements-nogil.txt @@ -1 +1 @@ -granian[rloop]>=2.5.0,<2.6.0 +granian[rloop]>=2.6.0,<2.7.0 diff --git a/frameworks/Python/granian/requirements.txt b/frameworks/Python/granian/requirements.txt index 8fc318454b4..d3895189e0d 100644 --- a/frameworks/Python/granian/requirements.txt +++ b/frameworks/Python/granian/requirements.txt @@ -1,4 +1,4 @@ asyncpg==0.30.0 -granian[uvloop]>=2.5.0,<2.6.0 +granian[uvloop]>=2.6.0,<2.7.0 jinja2==3.1.6 orjson==3.11.3 diff --git a/frameworks/Python/klein/benchmark_config.json b/frameworks/Python/klein/benchmark_config.json index e43ece59d8d..e00da480751 100644 --- a/frameworks/Python/klein/benchmark_config.json +++ b/frameworks/Python/klein/benchmark_config.json @@ -21,6 +21,7 @@ "os": "Linux", "database_os": "Linux", "display_name": "Klein", + "tags": ["broken"], "notes": "CPython 2.7" } }] diff --git a/frameworks/Python/tornado/benchmark_config.json b/frameworks/Python/tornado/benchmark_config.json index a64c47a7cfe..3966265fb04 100644 --- a/frameworks/Python/tornado/benchmark_config.json +++ b/frameworks/Python/tornado/benchmark_config.json @@ -2,72 +2,6 @@ "framework": "tornado", "tests": [{ "default": { - "json_url": "/json", - "db_url": "/db", - "query_url": "/queries?queries=", - "plaintext_url": "/plaintext", - "fortune_url": "/fortunes", - "update_url": "/updates?queries=", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "MongoDB", - "framework": "None", - "language": "Python", - "flavor": "Python2", - "orm": "Raw", - "platform": "None", - "webserver": "Tornado", - "os": "Linux", - "database_os": "Linux", - "display_name": "Tornado", - "notes": "", - "versus": "tornado" - }, - "pypy2": { - "json_url": "/json", - "db_url": "/db", - "query_url": "/queries?queries=", - "plaintext_url": "/plaintext", - "fortune_url": "/fortunes", - "update_url": "/updates?queries=", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "MongoDB", - "framework": "None", - "language": "Python", - "flavor": "PyPy2", - "orm": "Raw", - "platform": "None", - "webserver": "Tornado", - "os": "Linux", - "database_os": "Linux", - "display_name": "Tornado", - "notes": "", - "versus": "tornado" - }, - "postgresql-raw": { - "db_url": "/db", - "query_url": "/queries?queries=", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "Postgres", - "framework": "None", - "language": "Python", - "flavor": "Python2", - "orm": "Raw", - "platform": "None", - "webserver": "Tornado", - "os": "Linux", - "database_os": "Linux", - "display_name": "Tornado", - "notes": "", - "versus": "tornado", - "tags": ["broken"] - }, - "py3": { "json_url": "/json", "db_url": "/db", "query_url": "/queries?queries=", @@ -90,7 +24,7 @@ "notes": "", "versus": "tornado" }, - "py3-uvloop": { + "uvloop": { "db_url": "/db", "query_url": "/queries?queries=", "fortune_url": "/fortunes", @@ -107,7 +41,7 @@ "webserver": "Tornado", "os": "Linux", "database_os": "Linux", - "display_name": "Tornado", + "display_name": "Tornado [uvloop]", "notes": "", "versus": "tornado" } diff --git a/frameworks/Python/tornado/requirements_py3_mongo.txt b/frameworks/Python/tornado/requirements_mongo.txt similarity index 100% rename from frameworks/Python/tornado/requirements_py3_mongo.txt rename to frameworks/Python/tornado/requirements_mongo.txt diff --git a/frameworks/Python/tornado/requirements_py2_mongo.txt b/frameworks/Python/tornado/requirements_py2_mongo.txt deleted file mode 100644 index ef65f2641ce..00000000000 --- a/frameworks/Python/tornado/requirements_py2_mongo.txt +++ /dev/null @@ -1,3 +0,0 @@ -tornado==5.1.1 -motor==2.0.0 -ujson==1.35 diff --git a/frameworks/Python/tornado/requirements_py2_pg.txt b/frameworks/Python/tornado/requirements_py2_pg.txt deleted file mode 100644 index 8f204caeb0a..00000000000 --- a/frameworks/Python/tornado/requirements_py2_pg.txt +++ /dev/null @@ -1,3 +0,0 @@ -tornado==5.1.1 -Momoko==2.2.4 -ujson==1.35 \ No newline at end of file diff --git a/frameworks/Python/tornado/requirements_py3_uvloop.txt b/frameworks/Python/tornado/requirements_uvloop.txt similarity index 100% rename from frameworks/Python/tornado/requirements_py3_uvloop.txt rename to frameworks/Python/tornado/requirements_uvloop.txt diff --git a/frameworks/Python/tornado/server_py3.py b/frameworks/Python/tornado/server.py similarity index 100% rename from frameworks/Python/tornado/server_py3.py rename to frameworks/Python/tornado/server.py diff --git a/frameworks/Python/tornado/server_pg.py b/frameworks/Python/tornado/server_pg.py deleted file mode 100755 index 1a354d80dbc..00000000000 --- a/frameworks/Python/tornado/server_pg.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python -import json -from random import randint -import momoko -import tornado.ioloop -import tornado.web -from tornado import gen -import tornado.options -from tornado.options import options -import tornado.httpserver -from commons import JsonHandler, JsonHelloWorldHandler, PlaintextHelloWorldHandler, BaseHandler - - -tornado.options.define('port', default=8888, type=int, help="Server port") -tornado.options.define('postgres', default="localhost", - type=str, help="PostgreSQL host") -tornado.options.define('backlog', default=8192, type=int, - help="Server backlog") - - -class SingleQueryHandler(JsonHandler): - SQL = "SELECT id, randomNumber FROM World WHERE id=%s" - - @gen.coroutine - def get(self): - - random_id = randint(1, 10000) - cursor = yield db.execute(self.SQL, (random_id,)) - row = cursor.fetchone() - response = json.dumps({self.ID: row[0], self.RANDOM_NUMBER: row[1]}) - self.finish(response) - - -class MultipleQueriesHandler(JsonHandler): - SQL = "SELECT id, randomNumber FROM World WHERE id=%s" - - @gen.coroutine - def get(self): - queries = self.get_argument(self.QUERIES, "1") - try: - queries = int(queries.strip()) - except ValueError: - queries = 1 - - queries = min(max(1, queries), 500) - worlds = [] - - cursors = yield [db.execute(self.SQL, (randint(1, 10000),)) for _ in xrange(queries)] - for cursor in cursors: - row = cursor.fetchone() - worlds.append({self.ID: row[0], self.RANDOM_NUMBER: row[1]}) - - response = json.dumps(worlds) - self.finish(response) - - -application = tornado.web.Application([ - (r"/json", JsonHelloWorldHandler), - (r"/plaintext", PlaintextHelloWorldHandler), - (r"/db", SingleQueryHandler), - (r"/queries", MultipleQueriesHandler) -], - template_path="templates" -) -application.ui_modules = {} - -if __name__ == "__main__": - tornado.options.parse_command_line() - server = tornado.httpserver.HTTPServer(application) - server.bind(options.port, backlog=options.backlog) - server.start(0) - - ioloop = tornado.ioloop.IOLoop.instance() - dsn = "user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world host=%s" % options.postgres - db = momoko.Pool(dsn, size=100, max_size=200) - ioloop.run_sync(db.connect) - ioloop.start() diff --git a/frameworks/Python/tornado/server_py2.py b/frameworks/Python/tornado/server_py2.py deleted file mode 100644 index 86d7177bccf..00000000000 --- a/frameworks/Python/tornado/server_py2.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env python - -import json -import motor -from pymongo.operations import UpdateOne -import tornado.ioloop -import tornado.web -import tornado.httpserver - -from random import randint -from tornado import gen -from tornado.options import options -from commons import JsonHandler, JsonHelloWorldHandler, PlaintextHelloWorldHandler, HtmlHandler - - -options.define('port', default=8888, type=int, help="Server port") -options.define('mongo', default='localhost', type=str, help="MongoDB host") -options.define('backlog', default=8192, type=int, help="Server backlog") - - -class SingleQueryHandler(JsonHandler): - - @gen.coroutine - def get(self): - world = yield db.world.find_one(randint(1, 10000)) - world = {self.ID: int(world['_id']), - self.RANDOM_NUMBER: int(world[self.RANDOM_NUMBER]) - } - - response = json.dumps(world) - self.finish(response) - - -class MultipleQueriesHandler(JsonHandler): - @gen.coroutine - def get(self): - try: - queries = int(self.get_argument(self.QUERIES)) - except Exception: - queries = 1 - else: - if queries < 1: - queries = 1 - elif queries > 500: - queries = 500 - - worlds = yield [db.world.find_one(randint(1, 10000)) for _ in xrange(queries)] - - worlds = [{self.ID: int(world['_id']), - self.RANDOM_NUMBER: int(world[self.RANDOM_NUMBER])} - for world in worlds] - - self.finish(json.dumps(worlds)) - - -class UpdateHandler(JsonHandler): - @gen.coroutine - def get(self): - try: - queries = int(self.get_argument(self.QUERIES)) - except Exception: - queries = 1 - else: - if queries < 1: - queries = 1 - elif queries > 500: - queries = 500 - - worlds = yield [db.world.find_one(randint(1, 10000)) for _ in xrange(queries)] - updates = [] - out = [] - - for world in worlds: - new_value = randint(1, 10000) - updates.append(UpdateOne({'_id': world['_id']}, {"$set": {self.RANDOM_NUMBER: new_value}})) - out.append({self.ID: world["_id"], self.RANDOM_NUMBER: new_value}) - - yield db.world.bulk_write(updates, ordered=False) - self.finish(json.dumps(out)) - - -class FortuneHandler(HtmlHandler): - @gen.coroutine - def get(self): - fortunes = [] - cursor = db.fortune.find() - - while (yield cursor.fetch_next): - fortunes.append(cursor.next_object()) - fortunes.append({self.ID: 0, 'message': 'Additional fortune added at request time.'}) - fortunes.sort(key=lambda f: f['message']) - self.render('fortunes.html', fortunes=fortunes) - - -application = tornado.web.Application([ - (r"/json", JsonHelloWorldHandler), - (r"/plaintext", PlaintextHelloWorldHandler), - (r"/db", SingleQueryHandler), - (r"/queries", MultipleQueriesHandler), - (r"/updates", UpdateHandler), - (r"/fortunes", FortuneHandler), -], - template_path="templates" -) -application.ui_modules = {} - -if __name__ == "__main__": - tornado.options.parse_command_line() - server = tornado.httpserver.HTTPServer(application) - server.bind(options.port, backlog=options.backlog) - server.start(0) - - ioloop = tornado.ioloop.IOLoop.instance() - db = motor.MotorClient(options.mongo, maxPoolSize=500).hello_world - ioloop.start() diff --git a/frameworks/Python/tornado/server_py3_uvloop.py b/frameworks/Python/tornado/server_uvloop.py similarity index 100% rename from frameworks/Python/tornado/server_py3_uvloop.py rename to frameworks/Python/tornado/server_uvloop.py diff --git a/frameworks/Python/tornado/tornado-postgresql-raw.dockerfile b/frameworks/Python/tornado/tornado-postgresql-raw.dockerfile deleted file mode 100644 index 6a6119bda5d..00000000000 --- a/frameworks/Python/tornado/tornado-postgresql-raw.dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:2.7.15-stretch - -ADD ./ /tornado - -WORKDIR /tornado - -RUN pip install -r /tornado/requirements_py2_pg.txt - -EXPOSE 8080 - -CMD python server_pg.py --port=8080 --postgres=tfb-database --logging=error diff --git a/frameworks/Python/tornado/tornado-py3-uvloop.dockerfile b/frameworks/Python/tornado/tornado-py3-uvloop.dockerfile deleted file mode 100644 index 2bc64e882a1..00000000000 --- a/frameworks/Python/tornado/tornado-py3-uvloop.dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:3.6.6-stretch - -ADD ./ /tornado - -WORKDIR /tornado - -RUN pip3 install -r /tornado/requirements_py3_uvloop.txt - -EXPOSE 8080 - -CMD python3 server_py3_uvloop.py --logging=error diff --git a/frameworks/Python/tornado/tornado-py3.dockerfile b/frameworks/Python/tornado/tornado-py3.dockerfile deleted file mode 100644 index 667a7a330ef..00000000000 --- a/frameworks/Python/tornado/tornado-py3.dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:3.6.6-stretch - -ADD ./ /pyramid - -WORKDIR /pyramid - -RUN pip3 install -r /pyramid/requirements_py3_mongo.txt - -EXPOSE 8080 - -CMD python3 server_py3.py --port=8080 --mongo=tfb-database --logging=error diff --git a/frameworks/Python/tornado/tornado-pypy2.dockerfile b/frameworks/Python/tornado/tornado-pypy2.dockerfile deleted file mode 100644 index 1b9d73f3032..00000000000 --- a/frameworks/Python/tornado/tornado-pypy2.dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM pypy:2-5.10 - -ADD ./ /tornado - -WORKDIR /tornado - -RUN pip install -r /tornado/requirements_py2_mongo.txt - -EXPOSE 8080 - -CMD pypy server_py2.py --port=8080 --mongo=tfb-database --logging=error diff --git a/frameworks/Python/tornado/tornado-uvloop.dockerfile b/frameworks/Python/tornado/tornado-uvloop.dockerfile new file mode 100644 index 00000000000..4fe319a75c2 --- /dev/null +++ b/frameworks/Python/tornado/tornado-uvloop.dockerfile @@ -0,0 +1,11 @@ +FROM python:3.6.6-stretch + +ADD ./ /tornado + +WORKDIR /tornado + +RUN pip3 install -r /tornado/requirements_uvloop.txt + +EXPOSE 8080 + +CMD python3 server_uvloop.py --logging=error diff --git a/frameworks/Python/tornado/tornado.dockerfile b/frameworks/Python/tornado/tornado.dockerfile index 1a1f8cdf410..aa9a33f4cdf 100644 --- a/frameworks/Python/tornado/tornado.dockerfile +++ b/frameworks/Python/tornado/tornado.dockerfile @@ -1,11 +1,11 @@ -FROM python:2.7.15-stretch +FROM python:3.6.6-stretch ADD ./ /tornado WORKDIR /tornado -RUN pip install -r /tornado/requirements_py2_mongo.txt +RUN pip3 install -r /tornado/requirements_mongo.txt EXPOSE 8080 -CMD python server_py2.py --port=8080 --mongo=tfb-database --logging=error +CMD python3 server.py --port=8080 --mongo=tfb-database --logging=error diff --git a/frameworks/Python/turbogears/benchmark_config.json b/frameworks/Python/turbogears/benchmark_config.json index cfd4c3efda7..162dbb38e64 100644 --- a/frameworks/Python/turbogears/benchmark_config.json +++ b/frameworks/Python/turbogears/benchmark_config.json @@ -21,6 +21,7 @@ "os": "Linux", "database_os": "Linux", "display_name": "TurboGears", + "tags": ["broken"], "notes": "CPython 2.7" } }] diff --git a/frameworks/Python/web2py/benchmark_config.json b/frameworks/Python/web2py/benchmark_config.json index d1349f5633e..c8bf7c94bf0 100644 --- a/frameworks/Python/web2py/benchmark_config.json +++ b/frameworks/Python/web2py/benchmark_config.json @@ -22,6 +22,7 @@ "database_os": "Linux", "display_name": "web2py-standard", "notes": "CPython 2.7", + "tags": ["broken"], "versus": "wsgi" }, "optimized": { @@ -44,6 +45,7 @@ "database_os": "Linux", "display_name": "web2py-optimized", "notes": "CPython 2.7", + "tags": ["broken"], "versus": "wsgi" } }] diff --git a/frameworks/R/plumber/benchmark_config.json b/frameworks/R/plumber/benchmark_config.json index ceb6f0c608a..a2ad2107710 100755 --- a/frameworks/R/plumber/benchmark_config.json +++ b/frameworks/R/plumber/benchmark_config.json @@ -4,7 +4,6 @@ { "default": { "json_url": "/json", - "plaintext_url": "/plaintext", "db_url": "/db", "query_url": "/query?queries=", "fortune_url": "/fortunes", diff --git a/frameworks/Ruby/agoo/Gemfile.lock b/frameworks/Ruby/agoo/Gemfile.lock index 7f05c4040ea..8fced2a2ec4 100644 --- a/frameworks/Ruby/agoo/Gemfile.lock +++ b/frameworks/Ruby/agoo/Gemfile.lock @@ -2,12 +2,12 @@ GEM remote: https://rubygems.org/ specs: agoo (2.15.13) - bigdecimal (3.1.9) + bigdecimal (3.3.1) connection_pool (2.5.0) - oj (3.16.10) + oj (3.16.12) bigdecimal (>= 3.0) ostruct (>= 0.2) - ostruct (0.6.1) + ostruct (0.6.3) pg (1.6.2) pg (1.6.2-x86_64-linux) rack (3.2.0) diff --git a/frameworks/Ruby/agoo/agoo.dockerfile b/frameworks/Ruby/agoo/agoo.dockerfile index 548fb50341b..3f0e73a6f74 100644 --- a/frameworks/Ruby/agoo/agoo.dockerfile +++ b/frameworks/Ruby/agoo/agoo.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc RUN apt-get update -q \ && apt-get install --no-install-recommends -q -y \ diff --git a/frameworks/Ruby/agoo/benchmark_config.json b/frameworks/Ruby/agoo/benchmark_config.json index a4042facee3..d1d0d2f42b5 100644 --- a/frameworks/Ruby/agoo/benchmark_config.json +++ b/frameworks/Ruby/agoo/benchmark_config.json @@ -19,7 +19,7 @@ "webserver": "Agoo", "os": "Linux", "database_os": "Linux", - "display_name": "rack-agoo-mri", + "display_name": "agoo", "notes": "" } }] diff --git a/frameworks/Ruby/grape/Gemfile b/frameworks/Ruby/grape/Gemfile index 89f6c86a84e..7a551b00b76 100644 --- a/frameworks/Ruby/grape/Gemfile +++ b/frameworks/Ruby/grape/Gemfile @@ -1,8 +1,14 @@ source 'https://rubygems.org' gem 'mysql2', '0.5.6' -gem 'unicorn', '6.1.0' -gem 'puma', '~> 7.1' -gem 'activerecord', '~> 8.0.0', :require => 'active_record' +gem 'activerecord', '~> 8.1.0', :require => 'active_record' gem 'grape', '2.1.1' gem 'json', '~> 2.9' + +group :iodine, optional: true do + gem "iodine", "~> 0.7", require: false +end + +group :puma, optional: true do + gem "puma", "~> 7.1", require: false +end diff --git a/frameworks/Ruby/grape/Gemfile.lock b/frameworks/Ruby/grape/Gemfile.lock index a1053906658..d79d4469104 100644 --- a/frameworks/Ruby/grape/Gemfile.lock +++ b/frameworks/Ruby/grape/Gemfile.lock @@ -1,27 +1,26 @@ GEM remote: https://rubygems.org/ specs: - activemodel (8.0.1) - activesupport (= 8.0.1) - activerecord (8.0.1) - activemodel (= 8.0.1) - activesupport (= 8.0.1) + activemodel (8.1.1) + activesupport (= 8.1.1) + activerecord (8.1.1) + activemodel (= 8.1.1) + activesupport (= 8.1.1) timeout (>= 0.4.0) - activesupport (8.0.1) + activesupport (8.1.1) base64 - benchmark (>= 0.3) bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + json logger (>= 1.4.2) minitest (>= 5.1) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) uri (>= 0.13.1) base64 (0.2.0) - benchmark (0.4.0) bigdecimal (3.1.9) concurrent-ruby (1.3.5) connection_pool (2.5.0) @@ -51,8 +50,8 @@ GEM zeitwerk i18n (1.14.7) concurrent-ruby (~> 1.0) - json (2.11.3) - kgio (2.11.4) + iodine (0.7.58) + json (2.16.0) logger (1.6.6) minitest (5.25.4) mustermann (3.0.3) @@ -64,15 +63,11 @@ GEM puma (7.1.0) nio4r (~> 2.0) rack (3.2.3) - raindrops (0.20.1) ruby2_keywords (0.0.5) securerandom (0.4.1) timeout (0.4.3) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicorn (6.1.0) - kgio (~> 2.6) - raindrops (~> 0.7) uri (1.0.3) zeitwerk (2.7.2) @@ -82,12 +77,12 @@ PLATFORMS x86_64-linux DEPENDENCIES - activerecord (~> 8.0.0) + activerecord (~> 8.1.0) grape (= 2.1.1) + iodine (~> 0.7) json (~> 2.9) mysql2 (= 0.5.6) puma (~> 7.1) - unicorn (= 6.1.0) BUNDLED WITH 2.7.0 diff --git a/frameworks/Ruby/grape/README.md b/frameworks/Ruby/grape/README.md index 87f4e3f1c2a..1e5f2e908af 100644 --- a/frameworks/Ruby/grape/README.md +++ b/frameworks/Ruby/grape/README.md @@ -12,9 +12,9 @@ comparing a variety of web servers. The tests were run with: * [Ruby 3.4](http://www.ruby-lang.org/) -* [Grape 2.0.0](http://www.ruby-grape.org/) -* [Unicorn 6.1.0](https://yhbt.net/unicorn/) -* [Puma 6.4](https://puma.io/) +* [Grape 2.1](http://www.ruby-grape.org/) +* [Iodine](https://github.com/boazsegev/iodine) +* [Puma 7](https://puma.io/) ## Paths & Source for Tests diff --git a/frameworks/Ruby/grape/benchmark_config.json b/frameworks/Ruby/grape/benchmark_config.json index f0afa34bc72..dd8892f5ea9 100644 --- a/frameworks/Ruby/grape/benchmark_config.json +++ b/frameworks/Ruby/grape/benchmark_config.json @@ -18,11 +18,11 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "grape-puma-mri", + "display_name": "grape [puma]", "notes": "", "versus": "rack-puma-mri" }, - "unicorn": { + "iodine": { "json_url": "/json", "db_url": "/db", "query_url": "/query?queries=", @@ -36,12 +36,12 @@ "language": "Ruby", "orm": "Full", "platform": "Rack", - "webserver": "Unicorn", + "webserver": "Iodine", "os": "Linux", "database_os": "Linux", - "display_name": "grape-unicorn-mri", + "display_name": "grape [iodine]", "notes": "", - "versus": "rack-unicorn-mri" + "versus": "rack-iodine-mri" } }] } diff --git a/frameworks/Ruby/grape/boot.rb b/frameworks/Ruby/grape/boot.rb new file mode 100644 index 00000000000..dd2ffda7f0e --- /dev/null +++ b/frameworks/Ruby/grape/boot.rb @@ -0,0 +1,91 @@ +require 'erb' +require 'active_record' +require 'yaml' + +MAX_PK = 10_000 +ID_RANGE = (1..MAX_PK).freeze +ALL_IDS = ID_RANGE.to_a +QUERIES_MIN = 1 +QUERIES_MAX = 500 + +Bundler.require :default + +db_config = YAML.load(ERB.new(File.read('config/database.yml')).result)[ENV['RACK_ENV']] +ActiveRecord::Base.establish_connection(db_config) + +class World < ActiveRecord::Base + self.table_name = 'World' +end + +module Acme + class HelloWorld < Grape::API + get '/json' do + {message:'Hello, World!'} + end + end + + class PlainText < Grape::API + content_type :plain, 'text/plain' + format :plain + + get '/plaintext' do + 'Hello, World!' + end + end + + class DatabaseQueries < Grape::API + logger nil + helpers do + def bounded_queries + queries = params[:queries].to_i + queries.clamp(QUERIES_MIN, QUERIES_MAX) + end + + # Return a random number between 1 and MAX_PK + def rand1 + rand(MAX_PK).succ + end + end + + get '/db' do + ActiveRecord::Base.with_connection do + World.find(rand1).attributes + end + end + + get '/query' do + ActiveRecord::Base.with_connection do + ALL_IDS.sample(bounded_queries).map do |id| + World.find(id) + end + end + end + + get '/updates' do + worlds = + ActiveRecord::Base.with_connection do + ALL_IDS.sample(bounded_queries).map do |id| + world = World.find(id) + new_value = rand1 + new_value = rand1 while new_value == world.randomNumber + world.update_columns(randomNumber: new_value) + world + end + end + end + end + + class API < Grape::API + before do + header 'Date', Time.now.httpdate if defined?(Puma) + header 'Server', 'grape' + end + logger nil + content_type :json, 'application/json' + format :json + + mount ::Acme::HelloWorld + mount ::Acme::PlainText + mount ::Acme::DatabaseQueries + end +end diff --git a/frameworks/Ruby/grape/config.ru b/frameworks/Ruby/grape/config.ru index 65396539b64..54d0ce8ca74 100644 --- a/frameworks/Ruby/grape/config.ru +++ b/frameworks/Ruby/grape/config.ru @@ -1,94 +1,2 @@ -require 'erb' -require 'active_record' -require 'yaml' -require_relative 'config/auto_tune' - -MAX_PK = 10_000 -ID_RANGE = (1..MAX_PK).freeze -ALL_IDS = ID_RANGE.to_a -QUERIES_MIN = 1 -QUERIES_MAX = 500 - -Bundler.require :default - -db_config = YAML.load(ERB.new(File.read('config/database.yml')).result)[ENV['RACK_ENV']] -ActiveRecord::Base.establish_connection(db_config) - -class World < ActiveRecord::Base - self.table_name = 'World' -end - -module Acme - class HelloWorld < Grape::API - get '/json' do - {message:'Hello, World!'} - end - end - - class PlainText < Grape::API - content_type :plain, 'text/plain' - format :plain - - get '/plaintext' do - 'Hello, World!' - end - end - - class DatabaseQueries < Grape::API - logger nil - helpers do - def bounded_queries - queries = params[:queries].to_i - queries.clamp(QUERIES_MIN, QUERIES_MAX) - end - - # Return a random number between 1 and MAX_PK - def rand1 - rand(MAX_PK).succ - end - end - - get '/db' do - ActiveRecord::Base.with_connection do - World.find(rand1).attributes - end - end - - get '/query' do - ActiveRecord::Base.with_connection do - ALL_IDS.sample(bounded_queries).map do |id| - World.find(id) - end - end - end - - get '/updates' do - worlds = - ActiveRecord::Base.with_connection do - ALL_IDS.sample(bounded_queries).map do |id| - world = World.find(id) - new_value = rand1 - new_value = rand1 while new_value == world.randomNumber - world.update_columns(randomNumber: new_value) - world - end - end - end - end - - class API < Grape::API - before do - header 'Date', Time.now.httpdate if defined?(Puma) - header 'Server', 'WebServer' - end - logger nil - content_type :json, 'application/json' - format :json - - mount ::Acme::HelloWorld - mount ::Acme::PlainText - mount ::Acme::DatabaseQueries - end -end - +require_relative 'boot' run Acme::API diff --git a/frameworks/Ruby/grape/config.toml b/frameworks/Ruby/grape/config.toml index 3802b46b42b..cc3542e065a 100644 --- a/frameworks/Ruby/grape/config.toml +++ b/frameworks/Ruby/grape/config.toml @@ -17,7 +17,7 @@ platform = "Rack" webserver = "Puma" versus = "rack-puma-mri" -[unicorn] +[iodine] urls.plaintext = "/plaintext" urls.json = "/json" urls.db = "/db" @@ -30,5 +30,5 @@ database_os = "Linux" os = "Linux" orm = "Full" platform = "Rack" -webserver = "Unicorn" -versus = "rack-unicorn-mri" +webserver = "Iodine" +versus = "rack-iodine-mri" diff --git a/frameworks/Ruby/grape/config/database.yml b/frameworks/Ruby/grape/config/database.yml index 9be8d7d851a..32ce75b69bf 100644 --- a/frameworks/Ruby/grape/config/database.yml +++ b/frameworks/Ruby/grape/config/database.yml @@ -5,5 +5,5 @@ production: database: hello_world username: benchmarkdbuser password: benchmarkdbpass - pool: 3 + pool: <%= ENV.fetch('MAX_THREADS') %> timeout: 5000 diff --git a/frameworks/Ruby/grape/config/nginx.conf b/frameworks/Ruby/grape/config/nginx.conf deleted file mode 100644 index 19534510faf..00000000000 --- a/frameworks/Ruby/grape/config/nginx.conf +++ /dev/null @@ -1,158 +0,0 @@ -# This is example contains the bare mininum to get nginx going with -# Unicorn or Rainbows! servers. Generally these configuration settings -# are applicable to other HTTP application servers (and not just Ruby -# ones), so if you have one working well for proxying another app -# server, feel free to continue using it. -# -# The only setting we feel strongly about is the fail_timeout=0 -# directive in the "upstream" block. max_fails=0 also has the same -# effect as fail_timeout=0 for current versions of nginx and may be -# used in its place. -# -# Users are strongly encouraged to refer to nginx documentation for more -# details and search for other example configs. - -# you generally only need one nginx worker unless you're serving -# large amounts of static files which require blocking disk reads -worker_processes 8; - -# # drop privileges, root is needed on most systems for binding to port 80 -# # (or anything < 1024). Capability-based security may be available for -# # your system and worth checking out so you won't need to be root to -# # start nginx to bind on 80 -# user nobody nogroup; # for systems with a "nogroup" -#user nobody nobody; # for systems with "nobody" as a group instead - -# Feel free to change all paths to suite your needs here, of course -pid /tmp/nginx.pid; -#error_log /tmp/nginx.error.log; -error_log stderr error; - -events { - worker_connections 4096; # increase if you have lots of clients - accept_mutex off; # "on" if nginx worker_processes > 1 - use epoll; # enable for Linux 2.6+ - # use kqueue; # enable for FreeBSD, OSX -} - -http { - # nginx will find this file in the config directory set at nginx build time - include /etc/nginx/mime.types; - - # fallback in case we can't determine a type - default_type application/octet-stream; - - # click tracking! - #access_log /tmp/nginx.access.log combined; - access_log off; - - # you generally want to serve static files with nginx since neither - # Unicorn nor Rainbows! is optimized for it at the moment - sendfile on; - - tcp_nopush on; # off may be better for *some* Comet/long-poll stuff - tcp_nodelay off; # on may be better for some Comet/long-poll stuff - - # we haven't checked to see if Rack::Deflate on the app server is - # faster or not than doing compression via nginx. It's easier - # to configure it all in one place here for static files and also - # to disable gzip for clients who don't get gzip/deflate right. - # There are other gzip settings that may be needed used to deal with - # bad clients out there, see http://wiki.nginx.org/NginxHttpGzipModule - #gzip on; - #gzip_http_version 1.0; - #gzip_proxied any; - #gzip_min_length 500; - #gzip_disable "MSIE [1-6]\."; - #gzip_types text/plain text/html text/xml text/css - # text/comma-separated-values - # text/javascript application/x-javascript - # application/atom+xml; - - # this can be any application server, not just Unicorn/Rainbows! - upstream app_server { - # fail_timeout=0 means we always retry an upstream even if it failed - # to return a good HTTP response (in case the Unicorn master nukes a - # single worker for timing out). - - # for UNIX domain socket setups: - server unix:/tmp/unicorn.sock fail_timeout=0; - - # for TCP setups, point these to your backend servers - # server 192.168.0.7:8080 fail_timeout=0; - # server 192.168.0.8:8080 fail_timeout=0; - # server 192.168.0.9:8080 fail_timeout=0; - } - - server { - # enable one of the following if you're on Linux or FreeBSD - listen 8080 default deferred; # for Linux - # listen 80 default accept_filter=httpready; # for FreeBSD - - # If you have IPv6, you'll likely want to have two separate listeners. - # One on IPv4 only (the default), and another on IPv6 only instead - # of a single dual-stack listener. A dual-stack listener will make - # for ugly IPv4 addresses in $remote_addr (e.g ":ffff:10.0.0.1" - # instead of just "10.0.0.1") and potentially trigger bugs in - # some software. - # listen [::]:80 ipv6only=on; # deferred or accept_filter recommended - - client_max_body_size 4G; - server_name _; - - # ~2 seconds is often enough for most folks to parse HTML/CSS and - # retrieve needed images/icons/frames, connections are cheap in - # nginx so increasing this is generally safe... - keepalive_timeout 10; - - # path for static files - root /path/to/app/current/public; - - # Prefer to serve static files directly from nginx to avoid unnecessary - # data copies from the application server. - # - # try_files directive appeared in in nginx 0.7.27 and has stabilized - # over time. Older versions of nginx (e.g. 0.6.x) requires - # "if (!-f $request_filename)" which was less efficient: - # http://bogomips.org/unicorn.git/tree/examples/nginx.conf?id=v3.3.1#n127 - try_files $uri/index.html $uri.html $uri @app; - - location @app { - # an HTTP header important enough to have its own Wikipedia entry: - # http://en.wikipedia.org/wiki/X-Forwarded-For - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - # enable this if you forward HTTPS traffic to unicorn, - # this helps Rack set the proper URL scheme for doing redirects: - # proxy_set_header X-Forwarded-Proto $scheme; - - # pass the Host: header from the client right along so redirects - # can be set properly within the Rack application - proxy_set_header Host $http_host; - - # we don't want nginx trying to do something clever with - # redirects, we set the Host: header above already. - proxy_redirect off; - - # set "proxy_buffering off" *only* for Rainbows! when doing - # Comet/long-poll/streaming. It's also safe to set if you're using - # only serving fast clients with Unicorn + nginx, but not slow - # clients. You normally want nginx to buffer responses to slow - # clients, even with Rails 3.1 streaming because otherwise a slow - # client can become a bottleneck of Unicorn. - # - # The Rack application may also set "X-Accel-Buffering (yes|no)" - # in the response headers do disable/enable buffering on a - # per-response basis. - # proxy_buffering off; - - proxy_pass http://app_server; - } - - # Rails error pages - error_page 500 502 503 504 /500.html; - location = /500.html { - root /path/to/app/current/public; - } - } -} diff --git a/frameworks/Ruby/grape/config/puma.rb b/frameworks/Ruby/grape/config/puma.rb deleted file mode 100644 index a489e1af89d..00000000000 --- a/frameworks/Ruby/grape/config/puma.rb +++ /dev/null @@ -1,13 +0,0 @@ -require_relative 'auto_tune' - -# FWBM only... use the puma_auto_tune gem in production! -_, num_threads = auto_tune - -threads num_threads - -# Use the `preload_app!` method when specifying a `workers` number. -# This directive tells Puma to first boot the application and load code -# before forking the application. This takes advantage of Copy On Write -# process behavior so workers use less memory. -# -preload_app! diff --git a/frameworks/Ruby/grape/config/unicorn.rb b/frameworks/Ruby/grape/config/unicorn.rb deleted file mode 100644 index 697d61d8016..00000000000 --- a/frameworks/Ruby/grape/config/unicorn.rb +++ /dev/null @@ -1,15 +0,0 @@ -require_relative 'auto_tune' - -num_workers, = auto_tune -worker_processes num_workers - -listen "/tmp/unicorn.sock", :backlog => 4096 - -preload_app true -GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true - -before_fork do |server, worker| -end - -after_fork do |server, worker| -end diff --git a/frameworks/Ruby/grape/grape-unicorn.dockerfile b/frameworks/Ruby/grape/grape-iodine.dockerfile similarity index 51% rename from frameworks/Ruby/grape/grape-unicorn.dockerfile rename to frameworks/Ruby/grape/grape-iodine.dockerfile index a20de1c8e3f..4e20c95ba1c 100644 --- a/frameworks/Ruby/grape/grape-unicorn.dockerfile +++ b/frameworks/Ruby/grape/grape-iodine.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 @@ -13,8 +13,12 @@ ADD ./ /grape WORKDIR /grape -RUN bundle install --jobs=4 --gemfile=/grape/Gemfile +RUN bundle config set with 'iodine' +RUN bundle install --jobs=8 --gemfile=/grape/Gemfile + +ENV RACK_ENV=production +ENV MAX_THREADS=1 EXPOSE 8080 -CMD nginx -c /grape/config/nginx.conf && bundle exec unicorn -E production -c config/unicorn.rb +CMD bundle exec iodine -p 8080 -w $(ruby config/auto_tune.rb | grep -Eo '[0-9]+' | head -n 1) diff --git a/frameworks/Ruby/grape/grape.dockerfile b/frameworks/Ruby/grape/grape.dockerfile index 3108a40dc55..2ef47fcaed2 100644 --- a/frameworks/Ruby/grape/grape.dockerfile +++ b/frameworks/Ruby/grape/grape.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 @@ -11,9 +11,12 @@ ADD ./ /grape WORKDIR /grape -RUN bundle install --jobs=4 --gemfile=/grape/Gemfile +RUN bundle config set with 'puma' +RUN bundle install --jobs=8 --gemfile=/grape/Gemfile ENV WEB_CONCURRENCY=auto +ENV MAX_THREADS=5 + EXPOSE 8080 -CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 -e production +CMD bundle exec puma -b tcp://0.0.0.0:8080 -e production diff --git a/frameworks/Ruby/hanami/Gemfile b/frameworks/Ruby/hanami/Gemfile index 956ff09ad32..2065c222246 100644 --- a/frameworks/Ruby/hanami/Gemfile +++ b/frameworks/Ruby/hanami/Gemfile @@ -2,12 +2,12 @@ source "https://rubygems.org" -gem "hanami", "~> 2.2" -gem "hanami-router", "~> 2.2" -gem "hanami-controller", "~> 2.2" -gem "hanami-db", "~> 2.2" -gem "hanami-validations", "~> 2.2" -gem "hanami-view", "~> 2.2" +gem "hanami", "~> 2.3" +gem "hanami-router", "~> 2.3" +gem "hanami-controller", "~> 2.3" +gem "hanami-db", "~> 2.3" +gem "hanami-validations", "~> 2.3" +gem "hanami-view", "~> 2.3" gem "dry-types", "~> 1.0", ">= 1.6.1" gem "puma" @@ -16,4 +16,4 @@ gem "rake" gem "rom", "~> 5.3" gem "rom-sql", "~> 3.6" gem "pg" -gem "ostruct" # required for Ruby 3.5 +gem "ostruct" # required for Ruby 4.0 diff --git a/frameworks/Ruby/hanami/Gemfile.lock b/frameworks/Ruby/hanami/Gemfile.lock index 853de823128..953659b0535 100644 --- a/frameworks/Ruby/hanami/Gemfile.lock +++ b/frameworks/Ruby/hanami/Gemfile.lock @@ -1,8 +1,11 @@ GEM remote: https://rubygems.org/ specs: + base64 (0.3.0) bigdecimal (3.1.9) concurrent-ruby (1.3.5) + csv (3.3.5) + date (3.5.0) dry-auto_inject (1.1.0) dry-core (~> 1.1) zeitwerk (~> 2.6) @@ -20,7 +23,7 @@ GEM dry-files (1.1.0) dry-inflector (1.2.0) dry-initializer (3.2.0) - dry-logger (1.0.4) + dry-logger (1.2.0) dry-logic (1.6.0) bigdecimal concurrent-ruby (~> 1.0) @@ -63,46 +66,52 @@ GEM dry-initializer (~> 3.2) dry-schema (~> 1.14) zeitwerk (~> 2.6) - hanami (2.2.1) + erb (6.0.0) + hanami (2.3.0) bundler (>= 1.16, < 3) dry-configurable (~> 1.0, >= 1.2.0, < 2) dry-core (~> 1.0, < 2) dry-inflector (~> 1.0, >= 1.1.0, < 2) - dry-logger (~> 1.0, < 2) + dry-logger (~> 1.2, < 2) dry-monitor (~> 1.0, >= 1.0.1, < 2) dry-system (~> 1.1) - hanami-cli (~> 2.2.1) - hanami-utils (~> 2.2) + hanami-cli (>= 2.3.0) + hanami-utils (>= 2.3.0) json (>= 2.7.2) + rack-session zeitwerk (~> 2.6) - hanami-cli (2.2.1) + hanami-cli (2.3.0) bundler (~> 2.1) dry-cli (~> 1.0, >= 1.1.0) dry-files (~> 1.0, >= 1.0.2, < 2) dry-inflector (~> 1.0, < 2) + irb + rackup rake (~> 13.0) zeitwerk (~> 2.6) - hanami-controller (2.2.0) + hanami-controller (2.3.0) dry-configurable (~> 1.0, < 2) dry-core (~> 1.0) - hanami-utils (~> 2.2) - rack (~> 2.0) + hanami-utils (~> 2.3.0) + rack (>= 2.1) zeitwerk (~> 2.6) - hanami-db (2.2.1) + hanami-db (2.3.0) rom (~> 5.4, >= 5.4.1) rom-sql (~> 3.7) zeitwerk (~> 2.6) - hanami-router (2.2.0) + hanami-router (2.3.0) + csv (~> 3.3) mustermann (~> 3.0) mustermann-contrib (~> 3.0) - rack (~> 2.0) - hanami-utils (2.2.0) + rack (>= 2.0) + hanami-utils (2.3.0) + bigdecimal (~> 3.1) concurrent-ruby (~> 1.0) dry-core (~> 1.0, < 2) dry-transformer (~> 1.0, < 2) - hanami-validations (2.2.0) + hanami-validations (2.3.0) dry-validation (>= 1.10, < 2) - hanami-view (2.2.1) + hanami-view (2.3.0) dry-configurable (~> 1.0) dry-core (~> 1.0) dry-inflector (~> 1.0, < 2) @@ -111,7 +120,12 @@ GEM zeitwerk (~> 2.6) hansi (0.2.1) ice_nine (0.11.2) - json (2.11.3) + io-console (0.8.1) + irb (1.15.3) + pp (>= 0.6.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + json (2.16.0) logger (1.6.6) mustermann (3.0.3) ruby2_keywords (~> 0.0.1) @@ -121,10 +135,27 @@ GEM nio4r (2.7.4) ostruct (0.6.3) pg (1.5.9) + pp (0.6.3) + prettyprint + prettyprint (0.2.0) + psych (5.2.6) + date + stringio puma (6.6.0) nio4r (~> 2.0) - rack (2.2.19) + rack (3.2.4) + rack-session (2.1.1) + base64 (>= 0.1.0) + rack (>= 3.0.0) + rackup (2.2.1) + rack (>= 3) rake (13.2.1) + rdoc (6.15.1) + erb + psych (>= 4.0.0) + tsort + reline (0.6.3) + io-console (~> 0.5) rom (5.4.2) rom-changeset (~> 5.4) rom-core (~> 5.4) @@ -154,9 +185,11 @@ GEM ruby2_keywords (0.0.5) sequel (5.90.0) bigdecimal + stringio (3.1.8) temple (0.10.3) tilt (2.6.0) transproc (1.1.1) + tsort (0.2.0) zeitwerk (2.7.2) PLATFORMS @@ -166,12 +199,12 @@ PLATFORMS DEPENDENCIES dry-types (~> 1.0, >= 1.6.1) - hanami (~> 2.2) - hanami-controller (~> 2.2) - hanami-db (~> 2.2) - hanami-router (~> 2.2) - hanami-validations (~> 2.2) - hanami-view (~> 2.2) + hanami (~> 2.3) + hanami-controller (~> 2.3) + hanami-db (~> 2.3) + hanami-router (~> 2.3) + hanami-validations (~> 2.3) + hanami-view (~> 2.3) ostruct pg puma diff --git a/frameworks/Ruby/padrino/Gemfile b/frameworks/Ruby/padrino/Gemfile index 3e643448adb..4e9aa2922ea 100644 --- a/frameworks/Ruby/padrino/Gemfile +++ b/frameworks/Ruby/padrino/Gemfile @@ -2,16 +2,13 @@ source 'https://rubygems.org' gem 'mysql2', '> 0.5' gem 'json' -gem 'activerecord', '>= 7.1', :require => 'active_record' +gem 'activerecord', '~> 8.1.0', :require => 'active_record' -gem 'slim', '2.0.3' -gem 'padrino', git: 'https://github.com/padrino/padrino-framework.git' +gem 'slim' +gem 'padrino', '0.16.0' gem 'rack' +gem 'ostruct' # required for Ruby 3.5 -group :puma, optional: true do - gem 'puma', '~> 7.1', require: false -end - -group :unicorn, optional: true do - gem 'unicorn', '~> 6.1', platforms: [:ruby, :windows], require: false +group :iodine, optional: true do + gem "iodine", "~> 0.7", require: false end diff --git a/frameworks/Ruby/padrino/Gemfile.lock b/frameworks/Ruby/padrino/Gemfile.lock index 45c6deadd77..b62ac92b5c5 100644 --- a/frameworks/Ruby/padrino/Gemfile.lock +++ b/frameworks/Ruby/padrino/Gemfile.lock @@ -1,90 +1,53 @@ -GIT - remote: https://github.com/padrino/padrino-framework.git - revision: 9a38042351c9f5768231e94abca87bb1592cdcfa - specs: - padrino (0.16.0.pre3) - padrino-admin (= 0.16.0.pre3) - padrino-cache (= 0.16.0.pre3) - padrino-core (= 0.16.0.pre3) - padrino-gen (= 0.16.0.pre3) - padrino-helpers (= 0.16.0.pre3) - padrino-mailer (= 0.16.0.pre3) - padrino-support (= 0.16.0.pre3) - padrino-admin (0.16.0.pre3) - padrino-core (= 0.16.0.pre3) - padrino-helpers (= 0.16.0.pre3) - padrino-cache (0.16.0.pre3) - moneta (~> 1.6) - padrino-core (= 0.16.0.pre3) - padrino-helpers (= 0.16.0.pre3) - padrino-core (0.16.0.pre3) - padrino-support (= 0.16.0.pre3) - rackup (~> 2.1) - sinatra (~> 4) - thor (~> 1.0) - padrino-gen (0.16.0.pre3) - bundler (>= 1.0, < 3) - padrino-core (= 0.16.0.pre3) - padrino-helpers (0.16.0.pre3) - i18n (>= 0.6.7, < 2) - padrino-support (= 0.16.0.pre3) - tilt (>= 1.4.1, < 3) - padrino-mailer (0.16.0.pre3) - mail (~> 2.5) - mime-types (< 4) - padrino-core (= 0.16.0.pre3) - padrino-support (0.16.0.pre3) - GEM remote: https://rubygems.org/ specs: - activemodel (8.0.2) - activesupport (= 8.0.2) - activerecord (8.0.2) - activemodel (= 8.0.2) - activesupport (= 8.0.2) + activemodel (8.1.1) + activesupport (= 8.1.1) + activerecord (8.1.1) + activemodel (= 8.1.1) + activesupport (= 8.1.1) timeout (>= 0.4.0) - activesupport (8.0.2) + activesupport (8.1.1) base64 - benchmark (>= 0.3) bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + json logger (>= 1.4.2) minitest (>= 5.1) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) uri (>= 0.13.1) - base64 (0.2.0) - benchmark (0.4.0) + base64 (0.3.0) bigdecimal (3.1.9) concurrent-ruby (1.3.5) connection_pool (2.5.0) - date (3.4.1) + date (3.5.0) drb (2.2.1) i18n (1.14.7) concurrent-ruby (~> 1.0) - json (2.11.3) - kgio (2.11.4) - logger (1.6.6) - mail (2.8.1) + iodine (0.7.58) + json (2.16.0) + logger (1.7.0) + mail (2.9.0) + logger mini_mime (>= 0.1.1) net-imap net-pop net-smtp - mime-types (3.6.1) + mime-types (3.7.0) logger - mime-types-data (~> 3.2015) - mime-types-data (3.2025.0318) + mime-types-data (~> 3.2025, >= 3.2025.0507) + mime-types-data (3.2025.0924) mini_mime (1.1.5) minitest (5.25.5) moneta (1.6.0) - mustermann (3.0.3) + mustermann (3.0.4) ruby2_keywords (~> 0.0.1) mysql2 (0.5.6) - net-imap (0.5.6) + net-imap (0.5.12) date net-protocol net-pop (0.1.2) @@ -93,41 +56,67 @@ GEM timeout net-smtp (0.5.1) net-protocol - nio4r (2.7.4) - puma (7.1.0) - nio4r (~> 2.0) - rack (3.1.18) - rack-protection (4.1.1) + ostruct (0.6.3) + padrino (0.16.0) + padrino-admin (= 0.16.0) + padrino-cache (= 0.16.0) + padrino-core (= 0.16.0) + padrino-gen (= 0.16.0) + padrino-helpers (= 0.16.0) + padrino-mailer (= 0.16.0) + padrino-support (= 0.16.0) + padrino-admin (0.16.0) + padrino-core (= 0.16.0) + padrino-helpers (= 0.16.0) + padrino-cache (0.16.0) + moneta (~> 1.6) + padrino-core (= 0.16.0) + padrino-helpers (= 0.16.0) + padrino-core (0.16.0) + padrino-support (= 0.16.0) + rackup (~> 2.1) + sinatra (~> 4) + thor (~> 1.0) + padrino-gen (0.16.0) + bundler (>= 1.0, < 3) + padrino-core (= 0.16.0) + padrino-helpers (0.16.0) + i18n (>= 0.6.7, < 2) + padrino-support (= 0.16.0) + tilt (>= 2.1, < 3) + padrino-mailer (0.16.0) + mail (~> 2.5) + mime-types (>= 3.1, < 4) + padrino-core (= 0.16.0) + padrino-support (0.16.0) + rack (3.2.4) + rack-protection (4.2.1) base64 (>= 0.1.0) logger (>= 1.6.0) rack (>= 3.0.0, < 4) - rack-session (2.1.0) + rack-session (2.1.1) base64 (>= 0.1.0) rack (>= 3.0.0) rackup (2.2.1) rack (>= 3) - raindrops (0.20.1) ruby2_keywords (0.0.5) securerandom (0.4.1) - sinatra (4.1.1) + sinatra (4.2.1) logger (>= 1.6.0) mustermann (~> 3.0) rack (>= 3.0.0, < 4) - rack-protection (= 4.1.1) + rack-protection (= 4.2.1) rack-session (>= 2.0.0, < 3) tilt (~> 2.0) - slim (2.0.3) - temple (~> 0.6.6) - tilt (>= 1.3.3, < 2.1) - temple (0.6.10) - thor (1.3.2) - tilt (2.0.11) - timeout (0.4.3) + slim (5.2.1) + temple (~> 0.10.0) + tilt (>= 2.1.0) + temple (0.10.4) + thor (1.4.0) + tilt (2.6.1) + timeout (0.4.4) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicorn (6.1.0) - kgio (~> 2.6) - raindrops (~> 0.7) uri (1.0.3) PLATFORMS @@ -136,14 +125,14 @@ PLATFORMS x86_64-linux DEPENDENCIES - activerecord (>= 7.1) + activerecord (~> 8.1.0) + iodine (~> 0.7) json mysql2 (> 0.5) - padrino! - puma (~> 7.1) + ostruct + padrino (= 0.16.0) rack - slim (= 2.0.3) - unicorn (~> 6.1) + slim BUNDLED WITH 2.7.0 diff --git a/frameworks/Ruby/padrino/README.md b/frameworks/Ruby/padrino/README.md index c0c1e7601fe..9d11b9ef5a4 100644 --- a/frameworks/Ruby/padrino/README.md +++ b/frameworks/Ruby/padrino/README.md @@ -11,14 +11,9 @@ comparing a variety of web servers. ## Infrastructure Software Versions The tests were run with: -* [Ruby 2.0.0-p0](http://www.ruby-lang.org/) -* [JRuby 1.7.8](http://jruby.org/) -* [Rubinius 2.2.10](http://rubini.us/) +* [Ruby 3.5](http://www.ruby-lang.org/) * [Padrino 0.12.3](http://www.padrinorb.com/) -* [Rack 1.5.2](http://rack.github.com/) -* [Unicorn 4.8.3](http://unicorn.bogomips.org/) -* [Puma 3.9](http://puma.io/) -* [Thin 1.6.2](http://code.macournoyer.com/thin/) +* [Iodine](https://github.com/boazsegev/iodine) ## Paths & Source for Tests diff --git a/frameworks/Ruby/padrino/app/controllers.rb b/frameworks/Ruby/padrino/app/controllers.rb index c2a3291d797..e5a200c7f2c 100644 --- a/frameworks/Ruby/padrino/app/controllers.rb +++ b/frameworks/Ruby/padrino/app/controllers.rb @@ -7,10 +7,6 @@ response['Server'] = 'padrino' end - after do - response['Date'] = Time.now.httpdate - end if defined?(Puma) - get '/json', :provides => [:json] do {message: "Hello, World!"}.to_json end diff --git a/frameworks/Ruby/padrino/benchmark_config.json b/frameworks/Ruby/padrino/benchmark_config.json index 2fa32a70b47..0eaf86be1d9 100644 --- a/frameworks/Ruby/padrino/benchmark_config.json +++ b/frameworks/Ruby/padrino/benchmark_config.json @@ -2,28 +2,6 @@ "framework": "padrino", "tests": [{ "default": { - "json_url": "/json", - "db_url": "/db", - "query_url": "/queries?queries=", - "fortune_url": "/fortunes", - "update_url": "/updates?queries=", - "plaintext_url": "/plaintext", - "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "database": "MySQL", - "framework": "padrino", - "language": "Ruby", - "orm": "Full", - "platform": "Rack", - "webserver": "Puma", - "os": "Linux", - "database_os": "Linux", - "display_name": "padrino-puma-mri", - "notes": "", - "versus": "rack-puma-mri" - }, - "unicorn": { "json_url": "/json", "db_url": "/db", "query_url": "/queries?queries=", @@ -38,12 +16,12 @@ "language": "Ruby", "orm": "Full", "platform": "Rack", - "webserver": "Unicorn", + "webserver": "Iodine", "os": "Linux", "database_os": "Linux", - "display_name": "padrino-unicorn", + "display_name": "padrino", "notes": "", - "versus": "rack-unicorn" + "versus": "rack-iodine" } }] } diff --git a/frameworks/Ruby/padrino/config.toml b/frameworks/Ruby/padrino/config.toml index 795c2789614..e5103e75fa5 100644 --- a/frameworks/Ruby/padrino/config.toml +++ b/frameworks/Ruby/padrino/config.toml @@ -15,22 +15,5 @@ database_os = "Linux" os = "Linux" orm = "Full" platform = "Rack" -webserver = "Puma" -versus = "rack-puma-mri" - -[unicorn] -urls.plaintext = "/plaintext" -urls.json = "/json" -urls.db = "/db" -urls.query = "/queries?queries=" -urls.update = "/updates?queries=" -urls.fortune = "/fortunes" -approach = "Realistic" -classification = "Micro" -database = "MySQL" -database_os = "Linux" -os = "Linux" -orm = "Full" -platform = "Rack" -webserver = "Unicorn" -versus = "rack-unicorn" +webserver = "Iodine" +versus = "rack-iodine" diff --git a/frameworks/Ruby/padrino/config/database.rb b/frameworks/Ruby/padrino/config/database.rb index 06324898cd9..c4bf9d564d2 100644 --- a/frameworks/Ruby/padrino/config/database.rb +++ b/frameworks/Ruby/padrino/config/database.rb @@ -8,14 +8,9 @@ } # Determine threading/thread pool size and timeout -if defined?(Puma) && (threads = Puma.cli_config.options.fetch(:max_threads)) > 1 - opts[:pool] = threads - opts[:checkout_timeout] = 10 -else - # TODO: ActiveRecord doesn't have a single-threaded mode? - opts[:pool] = 1 - opts[:checkout_timeout] = 0 -end +# TODO: ActiveRecord doesn't have a single-threaded mode? +opts[:pool] = 512 +opts[:checkout_timeout] = 5 # Setup our logger diff --git a/frameworks/Ruby/padrino/config/nginx.conf b/frameworks/Ruby/padrino/config/nginx.conf deleted file mode 100644 index 83d4479f28d..00000000000 --- a/frameworks/Ruby/padrino/config/nginx.conf +++ /dev/null @@ -1,158 +0,0 @@ -# This is example contains the bare mininum to get nginx going with -# Unicorn or Rainbows! servers. Generally these configuration settings -# are applicable to other HTTP application servers (and not just Ruby -# ones), so if you have one working well for proxying another app -# server, feel free to continue using it. -# -# The only setting we feel strongly about is the fail_timeout=0 -# directive in the "upstream" block. max_fails=0 also has the same -# effect as fail_timeout=0 for current versions of nginx and may be -# used in its place. -# -# Users are strongly encouraged to refer to nginx documentation for more -# details and search for other example configs. - -# you generally only need one nginx worker unless you're serving -# large amounts of static files which require blocking disk reads -worker_processes 8; - -# # drop privileges, root is needed on most systems for binding to port 80 -# # (or anything < 1024). Capability-based security may be available for -# # your system and worth checking out so you won't need to be root to -# # start nginx to bind on 80 -# user nobody nogroup; # for systems with a "nogroup" -#user nobody nobody; # for systems with "nobody" as a group instead - -# Feel free to change all paths to suite your needs here, of course -pid /tmp/nginx.pid; -#error_log /tmp/nginx.error.log; -error_log stderr error; - -events { - worker_connections 4096; # increase if you have lots of clients - accept_mutex off; # "on" if nginx worker_processes > 1 - use epoll; # enable for Linux 2.6+ - # use kqueue; # enable for FreeBSD, OSX -} - -http { - # nginx will find this file in the config directory set at nginx build time - include /etc/nginx/mime.types; - - # fallback in case we can't determine a type - default_type application/octet-stream; - - # click tracking! - #access_log /tmp/nginx.access.log combined; - access_log off; - - # you generally want to serve static files with nginx since neither - # Unicorn nor Rainbows! is optimized for it at the moment - sendfile on; - - tcp_nopush on; # off may be better for *some* Comet/long-poll stuff - tcp_nodelay off; # on may be better for some Comet/long-poll stuff - - # we haven't checked to see if Rack::Deflate on the app server is - # faster or not than doing compression via nginx. It's easier - # to configure it all in one place here for static files and also - # to disable gzip for clients who don't get gzip/deflate right. - # There are other gzip settings that may be needed used to deal with - # bad clients out there, see http://wiki.nginx.org/NginxHttpGzipModule - #gzip on; - #gzip_http_version 1.0; - #gzip_proxied any; - #gzip_min_length 500; - #gzip_disable "MSIE [1-6]\."; - #gzip_types text/plain text/html text/xml text/css - # text/comma-separated-values - # text/javascript application/x-javascript - # application/atom+xml; - - # this can be any application server, not just Unicorn/Rainbows! - upstream app_server { - # fail_timeout=0 means we always retry an upstream even if it failed - # to return a good HTTP response (in case the Unicorn master nukes a - # single worker for timing out). - - # for UNIX domain socket setups: - server unix:/tmp/.sock fail_timeout=0; - - # for TCP setups, point these to your backend servers - # server 192.168.0.7:8080 fail_timeout=0; - # server 192.168.0.8:8080 fail_timeout=0; - # server 192.168.0.9:8080 fail_timeout=0; - } - - server { - # enable one of the following if you're on Linux or FreeBSD - listen 8080 default deferred; # for Linux - # listen 80 default accept_filter=httpready; # for FreeBSD - - # If you have IPv6, you'll likely want to have two separate listeners. - # One on IPv4 only (the default), and another on IPv6 only instead - # of a single dual-stack listener. A dual-stack listener will make - # for ugly IPv4 addresses in $remote_addr (e.g ":ffff:10.0.0.1" - # instead of just "10.0.0.1") and potentially trigger bugs in - # some software. - # listen [::]:80 ipv6only=on; # deferred or accept_filter recommended - - client_max_body_size 4G; - server_name _; - - # ~2 seconds is often enough for most folks to parse HTML/CSS and - # retrieve needed images/icons/frames, connections are cheap in - # nginx so increasing this is generally safe... - keepalive_timeout 10; - - # path for static files - root /path/to/app/current/public; - - # Prefer to serve static files directly from nginx to avoid unnecessary - # data copies from the application server. - # - # try_files directive appeared in in nginx 0.7.27 and has stabilized - # over time. Older versions of nginx (e.g. 0.6.x) requires - # "if (!-f $request_filename)" which was less efficient: - # http://bogomips.org/unicorn.git/tree/examples/nginx.conf?id=v3.3.1#n127 - try_files $uri/index.html $uri.html $uri @app; - - location @app { - # an HTTP header important enough to have its own Wikipedia entry: - # http://en.wikipedia.org/wiki/X-Forwarded-For - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - # enable this if you forward HTTPS traffic to unicorn, - # this helps Rack set the proper URL scheme for doing redirects: - # proxy_set_header X-Forwarded-Proto $scheme; - - # pass the Host: header from the client right along so redirects - # can be set properly within the Rack application - proxy_set_header Host $http_host; - - # we don't want nginx trying to do something clever with - # redirects, we set the Host: header above already. - proxy_redirect off; - - # set "proxy_buffering off" *only* for Rainbows! when doing - # Comet/long-poll/streaming. It's also safe to set if you're using - # only serving fast clients with Unicorn + nginx, but not slow - # clients. You normally want nginx to buffer responses to slow - # clients, even with Rails 3.1 streaming because otherwise a slow - # client can become a bottleneck of Unicorn. - # - # The Rack application may also set "X-Accel-Buffering (yes|no)" - # in the response headers do disable/enable buffering on a - # per-response basis. - # proxy_buffering off; - - proxy_pass http://app_server; - } - - # Rails error pages - error_page 500 502 503 504 /500.html; - location = /500.html { - root /path/to/app/current/public; - } - } -} diff --git a/frameworks/Ruby/padrino/config/puma.rb b/frameworks/Ruby/padrino/config/puma.rb deleted file mode 100644 index 8a42642fd61..00000000000 --- a/frameworks/Ruby/padrino/config/puma.rb +++ /dev/null @@ -1,9 +0,0 @@ -require_relative 'auto_tune' - -num_workers, num_threads = auto_tune - -workers num_workers -threads num_threads, num_threads - -environment 'production' -bind 'tcp://0.0.0.0:8080' diff --git a/frameworks/Ruby/padrino/config/unicorn.rb b/frameworks/Ruby/padrino/config/unicorn.rb deleted file mode 100644 index 9ca3171328b..00000000000 --- a/frameworks/Ruby/padrino/config/unicorn.rb +++ /dev/null @@ -1,15 +0,0 @@ -require_relative 'auto_tune' - -num_workers, = auto_tune - -worker_processes num_workers -listen "/tmp/.sock", :backlog => 4096 - -preload_app true -GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true - -before_fork do |server, worker| -end - -after_fork do |server, worker| -end diff --git a/frameworks/Ruby/padrino/padrino-unicorn.dockerfile b/frameworks/Ruby/padrino/padrino-unicorn.dockerfile deleted file mode 100644 index 81a6e0fefda..00000000000 --- a/frameworks/Ruby/padrino/padrino-unicorn.dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM ruby:3.4 - -WORKDIR /padrino -COPY app app -COPY config config -COPY models models -COPY .components .components -COPY config.ru config.ru -COPY Gemfile Gemfile -COPY Gemfile.lock Gemfile.lock -COPY Rakefile Rakefile - -RUN bundle config set with 'unicorn' -RUN bundle install --jobs=4 --gemfile=/padrino/Gemfile - -RUN apt-get update -yqq && apt-get install -yqq nginx - -EXPOSE 8080 - -ENV RUBY_YJIT_ENABLE=1 - -CMD nginx -c /padrino/config/nginx.conf && \ - bundle exec unicorn -E production -c config/unicorn.rb diff --git a/frameworks/Ruby/padrino/padrino.dockerfile b/frameworks/Ruby/padrino/padrino.dockerfile index fc6ba9456d3..50cdbe55042 100644 --- a/frameworks/Ruby/padrino/padrino.dockerfile +++ b/frameworks/Ruby/padrino/padrino.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.4 +FROM ruby:4.0-rc WORKDIR /padrino COPY app app @@ -10,11 +10,12 @@ COPY Gemfile Gemfile COPY Gemfile.lock Gemfile.lock COPY Rakefile Rakefile -RUN bundle config set with 'puma' +RUN bundle config set with 'iodine' RUN bundle install --jobs=4 --gemfile=/padrino/Gemfile EXPOSE 8080 ENV RUBY_YJIT_ENABLE=1 +ENV RACK_ENV=production -CMD bundle exec puma -C config/puma.rb +CMD bundle exec iodine -p 8080 -w $(ruby config/auto_tune.rb | grep -Eo '[0-9]+' | head -n 1) diff --git a/frameworks/Ruby/rack-app/Gemfile b/frameworks/Ruby/rack-app/Gemfile new file mode 100644 index 00000000000..2ad03adfb21 --- /dev/null +++ b/frameworks/Ruby/rack-app/Gemfile @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +gem 'rack-app' +gem 'rack-app-front_end' +gem 'iodine', '~> 0.7', platforms: %i[ruby windows] +gem 'irb' # for Ruby 3.5 +gem 'logger' # for Ruby 3.5 +gem 'json', '~> 2.10' +gem 'pg', '~> 1.5' +gem 'sequel', '~> 5.0' +gem 'sequel_pg', '~> 1.6', require: false diff --git a/frameworks/Ruby/rack-app/Gemfile.lock b/frameworks/Ruby/rack-app/Gemfile.lock new file mode 100644 index 00000000000..2620ee87445 --- /dev/null +++ b/frameworks/Ruby/rack-app/Gemfile.lock @@ -0,0 +1,63 @@ +GEM + remote: https://rubygems.org/ + specs: + bigdecimal (3.3.1) + date (3.5.0) + erb (5.1.3) + io-console (0.8.1) + iodine (0.7.58) + irb (1.15.3) + pp (>= 0.6.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + json (2.16.0) + logger (1.7.0) + pg (1.6.2) + pg (1.6.2-arm64-darwin) + pp (0.6.3) + prettyprint + prettyprint (0.2.0) + psych (5.2.6) + date + stringio + rack (3.2.4) + rack-app (11.0.2) + rack (>= 3.0.0) + rackup + rack-app-front_end (0.22.2) + rack-app (>= 6.3.1) + tilt + rackup (2.2.1) + rack (>= 3) + rdoc (6.15.1) + erb + psych (>= 4.0.0) + tsort + reline (0.6.2) + io-console (~> 0.5) + sequel (5.98.0) + bigdecimal + sequel_pg (1.17.2) + pg (>= 0.18.0, != 1.2.0) + sequel (>= 4.38.0) + stringio (3.1.7) + tilt (2.6.1) + tsort (0.2.0) + +PLATFORMS + arm64-darwin-24 + ruby + +DEPENDENCIES + iodine (~> 0.7) + irb + json (~> 2.10) + logger + pg (~> 1.5) + rack-app + rack-app-front_end + sequel (~> 5.0) + sequel_pg (~> 1.6) + +BUNDLED WITH + 2.7.2 diff --git a/frameworks/Ruby/rack-app/README.md b/frameworks/Ruby/rack-app/README.md new file mode 100644 index 00000000000..585c970919e --- /dev/null +++ b/frameworks/Ruby/rack-app/README.md @@ -0,0 +1,44 @@ +# Rack-app Benchmarking Test + +rack-app is a minimalist web framework that focuses on simplicity and +maintainability. The framework is meant to be used by seasoned web developers. + +https://github.com/rack-app/rack-app + +### Test Type Implementation Source Code + +* [JSON Serialization](app.rb): "/json" +* [Single Database Query](app.rb): "/db" +* [Multiple Database Queries](app.rb): "/db?queries={#}" +* [Fortunes](app.rb): "/fortune" +* [Plaintext](app.rb): "/plaintext" + +## Important Libraries + +The tests were run with: + +* [Sequel](https://rubygems.org/gems/sequel) +* [PG](https://rubygems.org/gems/pg) + +## Test URLs + +### JSON + +http://localhost:8080/json + +### PLAINTEXT + +http://localhost:8080/plaintext + +### DB + +http://localhost:8080/db + +### QUERY + +http://localhost:8080/queries?queries= + +### FORTUNES + +http://localhost:8080/fortunes + diff --git a/frameworks/Ruby/rack-app/app.rb b/frameworks/Ruby/rack-app/app.rb new file mode 100644 index 00000000000..e5310fc012d --- /dev/null +++ b/frameworks/Ruby/rack-app/app.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +require 'rack/app' +require 'rack/app/front_end' +require 'json' + +class App < Rack::App + MAX_PK = 10_000 + ID_RANGE = (1..10_000).freeze + ALL_IDS = ID_RANGE.to_a + QUERIES_MIN = 1 + QUERIES_MAX = 500 + JSON_TYPE = 'application/json' + HTML_TYPE = 'text/html; charset=utf-8' + PLAINTEXT_TYPE = 'text/plain' + + apply_extensions :front_end + + helpers do + def fortunes + fortunes = Fortune.all + fortunes << Fortune.new( + id: 0, + message: "Additional fortune added at request time." + ) + fortunes.sort_by!(&:message) + end + end + + get '/json' do + set_headers(JSON_TYPE) + { message: 'Hello, World!' }.to_json + end + + get '/db' do + set_headers(JSON_TYPE) + World.with_pk(rand1).values.to_json + end + + get '/queries' do + set_headers(JSON_TYPE) + ids = ALL_IDS.sample(bounded_queries) + DB.synchronize do + ids.map do |id| + World.with_pk(id).values + end + end.to_json + end + + get '/fortunes' do + set_headers(HTML_TYPE) + render 'fortunes.html.erb' + end + + get '/plaintext' do + set_headers(PLAINTEXT_TYPE) + 'Hello, World!' + end + + private + + # Return a random number between 1 and MAX_PK + def rand1 + rand(MAX_PK).succ + end + + def bounded_queries + queries = params['queries'].to_i + queries.clamp(QUERIES_MIN, QUERIES_MAX) + end + + def set_headers(content_type) + response.headers[::Rack::CONTENT_TYPE] = content_type + response.headers['Server'] = 'rack-app' + end +end diff --git a/frameworks/Ruby/rack-app/app/fortunes.html.erb b/frameworks/Ruby/rack-app/app/fortunes.html.erb new file mode 100644 index 00000000000..56c5c540270 --- /dev/null +++ b/frameworks/Ruby/rack-app/app/fortunes.html.erb @@ -0,0 +1,12 @@ + + + Fortunes + + + + <% fortunes.each do |record| %> + + <% end %> +
idmessage
<%= record.id %><%= ERB::Escape.html_escape(record.message) %>
+ + diff --git a/frameworks/Crystal/onyx/benchmark_config.json b/frameworks/Ruby/rack-app/benchmark_config.json old mode 100755 new mode 100644 similarity index 51% rename from frameworks/Crystal/onyx/benchmark_config.json rename to frameworks/Ruby/rack-app/benchmark_config.json index a0646d4084c..d25acd9a641 --- a/frameworks/Crystal/onyx/benchmark_config.json +++ b/frameworks/Ruby/rack-app/benchmark_config.json @@ -1,28 +1,26 @@ { - "framework": "onyx", + "framework": "rack-app", "tests": [ { "default": { "json_url": "/json", + "plaintext_url": "/plaintext", "db_url": "/db", "query_url": "/queries?queries=", - "update_url": "/updates?queries=", - "plaintext_url": "/plaintext", + "fortune_url": "/fortunes", "port": 8080, "approach": "Realistic", - "classification": "Fullstack", - "database": "Postgres", - "framework": "Onyx", - "language": "Crystal", - "flavor": "None", + "classification": "Micro", "orm": "Full", - "platform": "None", - "webserver": "None", + "database": "Postgres", + "framework": "rack-app", + "language": "Ruby", + "platform": "Mri", + "webserver": "Iodine", "os": "Linux", "database_os": "Linux", - "display_name": "Onyx (PostgreSQL)", - "notes": "", - "versus": "None" + "display_name": "rack-app", + "notes": "" } } ] diff --git a/frameworks/Ruby/rack-app/boot.rb b/frameworks/Ruby/rack-app/boot.rb new file mode 100644 index 00000000000..7711f76a0a1 --- /dev/null +++ b/frameworks/Ruby/rack-app/boot.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true +require 'bundler/setup' +require 'time' + +MAX_PK = 10_000 +ID_RANGE = (1..MAX_PK).freeze +ALL_IDS = ID_RANGE.to_a +QUERIES_MIN = 1 +QUERIES_MAX = 500 +SEQUEL_NO_ASSOCIATIONS = true +#SERVER_STRING = "Sinatra" + +Bundler.require(:default) # Load core modules + +def connect(dbtype) + Bundler.require(dbtype) # Load database-specific modules + + opts = {} + + adapter = 'postgresql' + + # Determine threading/thread pool size and timeout + if defined?(Puma) && (threads = Puma.cli_config.options.fetch(:max_threads)) > 1 + opts[:max_connections] = threads + opts[:pool_timeout] = 10 + else + opts[:max_connections] = 512 + end + + Sequel.connect \ + '%{adapter}://%{host}/%{database}?user=%{user}&password=%{password}' % { + adapter: adapter, + host: 'tfb-database', + database: 'hello_world', + user: 'benchmarkdbuser', + password: 'benchmarkdbpass' + }, opts +end + +DB = connect 'postgres' + +# Define ORM models +class World < Sequel::Model(:World) + def_column_alias(:randomnumber, :randomNumber) if DB.database_type == :mysql + + def self.batch_update(worlds) + if DB.database_type == :mysql + worlds.map(&:save_changes) + else + ids = [] + sql = String.new("UPDATE world SET randomnumber = CASE id ") + worlds.each do |world| + sql << "when #{world.id} then #{world.randomnumber} " + ids << world.id + end + sql << "ELSE randomnumber END WHERE id IN ( #{ids.join(',')})" + DB.run(sql) + end + end +end + +class Fortune < Sequel::Model(:Fortune) + # Allow setting id to zero (0) per benchmark requirements + unrestrict_primary_key +end + +[World, Fortune].each(&:freeze) +DB.freeze diff --git a/frameworks/Ruby/rack-app/config.ru b/frameworks/Ruby/rack-app/config.ru new file mode 100644 index 00000000000..27540c2f4ee --- /dev/null +++ b/frameworks/Ruby/rack-app/config.ru @@ -0,0 +1,5 @@ +# frozen_string_literal: true +require_relative 'boot' +require_relative 'app' + +run App diff --git a/frameworks/Ruby/rack-app/config/auto_tune.rb b/frameworks/Ruby/rack-app/config/auto_tune.rb new file mode 100644 index 00000000000..1e075f56911 --- /dev/null +++ b/frameworks/Ruby/rack-app/config/auto_tune.rb @@ -0,0 +1,43 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# Instantiate about one process per X MiB of available memory, scaling up to as +# close to MAX_THREADS as possible while observing an upper bound based on the +# number of virtual/logical CPUs. If there are fewer processes than +# MAX_THREADS, add threads per process to reach MAX_THREADS. +require 'etc' + +KB_PER_WORKER = 64 * 1_024 # average of peak PSS of single-threaded processes (watch smem -k) +MIN_WORKERS = 2 +MAX_WORKERS_PER_VCPU = 1.25 # virtual/logical +MIN_THREADS_PER_WORKER = 1 +MAX_THREADS = Integer(ENV['MAX_CONCURRENCY'] || 256) + +def meminfo(arg) + File.open('/proc/meminfo') do |f| + f.each_line do |line| + key, value = line.split(/:\s+/) + return value.split(/\s+/).first.to_i if key == arg + end + end + + raise "Unable to find `#{arg}' in /proc/meminfo!" +end + +def auto_tune + avail_mem = meminfo('MemAvailable') * 0.8 - MAX_THREADS * 1_024 + + workers = [ + [(1.0 * avail_mem / KB_PER_WORKER).floor, MIN_WORKERS].max, + [(Etc.nprocessors * MAX_WORKERS_PER_VCPU).ceil, MIN_WORKERS].max + ].min + + threads_per_worker = [ + workers < MAX_THREADS ? (1.0 * MAX_THREADS / workers).ceil : -Float::INFINITY, + MIN_THREADS_PER_WORKER + ].max + + [workers, threads_per_worker] +end + +p auto_tune if $PROGRAM_NAME == __FILE__ diff --git a/frameworks/Ruby/roda-sequel/config/mri_puma.rb b/frameworks/Ruby/rack-app/config/puma.rb similarity index 81% rename from frameworks/Ruby/roda-sequel/config/mri_puma.rb rename to frameworks/Ruby/rack-app/config/puma.rb index 794c18f0c08..1b6d05d8ac0 100644 --- a/frameworks/Ruby/roda-sequel/config/mri_puma.rb +++ b/frameworks/Ruby/rack-app/config/puma.rb @@ -1,7 +1,7 @@ require_relative 'auto_tune' # FWBM only... use the puma_auto_tune gem in production! -_, num_threads = auto_tune +_num_workers, num_threads = auto_tune threads num_threads diff --git a/frameworks/Ruby/rack-app/rack-app.dockerfile b/frameworks/Ruby/rack-app/rack-app.dockerfile new file mode 100644 index 00000000000..2b24fcab8bd --- /dev/null +++ b/frameworks/Ruby/rack-app/rack-app.dockerfile @@ -0,0 +1,21 @@ +FROM ruby:3.5-rc + +ENV RUBY_YJIT_ENABLE=1 + +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + +WORKDIR /rack-app + +COPY Gemfile* ./ + +ENV BUNDLE_FORCE_RUBY_PLATFORM=true +RUN bundle install --jobs=8 + +COPY . . + +EXPOSE 8080 + +CMD bundle exec iodine -p 8080 -w $(ruby config/auto_tune.rb | grep -Eo '[0-9]+' | head -n 1) diff --git a/frameworks/Ruby/rack-sequel/Gemfile.lock b/frameworks/Ruby/rack-sequel/Gemfile.lock index 25aedc6282a..7f052698932 100644 --- a/frameworks/Ruby/rack-sequel/Gemfile.lock +++ b/frameworks/Ruby/rack-sequel/Gemfile.lock @@ -3,7 +3,7 @@ GEM specs: bigdecimal (3.3.1) concurrent-ruby (1.3.5) - json (2.13.2) + json (2.16.0) nio4r (2.7.4) pg (1.6.2) pg (1.6.2-x86_64-darwin) diff --git a/frameworks/Ruby/rack-sequel/benchmark_config.json b/frameworks/Ruby/rack-sequel/benchmark_config.json index 8c81927c69f..15763639c4c 100644 --- a/frameworks/Ruby/rack-sequel/benchmark_config.json +++ b/frameworks/Ruby/rack-sequel/benchmark_config.json @@ -18,7 +18,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "rack-sequel-puma-mri", + "display_name": "rack-sequel [puma, mysql]", "versus": "rack-puma-mri", "notes": "" }, @@ -38,7 +38,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "rack-sequel-postgres-puma-mri", + "display_name": "rack-sequel [puma, postgres]", "versus": null, "notes": "" } diff --git a/frameworks/Ruby/rack-sequel/boot.rb b/frameworks/Ruby/rack-sequel/boot.rb index 9c06a7f981f..91594951944 100644 --- a/frameworks/Ruby/rack-sequel/boot.rb +++ b/frameworks/Ruby/rack-sequel/boot.rb @@ -20,8 +20,8 @@ def connect(dbtype) end # Determine threading/thread pool size and timeout - if defined?(Puma) && (threads = Puma.cli_config.options.fetch(:max_threads)) > 1 - opts[:max_connections] = threads + if defined?(Puma) + opts[:max_connections] = ENV.fetch('MAX_THREADS') opts[:pool_timeout] = 10 else opts[:max_connections] = 512 diff --git a/frameworks/Ruby/rack-sequel/config/mri_puma.rb b/frameworks/Ruby/rack-sequel/config/mri_puma.rb deleted file mode 100644 index d70db95a94f..00000000000 --- a/frameworks/Ruby/rack-sequel/config/mri_puma.rb +++ /dev/null @@ -1,10 +0,0 @@ -require_relative 'auto_tune' - -# FWBM only... use the puma_auto_tune gem in production! -_, num_threads = auto_tune - -threads num_threads, num_threads - -before_fork do - Sequel::DATABASES.each(&:disconnect) -end diff --git a/frameworks/Ruby/rack-sequel/config/puma.rb b/frameworks/Ruby/rack-sequel/config/puma.rb new file mode 100644 index 00000000000..907837b4892 --- /dev/null +++ b/frameworks/Ruby/rack-sequel/config/puma.rb @@ -0,0 +1,3 @@ +before_fork do + Sequel::DATABASES.each(&:disconnect) +end diff --git a/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile b/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile index 65728878595..a1cf4826f9c 100644 --- a/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile +++ b/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ADD ./ /rack-sequel @@ -17,6 +17,8 @@ RUN bundle install --jobs=4 --gemfile=/rack-sequel/Gemfile ENV DBTYPE=postgresql ENV WEB_CONCURRENCY=auto +ENV MAX_THREADS=5 + EXPOSE 8080 -CMD bundle exec puma -C config/mri_puma.rb -b tcp://0.0.0.0:8080 -e production +CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 -e production diff --git a/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile b/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile index a7e0c901daa..bf8a4a28f13 100644 --- a/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile +++ b/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ADD ./ /rack-sequel @@ -17,6 +17,8 @@ RUN bundle install --jobs=4 --gemfile=/rack-sequel/Gemfile ENV DBTYPE=mysql ENV WEB_CONCURRENCY=auto +ENV MAX_THREADS=5 + EXPOSE 8080 -CMD bundle exec puma -C config/mri_puma.rb -b tcp://0.0.0.0:8080 -e production +CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 -e production diff --git a/frameworks/Ruby/rack/Gemfile b/frameworks/Ruby/rack/Gemfile index 091baa8d0e4..47ec614226a 100644 --- a/frameworks/Ruby/rack/Gemfile +++ b/frameworks/Ruby/rack/Gemfile @@ -15,13 +15,17 @@ gem 'sequel_pg', platforms: %i[ruby windows] gem 'tzinfo-data', '1.2023.3' group :falcon, optional: true do - gem 'falcon', '~> 0.47', platforms: %i[ruby windows] + gem 'falcon', '~> 0.52', platforms: %i[ruby windows] end group :iodine, optional: true do gem 'iodine', '~> 0.7', platforms: %i[ruby windows] end +group :itsi, optional: true do + gem 'itsi' +end + group :passenger, optional: true do gem 'logger' # required by passenger on Ruby 3.5 gem 'passenger', '~> 6.1', platforms: [:ruby, :windows], require: false diff --git a/frameworks/Ruby/rack/Gemfile.lock b/frameworks/Ruby/rack/Gemfile.lock index 0322d2109ed..7028b8ed05d 100644 --- a/frameworks/Ruby/rack/Gemfile.lock +++ b/frameworks/Ruby/rack/Gemfile.lock @@ -2,47 +2,53 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.2) - async (2.23.0) + async (2.34.0) console (~> 1.29) fiber-annotation - io-event (~> 1.9) + io-event (~> 1.11) metrics (~> 0.12) - traces (~> 0.15) - async-container (0.24.0) + traces (~> 0.18) + async-container (0.27.7) async (~> 2.22) - async-container-supervisor (0.5.1) - async-container (~> 0.22) + async-container-supervisor (0.9.1) async-service io-endpoint + memory (~> 0.7) memory-leak (~> 0.5) - async-http (0.87.0) + process-metrics + async-http (0.92.1) async (>= 2.10.2) - async-pool (~> 0.9) + async-pool (~> 0.11) io-endpoint (~> 0.14) io-stream (~> 0.6) metrics (~> 0.12) protocol-http (~> 0.49) protocol-http1 (~> 0.30) protocol-http2 (~> 0.22) + protocol-url (~> 0.2) traces (~> 0.10) - async-http-cache (0.4.5) + async-http-cache (0.4.6) async-http (~> 0.56) - async-pool (0.10.3) - async (>= 1.25) - async-service (0.13.0) + async-pool (0.11.0) + async (>= 2.0) + async-service (0.14.4) async async-container (~> 0.16) + string-format (~> 0.2) + bake (0.24.1) + bigdecimal + samovar (~> 2.1) bigdecimal (3.1.9) concurrent-ruby (1.3.5) connection_pool (2.5.0) - console (1.30.0) + console (1.34.2) fiber-annotation fiber-local (~> 1.1) json - falcon (0.51.1) + falcon (0.52.4) async async-container (~> 0.20) - async-container-supervisor (~> 0.5.0) + async-container-supervisor (~> 0.6) async-http (~> 0.75) async-http-cache (~> 0.4) async-service (~> 0.10) @@ -55,21 +61,36 @@ GEM fiber-annotation (0.2.0) fiber-local (1.1.0) fiber-storage - fiber-storage (1.0.0) + fiber-storage (1.0.1) io-endpoint (0.15.2) - io-event (1.9.0) - io-stream (0.6.1) + io-event (1.14.2) + io-stream (0.11.0) iodine (0.7.58) - json (2.13.2) + itsi (0.2.18) + itsi-scheduler (~> 0.2.18) + itsi-server (~> 0.2.18) + itsi-scheduler (0.2.18) + rb_sys (~> 0.9.91) + itsi-server (0.2.18) + json (~> 2) + prism (~> 1.4) + rack (>= 1.6) + rb_sys (~> 0.9.91) + json (2.16.0) language_server-protocol (3.17.0.4) lint_roller (1.1.0) - localhost (1.3.1) + localhost (1.6.0) logger (1.6.6) - mapping (1.1.1) - memory-leak (0.5.2) - metrics (0.12.2) + mapping (1.1.3) + memory (0.12.0) + bake (~> 0.15) + console + msgpack + memory-leak (0.7.0) + metrics (0.15.0) + msgpack (1.8.0) nio4r (2.7.4) - openssl (3.3.0) + openssl (3.3.2) parallel (1.26.3) parser (3.3.7.1) ast (~> 2.4.1) @@ -84,26 +105,36 @@ GEM pitchfork (0.17.0) logger rack (>= 2.0) + prism (1.4.0) + process-metrics (0.7.0) + console (~> 1.8) + json (~> 2) + samovar (~> 2.1) protocol-hpack (1.5.1) - protocol-http (0.54.0) + protocol-http (0.55.0) protocol-http1 (0.35.2) protocol-http (~> 0.22) - protocol-http2 (0.22.1) + protocol-http2 (0.23.0) protocol-hpack (~> 1.4) protocol-http (~> 0.47) - protocol-rack (0.11.2) + protocol-rack (0.16.0) + io-stream (>= 0.10) protocol-http (~> 0.43) rack (>= 1.0) + protocol-url (0.4.0) puma (7.1.0) nio4r (~> 2.0) racc (1.8.1) - rack (3.2.2) + rack (3.2.4) rack-test (2.2.0) rack (>= 1.3) rackup (2.2.1) rack (>= 3) rainbow (3.1.1) rake (13.3.0) + rake-compiler-dock (1.9.1) + rb_sys (0.9.117) + rake-compiler-dock (= 1.9.1) regexp_parser (2.10.0) rubocop (1.73.2) json (~> 2.3) @@ -119,7 +150,7 @@ GEM rubocop-ast (1.38.1) parser (>= 3.3.1.0) ruby-progressbar (1.13.0) - samovar (2.3.0) + samovar (2.4.1) console (~> 1.0) mapping (~> 1.0) sequel (5.90.0) @@ -127,7 +158,8 @@ GEM sequel_pg (1.17.1) pg (>= 0.18.0, != 1.2.0) sequel (>= 4.38.0) - traces (0.15.2) + string-format (0.2.0) + traces (0.18.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) tzinfo-data (1.2023.3) @@ -143,8 +175,9 @@ PLATFORMS DEPENDENCIES connection_pool (~> 2.4) - falcon (~> 0.47) + falcon (~> 0.52) iodine (~> 0.7) + itsi jdbc-postgres (~> 42.2) json (~> 2.10) logger diff --git a/frameworks/Ruby/rack/README.md b/frameworks/Ruby/rack/README.md index 53a5d5c5b09..4dd0a7d3954 100644 --- a/frameworks/Ruby/rack/README.md +++ b/frameworks/Ruby/rack/README.md @@ -13,12 +13,13 @@ The tests were run with: * [Ruby 3.4](http://www.ruby-lang.org/) * [JRuby 9.4](http://jruby.org/) -* [Rack 3.1](http://rack.github.com/) -* [Unicorn 6.1.0](http://unicorn.bogomips.org/) -* [Puma 7](http://puma.io/) -* [Iodine](https://github.com/boazsegev/iodine) +* [Rack 3](http://rack.github.com/) * [Falcon](https://github.com/socketry/falcon) +* [Iodine](https://github.com/boazsegev/iodine) +* [Itsi](https://github.com/wouterken/itsi) +* [Passenger](https://github.com/phusion/passenger) * [Pitchfork](https://github.com/Shopify/pitchfork) +* [Puma](http://puma.io/) * [Sequel 5](https://sequel.jeremyevans.net/) diff --git a/frameworks/Ruby/rack/benchmark_config.json b/frameworks/Ruby/rack/benchmark_config.json index dec94fec3a9..031e00dc5e9 100644 --- a/frameworks/Ruby/rack/benchmark_config.json +++ b/frameworks/Ruby/rack/benchmark_config.json @@ -20,7 +20,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "rack-puma-mri-sequel-raw", + "display_name": "rack [puma]", "notes": "" }, "iodine": { @@ -41,7 +41,7 @@ "webserver": "Iodine", "os": "Linux", "database_os": "Linux", - "display_name": "rack-iodine-mri-sequel-raw", + "display_name": "rack [iodine]", "notes": "" }, "falcon": { @@ -62,7 +62,28 @@ "webserver": "Falcon", "os": "Linux", "database_os": "Linux", - "display_name": "rack-falcon-mri-sequel-raw", + "display_name": "rack [falcon]", + "notes": "" + }, + "itsi": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "db_url": "/db", + "query_url": "/queries?queries=", + "fortune_url": "/fortunes", + "update_url": "/updates?queries=", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "orm": "raw", + "database": "Postgres", + "framework": "rack", + "language": "Ruby", + "platform": "Mri", + "webserver": "Itsi", + "os": "Linux", + "database_os": "Linux", + "display_name": "rack [itsi]", "notes": "" }, "jruby": { @@ -83,7 +104,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "rack-puma-jruby-sequel-raw", + "display_name": "rack [jruby, puma]", "notes": "" }, "passenger": { @@ -104,7 +125,7 @@ "webserver": "Passenger", "os": "Linux", "database_os": "Linux", - "display_name": "rack-passenger-mri-sequel-raw", + "display_name": "rack [passenger]", "notes": "" }, "pitchfork": { @@ -125,7 +146,7 @@ "webserver": "Pitchfork", "os": "Linux", "database_os": "Linux", - "display_name": "rack-pitchfork-mri-sequel-raw", + "display_name": "rack [pitchfork]", "notes": "" } } diff --git a/frameworks/Ruby/rack/config/itsi.rb b/frameworks/Ruby/rack/config/itsi.rb new file mode 100644 index 00000000000..d0dd0992dc1 --- /dev/null +++ b/frameworks/Ruby/rack/config/itsi.rb @@ -0,0 +1,13 @@ +require_relative 'auto_tune' + +rackup_file './config.ru' + +ruby_thread_request_backlog_size 10_000 + +preload false + +num_workers, num_threads = auto_tune + +workers num_workers +threads num_threads +fiber_scheduler false diff --git a/frameworks/Ruby/rack/config/puma.rb b/frameworks/Ruby/rack/config/puma.rb index 5f6c878f757..18a4851a761 100644 --- a/frameworks/Ruby/rack/config/puma.rb +++ b/frameworks/Ruby/rack/config/puma.rb @@ -1,17 +1,11 @@ -require_relative 'auto_tune' - -# FWBM only... use the puma_auto_tune gem in production! -num_workers, num_threads = auto_tune - -if RUBY_PLATFORM == 'java' - num_threads = 512 - num_workers = 0 -end - -threads num_threads - -if num_workers > 0 +if ENV.fetch('WEB_CONCURRENCY') == 'auto' before_fork do Sequel::DATABASES.each(&:disconnect) end +else + workers ENV.fetch('WEB_CONCURRENCY') + require 'concurrent/utility/processor_counter' + threads = (::Concurrent.available_processor_count * 1.5).to_i + threads threads + ENV['MAX_THREADS'] = threads.to_s end diff --git a/frameworks/Ruby/rack/hello_world.rb b/frameworks/Ruby/rack/hello_world.rb index fdfbe679e00..9944ac45d40 100644 --- a/frameworks/Ruby/rack/hello_world.rb +++ b/frameworks/Ruby/rack/hello_world.rb @@ -6,6 +6,7 @@ require_relative 'config/auto_tune' require 'rack' require 'json' +require 'erb' if RUBY_PLATFORM == 'java' DEFAULT_DATABASE_URL = 'jdbc:postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass' @@ -42,8 +43,12 @@ class HelloWorld ' def initialize - if defined?(Puma) && (threads = Puma.cli_config.options.fetch(:max_threads)) > 1 - max_connections = threads + if defined?(Puma) + max_connections = ENV.fetch('MAX_THREADS') + elsif defined?(Itsi) + require_relative 'config/auto_tune' + _num_workers, num_threads = auto_tune + max_connections = num_threads else max_connections = 512 end diff --git a/frameworks/Ruby/rack/pg_db.rb b/frameworks/Ruby/rack/pg_db.rb index bcaa1dad480..c7b2c78cc6d 100644 --- a/frameworks/Ruby/rack/pg_db.rb +++ b/frameworks/Ruby/rack/pg_db.rb @@ -7,8 +7,6 @@ Jdbc::Postgres.load_driver end - - class PgDb QUERY_RANGE = (1..10_000).freeze # range of IDs in the Fortune DB ALL_IDS = QUERY_RANGE.to_a # enumeration of all the IDs in fortune DB @@ -18,7 +16,7 @@ class PgDb attr_reader :connection def initialize(connection_string = nil, max_connections = 512) - @connection = Sequel.connect(connection_string, max_connections: max_connections, sql_log_level: :warning) + @connection = Sequel.connect(connection_string, max_connections: max_connections) Sequel.extension :fiber_concurrency if defined?(Falcon) prepare_statements @@ -53,13 +51,6 @@ def select_promises(count) end end - def select_random_numbers(count) - count = validate_count(count) - ALL_IDS.sample(count).map do |id| - @world_random_select.call(randomvalue: random_id, id: id).first - end - end - def select_worlds(count) count = validate_count(count) ALL_IDS.sample(count).map do |id| @@ -78,8 +69,7 @@ def update_worlds(count, async = false) else select_worlds(count) end - #values = [] - ids=[] + ids = [] sql = String.new("UPDATE world SET randomnumber = CASE id ") results.each do |r| r[:randomnumber] = random_id diff --git a/frameworks/Ruby/rack/rack-iodine.dockerfile b/frameworks/Ruby/rack/rack-iodine.dockerfile index 0c4f7aafc6d..26f65700e15 100644 --- a/frameworks/Ruby/rack/rack-iodine.dockerfile +++ b/frameworks/Ruby/rack/rack-iodine.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 diff --git a/frameworks/Ruby/rack/rack-itsi.dockerfile b/frameworks/Ruby/rack/rack-itsi.dockerfile new file mode 100644 index 00000000000..952ac7ccdad --- /dev/null +++ b/frameworks/Ruby/rack/rack-itsi.dockerfile @@ -0,0 +1,24 @@ +FROM ruby:3.5-rc + +ENV RUBY_YJIT_ENABLE=1 + +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + +RUN apt-get install -y build-essential libclang-dev + +WORKDIR /rack + +COPY Gemfile* ./ + +ENV BUNDLE_FORCE_RUBY_PLATFORM=true +RUN bundle config set with 'itsi' +RUN bundle install --jobs=8 + +COPY . . + +EXPOSE 8080 + +CMD bundle exec itsi start -C config/itsi.rb --bind "http://tfb-server:8080" diff --git a/frameworks/Ruby/rack/rack-jruby.dockerfile b/frameworks/Ruby/rack/rack-jruby.dockerfile index 062547508ca..3e786c1a2e5 100644 --- a/frameworks/Ruby/rack/rack-jruby.dockerfile +++ b/frameworks/Ruby/rack/rack-jruby.dockerfile @@ -6,13 +6,15 @@ WORKDIR /rack COPY Gemfile* ./ +#RUN echo $(ruby config/auto_tune.rb | grep -Eo '[0-9]+' | head -n 1) + RUN bundle config set with 'puma' RUN bundle install --jobs=8 COPY . . -EXPOSE 8080 +ENV WEB_CONCURRENCY=0 -CMD config/java_tune.sh +EXPOSE 8080 CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 -e production diff --git a/frameworks/Ruby/rack/rack-passenger.dockerfile b/frameworks/Ruby/rack/rack-passenger.dockerfile index bde26ea58bc..115f5740f1c 100644 --- a/frameworks/Ruby/rack/rack-passenger.dockerfile +++ b/frameworks/Ruby/rack/rack-passenger.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 diff --git a/frameworks/Ruby/rack/rack-pitchfork.dockerfile b/frameworks/Ruby/rack/rack-pitchfork.dockerfile index bebaf61bcb4..1546e882b4e 100644 --- a/frameworks/Ruby/rack/rack-pitchfork.dockerfile +++ b/frameworks/Ruby/rack/rack-pitchfork.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 diff --git a/frameworks/Ruby/rack/rack.dockerfile b/frameworks/Ruby/rack/rack.dockerfile index ce1c639ea11..dea3795b187 100644 --- a/frameworks/Ruby/rack/rack.dockerfile +++ b/frameworks/Ruby/rack/rack.dockerfile @@ -1,7 +1,6 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 -ENV RUBY_THREAD_TIMESLICE=10 # Use Jemalloc RUN apt-get update && \ @@ -18,7 +17,9 @@ RUN bundle install --jobs=8 COPY . . -EXPOSE 8080 ENV WEB_CONCURRENCY=auto +ENV MAX_THREADS=5 + +EXPOSE 8080 CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 -e production diff --git a/frameworks/Ruby/rage-sequel/Gemfile b/frameworks/Ruby/rage-sequel/Gemfile index c3d6bfb0968..35b2df23c98 100644 --- a/frameworks/Ruby/rage-sequel/Gemfile +++ b/frameworks/Ruby/rage-sequel/Gemfile @@ -1,6 +1,6 @@ source "https://rubygems.org" -gem "rage-rb", "~> 1.10" +gem "rage-rb", "~> 1.17.0" gem "pg", "~> 1.0" gem 'sequel', '~> 5.0' diff --git a/frameworks/Ruby/rage-sequel/Gemfile.lock b/frameworks/Ruby/rage-sequel/Gemfile.lock index 566a7025400..fb432a9f4d3 100644 --- a/frameworks/Ruby/rage-sequel/Gemfile.lock +++ b/frameworks/Ruby/rage-sequel/Gemfile.lock @@ -8,11 +8,11 @@ GEM rack (2.2.20) rack-test (2.2.0) rack (>= 1.3) - rage-iodine (4.0.0) - rage-rb (1.11.0) + rage-iodine (4.4.0) + rage-rb (1.17.1) rack (~> 2.0) rack-test (~> 2.1) - rage-iodine (~> 4.0) + rage-iodine (~> 4.3) rake (>= 12.0) thor (~> 1.0) zeitwerk (~> 2.6) @@ -32,7 +32,7 @@ PLATFORMS DEPENDENCIES logger pg (~> 1.0) - rage-rb (~> 1.10) + rage-rb (~> 1.17.0) sequel (~> 5.0) sequel_pg (~> 1.6) diff --git a/frameworks/Ruby/rage-sequel/rage-sequel.dockerfile b/frameworks/Ruby/rage-sequel/rage-sequel.dockerfile index 41bfd349920..68a57f4b52a 100644 --- a/frameworks/Ruby/rage-sequel/rage-sequel.dockerfile +++ b/frameworks/Ruby/rage-sequel/rage-sequel.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc EXPOSE 8080 WORKDIR /rage-sequel diff --git a/frameworks/Ruby/rage/Gemfile b/frameworks/Ruby/rage/Gemfile index ad9ccba5aa8..f2a24ddb082 100644 --- a/frameworks/Ruby/rage/Gemfile +++ b/frameworks/Ruby/rage/Gemfile @@ -1,6 +1,6 @@ source "https://rubygems.org" -gem "rage-rb", "~> 1.10" +gem "rage-rb", "~> 1.17.0" gem "pg", "~> 1.0" gem "activerecord", "~> 8.0.0", require: "active_record" diff --git a/frameworks/Ruby/rage/Gemfile.lock b/frameworks/Ruby/rage/Gemfile.lock index d5d524b3192..f0bf4cd1dad 100644 --- a/frameworks/Ruby/rage/Gemfile.lock +++ b/frameworks/Ruby/rage/Gemfile.lock @@ -35,11 +35,11 @@ GEM rack (2.2.18) rack-test (2.2.0) rack (>= 1.3) - rage-iodine (4.0.0) - rage-rb (1.11.0) + rage-iodine (4.4.0) + rage-rb (1.17.1) rack (~> 2.0) rack-test (~> 2.1) - rage-iodine (~> 4.0) + rage-iodine (~> 4.3) rake (>= 12.0) thor (~> 1.0) zeitwerk (~> 2.6) @@ -59,7 +59,7 @@ PLATFORMS DEPENDENCIES activerecord (~> 8.0.0) pg (~> 1.0) - rage-rb (~> 1.10) + rage-rb (~> 1.17.0) BUNDLED WITH 2.7.0 diff --git a/frameworks/Ruby/rage/rage.dockerfile b/frameworks/Ruby/rage/rage.dockerfile index e73bb58f8c9..d70e975a853 100644 --- a/frameworks/Ruby/rage/rage.dockerfile +++ b/frameworks/Ruby/rage/rage.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc EXPOSE 8080 WORKDIR /rage diff --git a/frameworks/Ruby/rails/Gemfile.lock b/frameworks/Ruby/rails/Gemfile.lock index 5b86a8d2e48..c14a68a3c0e 100644 --- a/frameworks/Ruby/rails/Gemfile.lock +++ b/frameworks/Ruby/rails/Gemfile.lock @@ -155,7 +155,7 @@ GEM pp (>= 0.6.0) rdoc (>= 4.0.0) reline (>= 0.4.2) - json (2.15.2) + json (2.16.0) localhost (1.6.0) logger (1.7.0) loofah (2.24.1) diff --git a/frameworks/Ruby/rails/benchmark_config.json b/frameworks/Ruby/rails/benchmark_config.json index 232a4321e56..5f86a525145 100644 --- a/frameworks/Ruby/rails/benchmark_config.json +++ b/frameworks/Ruby/rails/benchmark_config.json @@ -20,7 +20,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "rails-postgresql", + "display_name": "rails [puma, postgres]", "notes": "", "versus": "" }, @@ -41,7 +41,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "rails-mysql", + "display_name": "rails [puma, mysql]", "notes": "", "versus": "rack-puma-mri" }, @@ -64,7 +64,7 @@ "webserver": "Falcon", "os": "Linux", "database_os": "Linux", - "display_name": "rails-falcon", + "display_name": "rails [falcon]", "notes": "", "versus": "rack-falcon-mri-sequel-raw" }, @@ -87,7 +87,7 @@ "webserver": "Iodine", "os": "Linux", "database_os": "Linux", - "display_name": "rails-iodine", + "display_name": "rails [iodine]", "notes": "", "versus": "rack-iodine-mri-sequel-raw" }, @@ -110,7 +110,7 @@ "webserver": "Pitchfork", "os": "Linux", "database_os": "Linux", - "display_name": "rails-pitchfork", + "display_name": "rails [pitchfork]", "notes": "", "versus": "rack-pitchfork-mri-sequel-raw" } diff --git a/frameworks/Ruby/rails/rails-falcon.dockerfile b/frameworks/Ruby/rails/rails-falcon.dockerfile index 6ede5622c05..c92590a0f19 100644 --- a/frameworks/Ruby/rails/rails-falcon.dockerfile +++ b/frameworks/Ruby/rails/rails-falcon.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends redis-server diff --git a/frameworks/Ruby/rails/rails-iodine.dockerfile b/frameworks/Ruby/rails/rails-iodine.dockerfile index ceab1c1ba4f..90020e652fa 100644 --- a/frameworks/Ruby/rails/rails-iodine.dockerfile +++ b/frameworks/Ruby/rails/rails-iodine.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends redis-server diff --git a/frameworks/Ruby/rails/rails-mysql.dockerfile b/frameworks/Ruby/rails/rails-mysql.dockerfile index 1009954ca6e..998294d1ec6 100644 --- a/frameworks/Ruby/rails/rails-mysql.dockerfile +++ b/frameworks/Ruby/rails/rails-mysql.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends redis-server diff --git a/frameworks/Ruby/rails/rails-pitchfork.dockerfile b/frameworks/Ruby/rails/rails-pitchfork.dockerfile index 190f30a4926..53f8c66b4cc 100644 --- a/frameworks/Ruby/rails/rails-pitchfork.dockerfile +++ b/frameworks/Ruby/rails/rails-pitchfork.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends redis-server diff --git a/frameworks/Ruby/rails/rails.dockerfile b/frameworks/Ruby/rails/rails.dockerfile index a1095428571..2e901b62062 100644 --- a/frameworks/Ruby/rails/rails.dockerfile +++ b/frameworks/Ruby/rails/rails.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends redis-server diff --git a/frameworks/Ruby/roda-sequel/Gemfile.lock b/frameworks/Ruby/roda-sequel/Gemfile.lock index cb7fb373054..37c5ce6a06e 100644 --- a/frameworks/Ruby/roda-sequel/Gemfile.lock +++ b/frameworks/Ruby/roda-sequel/Gemfile.lock @@ -6,7 +6,7 @@ GEM concurrent-ruby (1.3.5) erubi (1.13.1) iodine (0.7.58) - json (2.13.2) + json (2.16.0) nio4r (2.7.4) pg (1.6.2) pg (1.6.2-x86_64-darwin) diff --git a/frameworks/Ruby/roda-sequel/benchmark_config.json b/frameworks/Ruby/roda-sequel/benchmark_config.json index f51112ed0f9..c028cc7008c 100644 --- a/frameworks/Ruby/roda-sequel/benchmark_config.json +++ b/frameworks/Ruby/roda-sequel/benchmark_config.json @@ -20,7 +20,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "roda-sequel-puma-mri", + "display_name": "roda-sequel [puma, mysql]", "versus": "rack-sequel-puma-mri", "notes": "" }, @@ -40,7 +40,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "roda-sequel-postgres-puma-mri", + "display_name": "roda-sequel [puma, postgres]", "versus": "rack-sequel-postgres-puma-mri", "notes": "" }, @@ -62,7 +62,7 @@ "webserver": "Iodine", "os": "Linux", "database_os": "Linux", - "display_name": "roda-sequel-postgres-iodine-mri", + "display_name": "roda-sequel [iodine, postgres]", "versus": "rack-sequel-postgres-iodine-mri", "notes": "" } diff --git a/frameworks/Ruby/roda-sequel/boot.rb b/frameworks/Ruby/roda-sequel/boot.rb index 0878b21e9d3..6d2d2e44e9f 100644 --- a/frameworks/Ruby/roda-sequel/boot.rb +++ b/frameworks/Ruby/roda-sequel/boot.rb @@ -34,9 +34,8 @@ def connect(dbtype) end # Determine threading/thread pool size and timeout - if defined?(Puma) && - (threads = Puma.cli_config.options.fetch(:max_threads)) > 1 - opts[:max_connections] = threads + if defined?(Puma) + opts[:max_connections] = ENV.fetch('MAX_THREADS') opts[:pool_timeout] = 10 else opts[:max_connections] = 512 diff --git a/frameworks/Ruby/roda-sequel/config/puma.rb b/frameworks/Ruby/roda-sequel/config/puma.rb new file mode 100644 index 00000000000..907837b4892 --- /dev/null +++ b/frameworks/Ruby/roda-sequel/config/puma.rb @@ -0,0 +1,3 @@ +before_fork do + Sequel::DATABASES.each(&:disconnect) +end diff --git a/frameworks/Ruby/roda-sequel/roda-sequel-postgres-iodine-mri.dockerfile b/frameworks/Ruby/roda-sequel/roda-sequel-postgres-iodine-mri.dockerfile index 2ab0b2de6cc..db7fbc995f1 100644 --- a/frameworks/Ruby/roda-sequel/roda-sequel-postgres-iodine-mri.dockerfile +++ b/frameworks/Ruby/roda-sequel/roda-sequel-postgres-iodine-mri.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ADD ./ /roda-sequel WORKDIR /roda-sequel diff --git a/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile b/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile index 46cff7f1b39..f64942e8994 100644 --- a/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile +++ b/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ADD ./ /roda-sequel WORKDIR /roda-sequel @@ -17,7 +17,9 @@ RUN bundle install --jobs=8 ENV RACK_ENV=production ENV DBTYPE=postgresql +ENV MAX_THREADS=5 ENV WEB_CONCURRENCY=auto + EXPOSE 8080 -CMD bundle exec puma -C config/mri_puma.rb -b tcp://0.0.0.0:8080 +CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 diff --git a/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile b/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile index 1506324b59c..d72f87057db 100644 --- a/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile +++ b/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile @@ -1,10 +1,9 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ADD ./ /roda-sequel WORKDIR /roda-sequel ENV RUBY_YJIT_ENABLE=1 -ENV RUBY_THREAD_TIMESLICE=10 # Use Jemalloc RUN apt-get update && \ @@ -19,6 +18,8 @@ ENV RACK_ENV=production ENV DBTYPE=mysql ENV WEB_CONCURRENCY=auto +ENV MAX_THREADS=5 + EXPOSE 8080 -CMD bundle exec puma -C config/mri_puma.rb -b tcp://0.0.0.0:8080 +CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 diff --git a/frameworks/Ruby/sinatra-sequel/Gemfile.lock b/frameworks/Ruby/sinatra-sequel/Gemfile.lock index e9d49e6d9b1..5d1d43e6228 100644 --- a/frameworks/Ruby/sinatra-sequel/Gemfile.lock +++ b/frameworks/Ruby/sinatra-sequel/Gemfile.lock @@ -1,13 +1,13 @@ GEM remote: https://rubygems.org/ specs: - base64 (0.2.0) + base64 (0.3.0) bigdecimal (3.3.1) concurrent-ruby (1.3.5) iodine (0.7.58) - json (2.13.2) - logger (1.6.6) - mustermann (3.0.3) + json (2.16.0) + logger (1.7.0) + mustermann (3.0.4) ruby2_keywords (~> 0.0.1) nio4r (2.7.4) pg (1.6.2) @@ -15,12 +15,12 @@ GEM pg (1.6.2-x86_64-linux) puma (7.1.0) nio4r (~> 2.0) - rack (3.2.0) - rack-protection (4.1.1) + rack (3.2.4) + rack-protection (4.2.1) base64 (>= 0.1.0) logger (>= 1.6.0) rack (>= 3.0.0, < 4) - rack-session (2.1.0) + rack-session (2.1.1) base64 (>= 0.1.0) rack (>= 3.0.0) ruby2_keywords (0.0.5) @@ -29,14 +29,14 @@ GEM sequel_pg (1.17.2) pg (>= 0.18.0, != 1.2.0) sequel (>= 4.38.0) - sinatra (4.1.1) + sinatra (4.2.1) logger (>= 1.6.0) mustermann (~> 3.0) rack (>= 3.0.0, < 4) - rack-protection (= 4.1.1) + rack-protection (= 4.2.1) rack-session (>= 2.0.0, < 3) tilt (~> 2.0) - tilt (2.6.0) + tilt (2.6.1) trilogy (2.9.0) PLATFORMS diff --git a/frameworks/Ruby/sinatra-sequel/benchmark_config.json b/frameworks/Ruby/sinatra-sequel/benchmark_config.json index 8b09aafbd54..008e63a8148 100644 --- a/frameworks/Ruby/sinatra-sequel/benchmark_config.json +++ b/frameworks/Ruby/sinatra-sequel/benchmark_config.json @@ -18,7 +18,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "sinatra-sequel-puma-mri", + "display_name": "sinatra-sequel [puma, mysql]", "versus": "rack-sequel-puma-mri", "notes": "" }, @@ -38,7 +38,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "sinatra-sequel-postgres-puma-mri", + "display_name": "sinatra-sequel [puma, postgres]", "versus": "rack-sequel-postgres-puma-mri", "notes": "" }, @@ -58,7 +58,7 @@ "webserver": "Iodine", "os": "Linux", "database_os": "Linux", - "display_name": "sinatra-sequel-postgres-iodine-mri", + "display_name": "sinatra-sequel [iodine, postgres]", "versus": "rack-sequel-postgres-iodine-mri", "notes": "" } diff --git a/frameworks/Ruby/sinatra-sequel/boot.rb b/frameworks/Ruby/sinatra-sequel/boot.rb index ca44bdc08df..58cdb0c25cb 100644 --- a/frameworks/Ruby/sinatra-sequel/boot.rb +++ b/frameworks/Ruby/sinatra-sequel/boot.rb @@ -27,8 +27,8 @@ def connect(dbtype) end # Determine threading/thread pool size and timeout - if defined?(Puma) && (threads = Puma.cli_config.options.fetch(:max_threads)) > 1 - opts[:max_connections] = threads + if defined?(Puma) + opts[:max_connections] = ENV.fetch('MAX_THREADS') opts[:pool_timeout] = 10 else opts[:max_connections] = 512 diff --git a/frameworks/Ruby/sinatra-sequel/config/mri_puma.rb b/frameworks/Ruby/sinatra-sequel/config/mri_puma.rb deleted file mode 100644 index 794c18f0c08..00000000000 --- a/frameworks/Ruby/sinatra-sequel/config/mri_puma.rb +++ /dev/null @@ -1,10 +0,0 @@ -require_relative 'auto_tune' - -# FWBM only... use the puma_auto_tune gem in production! -_, num_threads = auto_tune - -threads num_threads - -before_fork do - Sequel::DATABASES.each(&:disconnect) -end diff --git a/frameworks/Ruby/sinatra-sequel/config/puma.rb b/frameworks/Ruby/sinatra-sequel/config/puma.rb new file mode 100644 index 00000000000..907837b4892 --- /dev/null +++ b/frameworks/Ruby/sinatra-sequel/config/puma.rb @@ -0,0 +1,3 @@ +before_fork do + Sequel::DATABASES.each(&:disconnect) +end diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-iodine-mri.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-iodine-mri.dockerfile index 83d1de64132..98e42167f64 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-iodine-mri.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-iodine-mri.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile index afbbc915d22..7cfbf8d9cb6 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 @@ -13,10 +13,12 @@ WORKDIR /sinatra-sequel ENV BUNDLE_WITH=postgresql:puma RUN bundle install --jobs=4 --gemfile=/sinatra-sequel/Gemfile -ENV WEB_CONCURRENCY=auto ENV APP_ENV=production ENV DBTYPE=postgresql +ENV WEB_CONCURRENCY=auto +ENV MAX_THREADS=5 + EXPOSE 8080 -CMD bundle exec puma -C config/mri_puma.rb -b tcp://0.0.0.0:8080 +CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile index 7f622501ddf..bc8a7a8b871 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 @@ -13,10 +13,12 @@ WORKDIR /sinatra-sequel ENV BUNDLE_WITH=mysql:puma RUN bundle install --jobs=4 --gemfile=/sinatra-sequel/Gemfile -ENV WEB_CONCURRENCY=auto ENV APP_ENV=production ENV DBTYPE=mysql +ENV WEB_CONCURRENCY=auto +ENV MAX_THREADS=5 + EXPOSE 8080 -CMD bundle exec puma -C config/mri_puma.rb -b tcp://0.0.0.0:8080 +CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 diff --git a/frameworks/Ruby/sinatra/Gemfile b/frameworks/Ruby/sinatra/Gemfile index 6b0a0c45fd8..c02e8ff075b 100644 --- a/frameworks/Ruby/sinatra/Gemfile +++ b/frameworks/Ruby/sinatra/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' -gem 'activerecord', '~> 8.0', require: 'active_record' +gem 'activerecord', '~> 8.1.0', require: 'active_record' gem 'json', '~> 2.8' gem 'sinatra', '~> 4.2', require: 'sinatra/base' diff --git a/frameworks/Ruby/sinatra/Gemfile.lock b/frameworks/Ruby/sinatra/Gemfile.lock index a9909fd6604..c4b7de85016 100644 --- a/frameworks/Ruby/sinatra/Gemfile.lock +++ b/frameworks/Ruby/sinatra/Gemfile.lock @@ -1,27 +1,26 @@ GEM remote: https://rubygems.org/ specs: - activemodel (8.0.2.1) - activesupport (= 8.0.2.1) - activerecord (8.0.2.1) - activemodel (= 8.0.2.1) - activesupport (= 8.0.2.1) + activemodel (8.1.1) + activesupport (= 8.1.1) + activerecord (8.1.1) + activemodel (= 8.1.1) + activesupport (= 8.1.1) timeout (>= 0.4.0) - activesupport (8.0.2.1) + activesupport (8.1.1) base64 - benchmark (>= 0.3) bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + json logger (>= 1.4.2) minitest (>= 5.1) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) uri (>= 0.13.1) base64 (0.3.0) - benchmark (0.4.1) bigdecimal (3.2.2) concurrent-ruby (1.3.5) connection_pool (2.5.3) @@ -29,7 +28,7 @@ GEM i18n (1.14.7) concurrent-ruby (~> 1.0) iodine (0.7.58) - json (2.13.2) + json (2.16.0) logger (1.7.0) minitest (5.25.5) mustermann (3.0.4) @@ -70,7 +69,7 @@ PLATFORMS x86_64-linux DEPENDENCIES - activerecord (~> 8.0) + activerecord (~> 8.1.0) iodine (~> 0.7) json (~> 2.8) pg (~> 1.5) diff --git a/frameworks/Ruby/sinatra/benchmark_config.json b/frameworks/Ruby/sinatra/benchmark_config.json index 0d14929dd67..7bdbb62e853 100644 --- a/frameworks/Ruby/sinatra/benchmark_config.json +++ b/frameworks/Ruby/sinatra/benchmark_config.json @@ -20,7 +20,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "sinatra-puma-mri", + "display_name": "sinatra [puma, mysql]", "versus": "rack-puma-mri", "notes": "" }, @@ -40,7 +40,7 @@ "webserver": "Puma", "os": "Linux", "database_os": "Linux", - "display_name": "sinatra-postgres-puma-mri", + "display_name": "sinatra [puma, postgres]", "versus": "rack-postgres-puma-mri", "notes": "" }, @@ -62,7 +62,7 @@ "webserver": "Iodine", "os": "Linux", "database_os": "Linux", - "display_name": "sinatra-postgres-iodine-mri", + "display_name": "sinatra [iodine, postgres]", "versus": "rack-postgres-iodine-mri", "notes": "" } diff --git a/frameworks/Ruby/sinatra/boot.rb b/frameworks/Ruby/sinatra/boot.rb index e27fe4e928c..33843258016 100644 --- a/frameworks/Ruby/sinatra/boot.rb +++ b/frameworks/Ruby/sinatra/boot.rb @@ -30,10 +30,9 @@ def connect(dbtype) opts[:adapter] = 'postgresql' end - # Determine threading/thread pool size and timeout - if defined?(Puma) && (threads = Puma.cli_config.options.fetch(:max_threads)) > 1 - opts[:pool] = threads + if defined?(Puma) + opts[:pool] = ENV.fetch('MAX_THREADS') opts[:checkout_timeout] = 10 else opts[:pool] = 512 diff --git a/frameworks/Ruby/sinatra/config/mri_puma.rb b/frameworks/Ruby/sinatra/config/mri_puma.rb deleted file mode 100644 index 95b855bafd3..00000000000 --- a/frameworks/Ruby/sinatra/config/mri_puma.rb +++ /dev/null @@ -1,7 +0,0 @@ -require_relative 'auto_tune' - -# FWBM only... use the puma_auto_tune gem in production! -num_workers, num_threads = auto_tune - -workers num_workers -threads num_threads, num_threads diff --git a/frameworks/Ruby/sinatra/sinatra-postgres-iodine-mri.dockerfile b/frameworks/Ruby/sinatra/sinatra-postgres-iodine-mri.dockerfile index a6a29633958..7dbd84dfeca 100644 --- a/frameworks/Ruby/sinatra/sinatra-postgres-iodine-mri.dockerfile +++ b/frameworks/Ruby/sinatra/sinatra-postgres-iodine-mri.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 diff --git a/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile b/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile index 5d16f620330..61cb25c2551 100644 --- a/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile +++ b/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 @@ -13,10 +13,12 @@ WORKDIR /sinatra ENV BUNDLE_WITH=postgresql:puma RUN bundle install --jobs=4 --gemfile=/sinatra/Gemfile -ENV WEB_CONCURRENCY=auto ENV APP_ENV=production ENV DBTYPE=postgresql +ENV WEB_CONCURRENCY=auto +ENV MAX_THREADS=5 + EXPOSE 8080 -CMD bundle exec puma -C config/mri_puma.rb -b tcp://0.0.0.0:8080 +CMD bundle exec puma -b tcp://0.0.0.0:8080 diff --git a/frameworks/Ruby/sinatra/sinatra.dockerfile b/frameworks/Ruby/sinatra/sinatra.dockerfile index 252f6743a01..f6082c07919 100644 --- a/frameworks/Ruby/sinatra/sinatra.dockerfile +++ b/frameworks/Ruby/sinatra/sinatra.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.5-rc +FROM ruby:4.0-rc ENV RUBY_YJIT_ENABLE=1 @@ -17,6 +17,8 @@ ENV APP_ENV=production ENV DBTYPE=mysql ENV WEB_CONCURRENCY=auto +ENV MAX_THREADS=5 + EXPOSE 8080 -CMD bundle exec puma -C config/mri_puma.rb -b tcp://0.0.0.0:8080 +CMD bundle exec puma -b tcp://0.0.0.0:8080 diff --git a/frameworks/Rust/axum/Cargo.lock b/frameworks/Rust/axum/Cargo.lock index d19c9254f3f..ae79df4e8d4 100644 --- a/frameworks/Rust/axum/Cargo.lock +++ b/frameworks/Rust/axum/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -24,7 +15,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", @@ -32,9 +23,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -45,21 +36,6 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - [[package]] name = "annotate-snippets" version = "0.9.2" @@ -72,13 +48,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -104,9 +80,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" +checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" dependencies = [ "axum-core", "bytes", @@ -123,8 +99,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "serde_json", "serde_path_to_error", "serde_urlencoded", @@ -137,9 +112,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" dependencies = [ "bytes", "futures-core", @@ -148,7 +123,6 @@ dependencies = [ "http-body-util", "mime", "pin-project-lite", - "rustversion", "sync_wrapper", "tower-layer", "tower-service", @@ -178,7 +152,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "simd-json", - "socket2", + "socket2 0.6.1", "sqlx", "tokio", "tokio-pg-mapper", @@ -189,33 +163,6 @@ dependencies = [ "yarte", ] -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -230,17 +177,11 @@ checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -271,12 +212,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969a9ba84b0ff843813e7249eed1678d9b6607ce5a3b8f0a47af3fcf7978e6e" dependencies = [ "ahash", - "base64 0.22.1", + "base64", "bitvec", "getrandom 0.2.16", - "getrandom 0.3.3", + "getrandom 0.3.4", "hex", - "indexmap 2.10.0", + "indexmap", "js-sys", "once_cell", "rand 0.9.2", @@ -301,16 +242,17 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "cc" -version = "1.2.30" +version = "1.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" +checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -318,22 +260,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" - -[[package]] -name = "chrono" -version = "0.4.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "num-traits", - "serde", - "windows-link", -] +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "concurrent-queue" @@ -376,12 +305,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - [[package]] name = "cpufeatures" version = "0.2.17" @@ -393,9 +316,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" dependencies = [ "crc-catalog", ] @@ -415,6 +338,30 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.12" @@ -438,9 +385,9 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -448,9 +395,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ "darling_core", "darling_macro", @@ -458,27 +405,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "darling_macro" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -489,11 +436,12 @@ checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "deadpool" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ed5957ff93768adf7a65ab167a17835c3d2c3c50d084fe305174c112f468e2f" +checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b" dependencies = [ "deadpool-runtime", + "lazy_static", "num_cpus", "serde", "tokio", @@ -536,12 +484,11 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", - "serde", ] [[package]] @@ -552,18 +499,18 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "derive-where" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "510c292c8cf384b1a340b816a9a6cf2599eb8f566a44949024af88418000c50b" +checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -576,7 +523,28 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.104", + "syn 2.0.111", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", + "unicode-xid", ] [[package]] @@ -599,7 +567,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -620,12 +588,6 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" -[[package]] -name = "dyn-clone" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" - [[package]] name = "either" version = "1.15.0" @@ -644,7 +606,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -666,9 +628,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.4.0" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -681,11 +643,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "flate2" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -723,11 +691,17 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -805,7 +779,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -857,35 +831,29 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", "wasm-bindgen", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "h2" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", @@ -893,7 +861,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.10.0", + "indexmap", "slab", "tokio", "tokio-util", @@ -902,29 +870,34 @@ dependencies = [ [[package]] name = "halfbrown" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2c385c6df70fd180bbb673d93039dbd2cd34e41d782600bdf6e1ca7bce39aa" +checksum = "0c7ed2f2edad8a14c8186b847909a41fbb9c3eafa44f88bd891114ed5019da09" dependencies = [ - "hashbrown 0.15.4", + "hashbrown 0.16.1", "serde", ] [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.1.5", +] [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.2.0", ] [[package]] @@ -933,7 +906,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.4", + "hashbrown 0.15.5", ] [[package]] @@ -956,9 +929,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hickory-proto" -version = "0.24.4" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248" +checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" dependencies = [ "async-trait", "cfg-if", @@ -970,8 +943,9 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.8.5", - "thiserror 1.0.69", + "rand 0.9.2", + "ring", + "thiserror", "tinyvec", "tokio", "tracing", @@ -980,21 +954,21 @@ dependencies = [ [[package]] name = "hickory-resolver" -version = "0.24.4" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" +checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" dependencies = [ "cfg-if", "futures-util", "hickory-proto", "ipconfig", - "lru-cache", + "moka", "once_cell", "parking_lot", - "rand 0.8.5", + "rand 0.9.2", "resolv-conf", "smallvec", - "thiserror 1.0.69", + "thiserror", "tokio", "tracing", ] @@ -1019,21 +993,20 @@ dependencies = [ [[package]] name = "home" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -1074,13 +1047,14 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.6.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "h2", "http", "http-body", @@ -1088,15 +1062,16 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", ] [[package]] name = "hyper-util" -version = "0.1.15" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df" +checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56" dependencies = [ "bytes", "futures-core", @@ -1108,35 +1083,11 @@ dependencies = [ "tower-service", ] -[[package]] -name = "iana-time-zone" -version = "0.1.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -1147,9 +1098,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -1160,11 +1111,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1175,42 +1125,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1226,9 +1172,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -1247,35 +1193,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", - "hashbrown 0.15.4", - "serde", -] - -[[package]] -name = "io-uring" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" -dependencies = [ - "bitflags 2.9.1", - "cfg-if", - "libc", + "hashbrown 0.16.1", ] [[package]] @@ -1284,7 +1207,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2", + "socket2 0.5.10", "widestring", "windows-sys 0.48.0", "winreg", @@ -1304,19 +1227,19 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -1333,9 +1256,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.174" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libm" @@ -1345,14 +1268,25 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libmimalloc-sys" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf88cd67e9de251c1781dbe2f641a1a3ad66eaae831b8a2c38fbdc5ddae16d4d" +checksum = "667f4fec20f29dfc6bc7357c582d91796c169ad7e2fce709468aefeb2c099870" dependencies = [ "cc", "libc", ] +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] + [[package]] name = "libsqlite3-sys" version = "0.30.1" @@ -1363,42 +1297,26 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "lru-cache" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -dependencies = [ - "linked-hash-map", -] +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "macro_magic" @@ -1409,7 +1327,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -1423,7 +1341,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -1434,7 +1352,7 @@ checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -1445,7 +1363,7 @@ checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -1466,15 +1384,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "mimalloc" -version = "0.1.47" +version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1791cbe101e95af5764f06f20f6760521f7158f69dbf9d6baf941ee1bf6bc40" +checksum = "e1ee66a4b64c74f4ef288bcbb9192ad9c3feaad75193129ac8509af543894fd8" dependencies = [ "libmimalloc-sys", ] @@ -1492,35 +1410,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "moka" +version = "0.12.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "equivalent", + "parking_lot", + "portable-atomic", + "rustc_version", + "smallvec", + "tagptr", + "uuid", +] + +[[package]] +name = "mongocrypt" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da0cd419a51a5fb44819e290fbdb0665a54f21dead8923446a799c7f4d26ad9" +dependencies = [ + "bson", + "mongocrypt-sys", + "once_cell", + "serde", ] +[[package]] +name = "mongocrypt-sys" +version = "0.1.5+1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224484c5d09285a7b8cb0a0c117e847ebd14cb6e4470ecf68cdb89c503b0edb9" + [[package]] name = "mongodb" -version = "3.2.4" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f8c69f13acf07eae386a2974f48ffd9187ea2aba8defbea9aa34e7e272c5f3" +checksum = "12f5c20217413bed97c613714e6d6dfe39ef59dd79a68999f1043b0566192975" dependencies = [ - "async-trait", - "base64 0.13.1", - "bitflags 1.3.2", + "base64", + "bitflags", "bson", - "chrono", "derive-where", - "derive_more", + "derive_more 2.0.1", "flate2", "futures-core", - "futures-executor", "futures-io", "futures-util", "hex", @@ -1529,53 +1481,52 @@ dependencies = [ "hmac", "macro_magic", "md-5", + "mongocrypt", "mongodb-internal-macros", - "once_cell", "pbkdf2", "percent-encoding", - "rand 0.8.5", + "rand 0.9.2", "rustc_version_runtime", - "rustls 0.21.12", - "rustls-pemfile", + "rustls", + "rustversion", "serde", "serde_bytes", "serde_with", "sha1", "sha2", "snap", - "socket2", + "socket2 0.6.1", "stringprep", "strsim", "take_mut", - "thiserror 1.0.69", + "thiserror", "tokio", "tokio-rustls", "tokio-util", "typed-builder", "uuid", - "webpki-roots 0.25.4", + "webpki-roots 1.0.4", "zstd", ] [[package]] name = "mongodb-internal-macros" -version = "3.2.4" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9202de265a3a8bbb43f9fe56db27c93137d4f9fb04c093f47e9c7de0c61ac7d" +checksum = "20033442aa13664e70bc9f8be1bacabebf6a31b6d4bb5608ceb99c4ec96e9951" dependencies = [ "macro_magic", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "num-bigint-dig" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" dependencies = [ - "byteorder", "lazy_static", "libm", "num-integer", @@ -1632,20 +1583,15 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +dependencies = [ + "critical-section", + "portable-atomic", +] [[package]] name = "parking" @@ -1655,9 +1601,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1665,22 +1611,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "pbkdf2" -version = "0.11.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest", ] @@ -1696,24 +1642,25 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "phf" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ "phf_shared", + "serde", ] [[package]] name = "phf_shared" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" dependencies = [ "siphasher", ] @@ -1757,13 +1704,19 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + [[package]] name = "postgres-protocol" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ff0abab4a9b844b93ef7b81f1efc0a366062aaef2cd702c76256b5dc075c54" +checksum = "fbef655056b916eb868048276cfd5d6a7dea4f81560dfd047f97c8c6fe3fcfd4" dependencies = [ - "base64 0.22.1", + "base64", "byteorder", "bytes", "fallible-iterator", @@ -1777,9 +1730,9 @@ dependencies = [ [[package]] name = "postgres-types" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613283563cd90e1dfc3518d548caee47e0e725455ed619881f5cf21f36de4b48" +checksum = "ef4605b7c057056dd35baeb6ac0c0338e4975b1f2bef0f65da953285eb007095" dependencies = [ "bytes", "fallible-iterator", @@ -1788,9 +1741,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -1822,30 +1775,30 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "quick_cache" -version = "0.6.14" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b450dad8382b1b95061d5ca1eb792081fb082adf48c678791fe917509596d5f" +checksum = "7ada44a88ef953a3294f6eb55d2007ba44646015e18613d2f213016379203ef3" dependencies = [ "ahash", "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.16.1", "parking_lot", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -1918,43 +1871,43 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] name = "redox_syscall" -version = "0.5.14" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3a5d9f0aba1dbcec1cc47f0ff94a4b778fe55bca98a6dfa92e4e094e57b1c4" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.1", + "bitflags", ] [[package]] name = "ref-cast" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -1964,9 +1917,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -1975,15 +1928,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "resolv-conf" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" [[package]] name = "ring" @@ -2001,9 +1954,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88" dependencies = [ "const-oid", "digest", @@ -2019,12 +1972,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustc-demangle" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" - [[package]] name = "rustc_version" version = "0.4.1" @@ -2046,63 +1993,33 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.12" +version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ "log", - "ring", - "rustls-webpki 0.101.7", - "sct", -] - -[[package]] -name = "rustls" -version = "0.23.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1" -dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.4", + "rustls-webpki", "subtle", "zeroize", ] -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.4" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "ring", "rustls-pki-types", @@ -2111,9 +2028,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -2121,102 +2038,81 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "schemars" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] - -[[package]] -name = "schemars" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] - [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.17" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "serde_json" -version = "1.0.141" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ - "indexmap 2.10.0", + "indexmap", "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] name = "serde_path_to_error" -version = "0.1.17" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ "itoa", "serde", + "serde_core", ] [[package]] @@ -2233,34 +2129,24 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.14.0" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" +checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.10.0", - "schemars 0.9.0", - "schemars 1.0.4", - "serde", - "serde_derive", - "serde_json", + "serde_core", "serde_with_macros", - "time", ] [[package]] name = "serde_with_macros" -version = "3.14.0" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" +checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -2293,9 +2179,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.5" +version = "1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" dependencies = [ "libc", ] @@ -2310,13 +2196,18 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "simd-json" -version = "0.15.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c962f626b54771990066e5435ec8331d1462576cd2d1e62f24076ae014f92112" +checksum = "4255126f310d2ba20048db6321c81ab376f6a6735608bf11f0785c41f01f64e3" dependencies = [ - "getrandom 0.3.3", "halfbrown", "ref-cast", "serde", @@ -2339,9 +2230,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" @@ -2368,6 +2259,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "spin" version = "0.9.8" @@ -2406,7 +2307,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "crc", "crossbeam-queue", @@ -2416,19 +2317,19 @@ dependencies = [ "futures-intrusive", "futures-io", "futures-util", - "hashbrown 0.15.4", + "hashbrown 0.15.5", "hashlink", - "indexmap 2.10.0", + "indexmap", "log", "memchr", "once_cell", "percent-encoding", - "rustls 0.23.29", + "rustls", "serde", "serde_json", "sha2", "smallvec", - "thiserror 2.0.12", + "thiserror", "tokio", "tokio-stream", "tracing", @@ -2446,7 +2347,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -2469,7 +2370,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.104", + "syn 2.0.111", "tokio", "url", ] @@ -2481,8 +2382,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", - "base64 0.22.1", - "bitflags 2.9.1", + "base64", + "bitflags", "byteorder", "bytes", "crc", @@ -2511,7 +2412,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.12", + "thiserror", "tracing", "whoami", ] @@ -2523,8 +2424,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", - "base64 0.22.1", - "bitflags 2.9.1", + "base64", + "bitflags", "byteorder", "crc", "dotenvy", @@ -2548,7 +2449,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.12", + "thiserror", "tracing", "whoami", ] @@ -2572,16 +2473,16 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", - "thiserror 2.0.12", + "thiserror", "tracing", "url", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stringprep" @@ -2619,9 +2520,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.104" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", @@ -2642,9 +2543,15 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "take_mut" version = "0.2.2" @@ -2659,49 +2566,29 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.12", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", + "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "time" -version = "0.3.41" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", "itoa", @@ -2714,15 +2601,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -2739,9 +2626,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -2749,9 +2636,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -2764,33 +2651,30 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.46.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -2815,9 +2699,9 @@ dependencies = [ [[package]] name = "tokio-postgres" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c95d533c83082bb6490e0189acaa0bbeef9084e60471b696ca6988cd0541fb0" +checksum = "2b40d66d9b2cfe04b628173409368e58247e8eddbbd3b0e6c6ba1d09f20f6c9e" dependencies = [ "async-trait", "byteorder", @@ -2833,7 +2717,7 @@ dependencies = [ "postgres-protocol", "postgres-types", "rand 0.9.2", - "socket2", + "socket2 0.6.1", "tokio", "tokio-util", "whoami", @@ -2841,11 +2725,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.21.12", + "rustls", "tokio", ] @@ -2862,9 +2746,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.15" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -2900,11 +2784,11 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456" dependencies = [ - "bitflags 2.9.1", + "bitflags", "bytes", "http", "pin-project-lite", @@ -2926,9 +2810,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" dependencies = [ "log", "pin-project-lite", @@ -2938,40 +2822,49 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" dependencies = [ "once_cell", ] [[package]] name = "typed-builder" -version = "0.10.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c" +checksum = "398a3a3c918c96de527dc11e6e846cd549d4508030b8a33e1da12789c856b81a" +dependencies = [ + "typed-builder-macro", +] + +[[package]] +name = "typed-builder-macro" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e48cea23f68d1f78eb7bc092881b6bb88d3d6b5b7e6234f6f9c911da1ffb221" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.111", ] [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-bidi" @@ -2981,24 +2874,24 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-width" @@ -3020,13 +2913,14 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -3037,11 +2931,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", "serde", "wasm-bindgen", @@ -3065,9 +2959,9 @@ checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" [[package]] name = "value-trait" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0508fce11ad19e0aab49ce20b6bec7f8f82902ded31df1c9fc61b90f0eb396b8" +checksum = "8e80f0c733af0720a501b3905d22e2f97662d8eacfe082a75ed7ffb5ab08cb59" dependencies = [ "float-cmp", "halfbrown", @@ -3094,12 +2988,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] @@ -3110,35 +3004,22 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.104", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3146,76 +3027,70 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.104", - "wasm-bindgen-backend", + "syn 2.0.111", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "webpki-roots" version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.2", + "webpki-roots 1.0.4", ] [[package]] name = "webpki-roots" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" dependencies = [ "rustls-pki-types", ] [[package]] name = "whoami" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" dependencies = [ - "redox_syscall", + "libredox", "wasite", "web-sys", ] [[package]] name = "widestring" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" [[package]] name = "winapi" @@ -3239,64 +3114,11 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - -[[package]] -name = "windows-interface" -version = "0.59.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - [[package]] name = "windows-link" -version = "0.1.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" @@ -3318,11 +3140,20 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.59.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", ] [[package]] @@ -3349,13 +3180,30 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -3368,6 +3216,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -3380,6 +3234,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -3392,12 +3252,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -3410,6 +3282,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -3422,6 +3300,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -3434,6 +3318,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -3446,6 +3336,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winreg" version = "0.50.0" @@ -3457,19 +3353,16 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "wyz" @@ -3548,7 +3441,7 @@ version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee42d2f704a3b1d8bc111d47a705d1302a0943d85e4c230f4e8300ee0dde4a6" dependencies = [ - "derive_more", + "derive_more 0.99.20", "proc-macro2", "quote", "syn 1.0.109", @@ -3565,7 +3458,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "538f72049cf7104e12d5c444048d112cb8fc788a31308afd912442a381ba860c" dependencies = [ "annotate-snippets", - "derive_more", + "derive_more 0.99.20", "proc-macro2", "quote", "serde", @@ -3576,11 +3469,10 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -3588,34 +3480,34 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -3635,21 +3527,21 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -3658,9 +3550,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -3669,13 +3561,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -3699,9 +3591,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.15+zstd.1.5.7" +version = "2.0.16+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ "cc", "pkg-config", diff --git a/frameworks/Rust/axum/Cargo.toml b/frameworks/Rust/axum/Cargo.toml index be0bf32250a..b17c3ea4209 100644 --- a/frameworks/Rust/axum/Cargo.toml +++ b/frameworks/Rust/axum/Cargo.toml @@ -39,7 +39,7 @@ simd-json = [ ] [dependencies] -axum = { version = "0.8.4", default-features = false, features = [ +axum = { version = "0.8.7", default-features = false, features = [ "json", "query", "http1", @@ -66,20 +66,20 @@ sqlx = { version = "0.8.6", features = [ "runtime-tokio", "tls-rustls", ] } -tokio = { version = "1.46.1", features = ["full"] } +tokio = { version = "1.48.0", features = ["full"] } tokio-pg-mapper = { version = "0.2.0" } tokio-pg-mapper-derive = { version = "0.2.0" } tokio-postgres = { version = "0.7.13" } tower = { version = "0.5.2", features = ["util"] } -tower-http = { version = "0.6.6", features = ["set-header"] } +tower-http = { version = "0.6.7", features = ["set-header"] } yarte = "0.15.7" -simd-json = { version = "0.15.1", optional = true } +simd-json = { version = "0.17.0", optional = true } axum-core = { version = "0.5.2", optional = true } mime = { version = "0.3.17", optional = true } bytes = { version = "1.10.1", optional = true } serde_path_to_error = { version = "0.1.17", optional = true } -socket2 = "0.5.10" -hyper = { version = "1.6", features = ["server", "http1"] } +socket2 = "0.6.1" +hyper = { version = "1.8.1", features = ["server", "http1"] } hyper-util = { version = "0.1", features = ["tokio", "server-auto", "http1"] } quick_cache = "0.6.14" mimalloc = "0.1.47" diff --git a/frameworks/Rust/axum/axum.dockerfile b/frameworks/Rust/axum/axum.dockerfile index 35167203a19..8ac2f9d687c 100644 --- a/frameworks/Rust/axum/axum.dockerfile +++ b/frameworks/Rust/axum/axum.dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/rust:1.88-slim-bookworm AS builder +FROM docker.io/rust:1.91-slim-bookworm AS builder RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config libssl-dev \ diff --git a/frameworks/Rust/axum/src/server.rs b/frameworks/Rust/axum/src/server.rs index 52705143dba..b1a782cf182 100644 --- a/frameworks/Rust/axum/src/server.rs +++ b/frameworks/Rust/axum/src/server.rs @@ -28,7 +28,7 @@ fn set_socket_options(addr: SocketAddr) -> io::Result { socket.set_reuse_port(true)?; socket.set_reuse_address(true)?; socket.set_nonblocking(true)?; - socket.set_nodelay(true)?; + socket.set_tcp_nodelay(true)?; socket.bind(&addr.into())?; socket.listen(4096)?; diff --git a/frameworks/Rust/gotham/benchmark_config.json b/frameworks/Rust/gotham/benchmark_config.json index 2ee7db2a39f..8813ea15eed 100755 --- a/frameworks/Rust/gotham/benchmark_config.json +++ b/frameworks/Rust/gotham/benchmark_config.json @@ -19,6 +19,7 @@ "database_os": "Linux", "display_name": "Gotham", "notes": "", + "tags": ["broken"], "versus": "None" } } diff --git a/frameworks/Rust/hyper/hyper.dockerfile b/frameworks/Rust/hyper/hyper.dockerfile index b2f6b8cb6b3..4816011104f 100644 --- a/frameworks/Rust/hyper/hyper.dockerfile +++ b/frameworks/Rust/hyper/hyper.dockerfile @@ -1,8 +1,17 @@ FROM rust:1.85 AS hyper WORKDIR /src -COPY . . -RUN RUSTFLAGS="-C target-cpu=native" cargo install --path . --locked +ENV RUSTFLAGS="-C target-cpu=native" + +# Cache dependency builds (requires passing --force-rm False to tfb command) +COPY Cargo.toml Cargo.lock /src/ +RUN mkdir src \ + && echo "fn main() {println!(\"if you see this, the build broke\")}" > src/main.rs \ + && cargo build --release \ + && rm -rfv src/ target/release/hyper-techempower* target/release/deps/hyper_techempower* + +COPY . /src/ +RUN cargo install --path . --locked EXPOSE 8080 CMD ["hyper-techempower"] HEALTHCHECK CMD curl --fail http://localhost:8080/ping || exit 1 \ No newline at end of file diff --git a/frameworks/Rust/hyperlane/Cargo.lock b/frameworks/Rust/hyperlane/Cargo.lock index 08387adbeb8..9b9082f85bb 100644 --- a/frameworks/Rust/hyperlane/Cargo.lock +++ b/frameworks/Rust/hyperlane/Cargo.lock @@ -274,9 +274,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -514,9 +514,9 @@ dependencies = [ [[package]] name = "http-compress" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1b2aca6817a5a211bd1aeafd3f3f5c9d222f3b1cac5416f667fd04d5ac655d" +checksum = "5a7b163ab0da395ee1f950d547b44ac3b73ed1a351d53454d6ae811e9daa288e" dependencies = [ "brotli", "flate2", @@ -525,15 +525,15 @@ dependencies = [ [[package]] name = "http-constant" -version = "1.68.0" +version = "1.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd414126bc050b1437bed5a52939854b2b7ef214e8e05aacca3663529514e3e" +checksum = "7886400d92b0eb2db84097de69ed4649ca9466f4c6b4e8cb342a3b46934a8d43" [[package]] name = "http-type" -version = "5.8.0" +version = "5.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb36d75dbf127e3bfa1c7f404ba69edd760a3a5a93687caaafdb07f73eff64f" +checksum = "b27d55be58ea8bc2ab73573aeafa68fd50b3098813f83029bcb766f1f1c61b3b" dependencies = [ "hex", "http-compress", @@ -549,9 +549,9 @@ dependencies = [ [[package]] name = "hyperlane" -version = "10.11.3" +version = "10.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c042df01c9d47727269228fa5bacbb25504a6785539c0e5942dd8b2541c33a0" +checksum = "6abaa8b50397c4a9d2d0d969ccba9cecdad7bf0fa75c7da0335d6895c3d0ce98" dependencies = [ "aho-corasick", "http-type", @@ -1161,14 +1161,14 @@ dependencies = [ [[package]] name = "serde-xml-rs" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53630160a98edebde0123eb4dfd0fce6adff091b2305db3154a9e920206eb510" +checksum = "cc2215ce3e6a77550b80a1c37251b7d294febaf42e36e21b7b411e0bf54d540d" dependencies = [ "log", "serde", - "thiserror 1.0.69", - "xml-rs", + "thiserror", + "xml", ] [[package]] @@ -1347,7 +1347,7 @@ dependencies = [ "serde_json", "sha2", "smallvec", - "thiserror 2.0.17", + "thiserror", "tokio", "tokio-stream", "tracing", @@ -1429,7 +1429,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.17", + "thiserror", "tracing", "whoami", ] @@ -1466,7 +1466,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.17", + "thiserror", "tracing", "whoami", ] @@ -1490,7 +1490,7 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", - "thiserror 2.0.17", + "thiserror", "tracing", "url", ] @@ -1540,33 +1540,13 @@ dependencies = [ "syn", ] -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - [[package]] name = "thiserror" version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.17", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "thiserror-impl", ] [[package]] @@ -1947,10 +1927,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] -name = "xml-rs" -version = "0.8.27" +name = "xml" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" +checksum = "2df5825faced2427b2da74d9100f1e2e93c533fff063506a81ede1cf517b2e7e" [[package]] name = "yoke" diff --git a/frameworks/Rust/hyperlane/Cargo.toml b/frameworks/Rust/hyperlane/Cargo.toml index 83196a7647b..40fddf212ec 100644 --- a/frameworks/Rust/hyperlane/Cargo.toml +++ b/frameworks/Rust/hyperlane/Cargo.toml @@ -20,7 +20,7 @@ exclude = [ [dependencies] futures = "0.3.31" -hyperlane = "10.11.3" +hyperlane = "10.14.0" hyperlane-time = "0.7.12" num_cpus = "1.17.0" once_cell = "1.21.3" diff --git a/frameworks/Rust/hyperlane/src/db/fn.rs b/frameworks/Rust/hyperlane/src/db/fn.rs index 8418f711c88..ab7ea1dd86e 100644 --- a/frameworks/Rust/hyperlane/src/db/fn.rs +++ b/frameworks/Rust/hyperlane/src/db/fn.rs @@ -87,13 +87,16 @@ pub(crate) async fn connection_db() -> DbPoolConnection { "{DATABASE_TYPE}://{DATABASE_USER_NAME}:{DATABASE_USER_PASSWORD}@{DATABASE_HOST}:{DATABASE_PORT}/{DATABASE_NAME}" ), }; - let pool_size: u32 = (get_thread_count() as u32).min(DB_MAX_CONNECTIONS); + let thread_count: u32 = get_thread_count() as u32; + let max_connections: u32 = (thread_count * 4).min(DB_MAX_CONNECTIONS); + let min_connections: u32 = thread_count.max(1); let pool: DbPoolConnection = PgPoolOptions::new() - .max_connections(DB_MAX_CONNECTIONS) - .min_connections(pool_size) + .max_connections(max_connections) + .min_connections(min_connections) + .acquire_timeout(std::time::Duration::from_secs(2)) + .idle_timeout(None) .max_lifetime(None) .test_before_acquire(false) - .idle_timeout(None) .connect(db_url) .await .unwrap(); diff --git a/frameworks/Rust/hyperlane/src/main.rs b/frameworks/Rust/hyperlane/src/main.rs index ea346052b05..3e16079e292 100644 --- a/frameworks/Rust/hyperlane/src/main.rs +++ b/frameworks/Rust/hyperlane/src/main.rs @@ -34,10 +34,7 @@ async fn main() { init_db().await; let config: ServerConfig = ServerConfig::new().await; - config.host("0.0.0.0").await; config.port(8080).await; - config.buffer(256).await; - config.disable_linger().await; config.disable_nodelay().await; let server: Server = Server::from(config).await; @@ -50,6 +47,6 @@ async fn main() { server.route::("/fortunes").await; server.route::("/upda").await; - let server_hook: ServerControlHook = server.run().await.unwrap_or_default(); + let server_hook: ServerControlHook = server.run().await.unwrap(); server_hook.wait().await; } diff --git a/frameworks/Rust/ntex/Cargo.toml b/frameworks/Rust/ntex/Cargo.toml index a4baf02318f..ae3e4cc977b 100755 --- a/frameworks/Rust/ntex/Cargo.toml +++ b/frameworks/Rust/ntex/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ntex-bench" -version = "2.1.0" +version = "3.0.0" edition = "2018" [[bin]] @@ -67,11 +67,10 @@ neon = ["ntex/neon"] neon-uring = ["ntex/neon-uring"] [dependencies] -ntex = "2.13" -ntex-compio = "0.3" -ntex-neon = "0.1.31" -ntex-net = "2.5.27" -ntex-bytes = { version = "0.1.21", features=["simd"] } +ntex = "3.0.0-pre.5" +ntex-neon = "0.1.35" +ntex-net = "3.0.0" +ntex-bytes = { version = "1", features=["simd"] } mimalloc = { version = "0.1.25", default-features = false } snmalloc-rs = { version = "0.3.3", features = ["native-cpu"] } yarte = { version = "0.15", features = ["bytes-buf", "json"] } @@ -86,11 +85,14 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" log = { version = "0.4", features = ["release_max_level_off"] } tok_io = {version = "1", package = "tokio" } -tokio-postgres = { git="https://github.com/fafhrd91/postgres.git", branch="ntex-2" } +tokio-postgres = { git="https://github.com/fafhrd91/postgres.git", branch="ntex-3" } [target.'cfg(target_os = "linux")'.dependencies] compio-driver = { version = "*", features = ["io-uring"]} +[patch.crates-io] +buf-min = { git = "https://github.com/fafhrd91/buf-min.git" } + [profile.release] opt-level = 3 codegen-units = 1 diff --git a/frameworks/Rust/ntex/src/db.rs b/frameworks/Rust/ntex/src/db.rs index a85b137139c..dc2eb93ffe3 100644 --- a/frameworks/Rust/ntex/src/db.rs +++ b/frameworks/Rust/ntex/src/db.rs @@ -39,7 +39,7 @@ pub struct PgConnection { impl PgConnection { pub async fn connect(db_url: &str) -> PgConnection { - let (cl, conn) = connect(db_url) + let (cl, conn) = connect(db_url, utils::db_config()) .await .expect("can not connect to postgresql"); ntex::rt::spawn(async move { diff --git a/frameworks/Rust/ntex/src/main.rs b/frameworks/Rust/ntex/src/main.rs index b0e53b3f05c..23494837277 100644 --- a/frameworks/Rust/ntex/src/main.rs +++ b/frameworks/Rust/ntex/src/main.rs @@ -2,7 +2,7 @@ static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; use ntex::http::header::{CONTENT_TYPE, SERVER}; -use ntex::{http, time::Seconds, util::BytesMut, util::PoolId, web}; +use ntex::{http, util::BytesMut, web}; use sonic_rs::Serialize; mod utils; @@ -52,18 +52,10 @@ async fn main() -> std::io::Result<()> { ntex::server::build() .backlog(1024) .enable_affinity() - .bind("techempower", "0.0.0.0:8080", |cfg| { - cfg.memory_pool(PoolId::P1); - PoolId::P1.set_read_params(65535, 2048); - PoolId::P1.set_write_params(65535, 2048); - - http::HttpService::build() - .keep_alive(http::KeepAlive::Os) - .client_timeout(Seconds::ZERO) - .headers_read_rate(Seconds::ZERO, Seconds::ZERO, 0) - .payload_read_rate(Seconds::ZERO, Seconds::ZERO, 0) - .h1(web::App::new().service(json).service(plaintext).finish()) + .bind("tfb", "0.0.0.0:8080", async |_| { + http::HttpService::h1(web::App::new().service(json).service(plaintext).finish()) })? + .config("tfb", utils::config()) .run() .await } diff --git a/frameworks/Rust/ntex/src/main_db.rs b/frameworks/Rust/ntex/src/main_db.rs index 544921fb594..8536a0978bb 100644 --- a/frameworks/Rust/ntex/src/main_db.rs +++ b/frameworks/Rust/ntex/src/main_db.rs @@ -3,10 +3,9 @@ static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; use ntex::http::header::{CONTENT_TYPE, SERVER}; -use ntex::http::{HttpService, KeepAlive, Request, Response, StatusCode}; -use ntex::service::{Service, ServiceCtx, ServiceFactory}; -use ntex::web::{Error, HttpResponse}; -use ntex::{time::Seconds, util::PoolId}; +use ntex::http::{HttpService, Request, Response, StatusCode}; +use ntex::service::{cfg::SharedCfg, Service, ServiceCtx, ServiceFactory}; +use ntex::{web::Error, web::HttpResponse}; mod db; mod utils; @@ -64,13 +63,13 @@ impl Service for App { struct AppFactory; -impl ServiceFactory for AppFactory { +impl ServiceFactory for AppFactory { type Response = Response; type Error = Error; type Service = App; type InitError = (); - async fn create(&self, _: ()) -> Result { + async fn create(&self, _: SharedCfg) -> Result { const DB_URL: &str = "postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world"; @@ -85,18 +84,8 @@ async fn main() -> std::io::Result<()> { ntex::server::build() .backlog(1024) .enable_affinity() - .bind("techempower", "0.0.0.0:8080", |cfg| { - cfg.memory_pool(PoolId::P1); - PoolId::P1.set_read_params(65535, 2048); - PoolId::P1.set_write_params(65535, 2048); - - HttpService::build() - .keep_alive(KeepAlive::Os) - .client_timeout(Seconds(0)) - .headers_read_rate(Seconds::ZERO, Seconds::ZERO, 0) - .payload_read_rate(Seconds::ZERO, Seconds::ZERO, 0) - .h1(AppFactory) - })? + .bind("tfb", "0.0.0.0:8080", async |_| HttpService::h1(AppFactory))? + .config("tfb", utils::config()) .run() .await } diff --git a/frameworks/Rust/ntex/src/main_plt.rs b/frameworks/Rust/ntex/src/main_plt.rs index e16070f0b63..83619c5053c 100644 --- a/frameworks/Rust/ntex/src/main_plt.rs +++ b/frameworks/Rust/ntex/src/main_plt.rs @@ -3,7 +3,7 @@ static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; use std::{future::Future, io, pin::Pin, task::ready, task::Context, task::Poll}; -use ntex::{fn_service, http::h1, io::Io, io::RecvError, util::PoolId}; +use ntex::{fn_service, http::h1, io::Io, io::RecvError}; use sonic_rs::Serialize; mod utils; @@ -82,16 +82,13 @@ async fn main() -> io::Result<()> { ntex::server::build() .backlog(1024) .enable_affinity() - .bind("techempower", "0.0.0.0:8080", |cfg| { - cfg.memory_pool(PoolId::P1); - PoolId::P1.set_read_params(65535, 2048); - PoolId::P1.set_write_params(65535, 2048); - + .bind("tfb", "0.0.0.0:8080", async |_| { fn_service(|io| App { io, codec: h1::Codec::default(), }) })? + .config("tfb", utils::config()) .run() .await } diff --git a/frameworks/Rust/ntex/src/utils.rs b/frameworks/Rust/ntex/src/utils.rs index 6fd48e6e265..b3399bd8497 100644 --- a/frameworks/Rust/ntex/src/utils.rs +++ b/frameworks/Rust/ntex/src/utils.rs @@ -2,7 +2,8 @@ use std::{cmp, io, io::Write, mem::MaybeUninit, slice::from_raw_parts_mut}; use atoi::FromRadix10; -use ntex::{http::header::HeaderValue, util::BufMut, util::Bytes, util::BytesMut}; +use ntex::http::{header::HeaderValue, HttpServiceConfig, KeepAlive}; +use ntex::{io::IoConfig, time::Seconds, util::BufMut, util::Bytes, util::BytesMut, SharedCfg}; use sonic_rs::writer::WriteExt; pub const HDR_SERVER: HeaderValue = HeaderValue::from_static("N"); @@ -15,6 +16,37 @@ pub const BODY_PLAIN_TEXT: Bytes = Bytes::from_static(b"Hello, World!"); const HW: usize = 128 * 1024; pub const SIZE: usize = 27; +pub fn config() -> SharedCfg { + thread_local! { + static CFG: SharedCfg = SharedCfg::new("tfb") + .add( + IoConfig::new() + .set_read_buf(65535, 2048, 128) + .set_write_buf(65535, 2048, 128), + ) + .add( + HttpServiceConfig::new() + .set_keepalive(KeepAlive::Os) + .set_client_timeout(Seconds::ZERO) + .set_headers_read_rate(Seconds::ZERO, Seconds::ZERO, 0) + .set_payload_read_rate(Seconds::ZERO, Seconds::ZERO, 0), + ).into(); + } + CFG.with(|cfg| *cfg) +} + +pub fn db_config() -> SharedCfg { + thread_local! { + static CFG: SharedCfg = SharedCfg::new("tfb-db") + .add( + IoConfig::new() + .set_read_buf(65535, 2048, 128) + .set_write_buf(65535, 2048, 128), + ).into() + } + CFG.with(|cfg| *cfg) +} + pub fn get_query_param(query: Option<&str>) -> usize { let query = query.unwrap_or(""); let q = if let Some(pos) = query.find('q') { diff --git a/frameworks/Rust/pavex/benchmark_config.json b/frameworks/Rust/pavex/benchmark_config.json index e9decbdcdd9..1a4bc1856a7 100755 --- a/frameworks/Rust/pavex/benchmark_config.json +++ b/frameworks/Rust/pavex/benchmark_config.json @@ -18,6 +18,7 @@ "database_os": "Linux", "display_name": "pavex", "notes": "", + "tags": ["broken"], "versus": "None" } } diff --git a/frameworks/Rust/rocket/benchmark_config.json b/frameworks/Rust/rocket/benchmark_config.json index 2569f14f9ef..fb37d7377e9 100755 --- a/frameworks/Rust/rocket/benchmark_config.json +++ b/frameworks/Rust/rocket/benchmark_config.json @@ -22,6 +22,7 @@ "database_os": "Linux", "display_name": "Rocket", "notes": "", + "tags": ["broken"], "versus": "None" }, "diesel": { diff --git a/frameworks/Rust/salvo/benchmark_config.json b/frameworks/Rust/salvo/benchmark_config.json index 2890085bf66..d5f4d1f91a0 100644 --- a/frameworks/Rust/salvo/benchmark_config.json +++ b/frameworks/Rust/salvo/benchmark_config.json @@ -19,6 +19,7 @@ "database_os": "Linux", "display_name": "Salvo", "notes": "", + "tags": ["broken"], "versus": "None" }, "diesel": { @@ -39,6 +40,7 @@ "database_os": "Linux", "display_name": "Salvo [postgres-diesel]", "notes": "", + "tags": ["broken"], "versus": "None" }, "pg": { @@ -59,6 +61,7 @@ "database_os": "Linux", "display_name": "Salvo [postgres]", "notes": "", + "tags": ["broken"], "versus": "None" }, "pg-pool": { @@ -79,6 +82,7 @@ "database_os": "Linux", "display_name": "Salvo [postgres-deadpool]", "notes": "", + "tags": ["broken"], "versus": "None" }, "mongo": { @@ -99,6 +103,7 @@ "database_os": "Linux", "display_name": "Salvo [mongodb]", "notes": "", + "tags": ["broken"], "versus": "None" }, "mongo-raw": { @@ -118,6 +123,7 @@ "database_os": "Linux", "display_name": "Salvo [mongodb-raw]", "notes": "", + "tags": ["broken"], "versus": "None" }, "sqlx": { @@ -136,6 +142,7 @@ "database_os": "Linux", "display_name": "Salvo [postgres-sqlx]", "notes": "", + "tags": ["broken"], "versus": "None" }, "lru": { @@ -153,6 +160,7 @@ "database_os": "Linux", "display_name": "Salvo [lru]", "notes": "", + "tags": ["broken"], "versus": "None" } } diff --git a/frameworks/Rust/viz/.gitignore b/frameworks/Rust/vidi/.gitignore similarity index 100% rename from frameworks/Rust/viz/.gitignore rename to frameworks/Rust/vidi/.gitignore diff --git a/frameworks/Rust/vidi/Cargo.toml b/frameworks/Rust/vidi/Cargo.toml new file mode 100644 index 00000000000..c3ea4dc571a --- /dev/null +++ b/frameworks/Rust/vidi/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "vidi" +version = "0.1.0" +edition = "2024" +publish = false +authors = ["Fangdun Tsai "] + +[[bin]] +name = "vidi" +path = "src/main.rs" + +[[bin]] +name = "vidi-pg" +path = "src/main_pg.rs" +required-features = ["tokio-postgres", "yarte"] + +[dependencies] +vidi = "0.1" +hyper = "1.0" +hyper-util = "0.1" +http-body-util = "0.1" +atoi = "2.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1" +mime = "0.3" +rand = { version = "0.9", features = ["small_rng"] } +thiserror = "2.0" +futures-util = "0.3" +socket2 = { version = "0.6.0", features = ["all"] } +num_cpus = "1.0" + +[target.'cfg(not(unix))'.dependencies] +nanorand = { version = "0.8" } + +[target.'cfg(unix)'.dependencies] +nanorand = { version = "0.8", features = ["getrandom"] } + +tokio = { version = "1", features = ["full"] } +tokio-postgres = { version = "0.7", optional = true } + +yarte = { version = "0.15", features = ["bytes-buf", "json"], optional = true } + +[profile.release] +lto = true +codegen-units = 1 +strip = true +opt-level = 3 diff --git a/frameworks/Rust/viz/README.md b/frameworks/Rust/vidi/README.md similarity index 55% rename from frameworks/Rust/viz/README.md rename to frameworks/Rust/vidi/README.md index 84c2be44a52..2a5575441eb 100644 --- a/frameworks/Rust/viz/README.md +++ b/frameworks/Rust/vidi/README.md @@ -1,5 +1,7 @@ -# [viz](https://github.com/viz-rs) web framework +# [vidi] web framework ## Description Fast, robust, flexible, lightweight web framework for Rust. + +[vidi]: https://github.com/viz-rs/vidi diff --git a/frameworks/Rust/vidi/benchmark_config.json b/frameworks/Rust/vidi/benchmark_config.json new file mode 100755 index 00000000000..9b5755ae71f --- /dev/null +++ b/frameworks/Rust/vidi/benchmark_config.json @@ -0,0 +1,47 @@ +{ + "framework": "vidi", + "tests": [ + { + "default": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "none", + "framework": "Vidi", + "language": "Rust", + "flavor": "None", + "orm": "Raw", + "platform": "Rust", + "webserver": "Hyper", + "os": "Linux", + "database_os": "Linux", + "display_name": "Vidi", + "notes": "", + "versus": "None" + }, + "pg": { + "db_url": "/db", + "fortune_url": "/fortunes", + "query_url": "/queries?q=", + "update_url": "/updates?q=", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "postgres", + "framework": "Vidi", + "language": "Rust", + "flavor": "None", + "orm": "Raw", + "platform": "Rust", + "webserver": "Hyper", + "os": "Linux", + "database_os": "Linux", + "display_name": "Vidi [Postgresql]", + "notes": "", + "versus": "None" + } + } + ] +} diff --git a/frameworks/Rust/vidi/config.toml b/frameworks/Rust/vidi/config.toml new file mode 100644 index 00000000000..187fb23966a --- /dev/null +++ b/frameworks/Rust/vidi/config.toml @@ -0,0 +1,30 @@ +[framework] +name = "vidi" + +[main] +urls.plaintext = "/plaintext" +urls.json = "/json" +approach = "Realistic" +classification = "Micro" +database = "Postgres" +database_os = "Linux" +os = "Linux" +orm = "Raw" +platform = "None" +webserver = "vidi" +versus = "" + +[pg] +urls.db = "/db" +urls.query = "/queries?q=" +urls.update = "/updates?q=" +urls.fortune = "/fortunes" +approach = "Realistic" +classification = "Fullstack" +database = "Postgres" +database_os = "Linux" +os = "Linux" +orm = "Raw" +platform = "None" +webserver = "vidi" +versus = "" diff --git a/frameworks/Rust/viz/rustfmt.toml b/frameworks/Rust/vidi/rustfmt.toml similarity index 100% rename from frameworks/Rust/viz/rustfmt.toml rename to frameworks/Rust/vidi/rustfmt.toml diff --git a/frameworks/Rust/viz/src/db_pg.rs b/frameworks/Rust/vidi/src/db_pg.rs similarity index 93% rename from frameworks/Rust/viz/src/db_pg.rs rename to frameworks/Rust/vidi/src/db_pg.rs index da7a5a0be5f..b307df01e81 100644 --- a/frameworks/Rust/viz/src/db_pg.rs +++ b/frameworks/Rust/vidi/src/db_pg.rs @@ -1,10 +1,10 @@ use std::{collections::HashMap, fmt::Write, io, sync::Arc}; -use futures_util::{stream::FuturesUnordered, StreamExt, TryFutureExt, TryStreamExt}; -use rand::{rng, rngs::SmallRng, Rng, SeedableRng}; +use futures_util::{StreamExt, TryFutureExt, TryStreamExt, stream::FuturesUnordered}; +use rand::{Rng, SeedableRng, rng, rngs::SmallRng}; use tokio::pin; -use tokio_postgres::{connect, types::ToSql, Client, NoTls, Statement}; -use viz::{Error, IntoResponse, Response, StatusCode}; +use tokio_postgres::{Client, NoTls, Statement, connect, types::ToSql}; +use vidi::{Error, IntoResponse, Response, StatusCode}; use crate::models::{Fortune, World}; @@ -21,7 +21,7 @@ pub enum PgError { impl From for Error { fn from(e: PgError) -> Self { - Error::Responder(e.into_response()) + Error::Responder(Box::new(e.into_response())) } } diff --git a/frameworks/Rust/viz/src/main.rs b/frameworks/Rust/vidi/src/main.rs similarity index 75% rename from frameworks/Rust/viz/src/main.rs rename to frameworks/Rust/vidi/src/main.rs index 3552b23920c..179badbf0d2 100644 --- a/frameworks/Rust/viz/src/main.rs +++ b/frameworks/Rust/vidi/src/main.rs @@ -1,9 +1,9 @@ #![allow(clippy::unused_async)] use serde::Serialize; -use viz::{ - header::{HeaderValue, CONTENT_TYPE, SERVER}, +use vidi::{ Bytes, Request, Response, ResponseExt, Result, Router, + header::{CONTENT_TYPE, HeaderValue}, }; mod server; @@ -14,12 +14,11 @@ struct Message { message: &'static str, } +const HELLO_WORLD: &str = "Hello, World!"; + #[inline(always)] async fn plaintext(_: Request) -> Result { - let mut res = Response::text("Hello, World!"); - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); - Ok(res) + Ok(Response::text(HELLO_WORLD)) } #[inline(always)] @@ -28,7 +27,7 @@ async fn json(_: Request) -> Result { .body( http_body_util::Full::new(Bytes::from( serde_json::to_vec(&Message { - message: "Hello, World!", + message: HELLO_WORLD, }) .unwrap(), )) @@ -36,7 +35,6 @@ async fn json(_: Request) -> Result { ) .unwrap(); let headers = res.headers_mut(); - headers.insert(SERVER, HeaderValue::from_static("Viz")); headers.insert( CONTENT_TYPE, HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()), diff --git a/frameworks/Rust/viz/src/main_pg.rs b/frameworks/Rust/vidi/src/main_pg.rs similarity index 70% rename from frameworks/Rust/viz/src/main_pg.rs rename to frameworks/Rust/vidi/src/main_pg.rs index 4898ca8f24a..553d4805a1f 100644 --- a/frameworks/Rust/viz/src/main_pg.rs +++ b/frameworks/Rust/vidi/src/main_pg.rs @@ -1,10 +1,6 @@ use std::sync::Arc; -use viz::{ - header::{HeaderValue, SERVER}, - types::State, - Request, RequestExt, Response, ResponseExt, Result, Router, -}; +use vidi::{Request, RequestExt, Response, ResponseExt, Result, Router, types::State}; use yarte::Template; mod db_pg; @@ -12,7 +8,7 @@ mod models; mod server; mod utils; -use db_pg::{get_conn, PgConnection}; +use db_pg::{PgConnection, get_conn}; #[derive(Template)] #[template(path = "fortune.hbs")] @@ -28,9 +24,8 @@ async fn db(req: Request) -> Result { let world = conn.get_world().await?; - let mut res = Response::json(world)?; - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); + let res = Response::json(world)?; + Ok(res) } @@ -43,10 +38,7 @@ async fn fortunes(req: Request) -> Result { .call() .expect("error rendering template"); - let mut res = Response::html(buf); - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); - Ok(res) + Ok(Response::html(buf)) } async fn queries(req: Request) -> Result { @@ -55,9 +47,8 @@ async fn queries(req: Request) -> Result { let worlds = conn.get_worlds(count).await?; - let mut res = Response::json(worlds)?; - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); + let res = Response::json(worlds)?; + Ok(res) } @@ -67,9 +58,8 @@ async fn updates(req: Request) -> Result { let worlds = conn.update(count).await?; - let mut res = Response::json(worlds)?; - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); + let res = Response::json(worlds)?; + Ok(res) } diff --git a/frameworks/Rust/viz/src/models.rs b/frameworks/Rust/vidi/src/models.rs similarity index 100% rename from frameworks/Rust/viz/src/models.rs rename to frameworks/Rust/vidi/src/models.rs diff --git a/frameworks/Rust/viz/src/server.rs b/frameworks/Rust/vidi/src/server.rs similarity index 84% rename from frameworks/Rust/viz/src/server.rs rename to frameworks/Rust/vidi/src/server.rs index 047da0ba88a..69b12b7b595 100644 --- a/frameworks/Rust/viz/src/server.rs +++ b/frameworks/Rust/vidi/src/server.rs @@ -9,19 +9,28 @@ use hyper::server::conn::http1::Builder; use hyper_util::rt::TokioIo; use socket2::{Domain, SockAddr, Socket}; use tokio::{net::TcpListener, runtime}; -use viz::{Responder, Router, Tree}; +use vidi::header::{HeaderValue, SERVER}; +use vidi::{HandlerExt, Responder, Response, Router, Tree}; pub async fn serve(router: Router) -> Result<(), Box> { let addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 8080)); let socket = create_socket(addr).expect("couldn't bind to addr"); let listener = TcpListener::from_std(socket.into())?; + let router = router.map_handler(|h| { + h.map(|mut res: Response| { + let headers = res.headers_mut(); + headers.insert(SERVER, HeaderValue::from_static("Vidi")); + res + }) + .boxed() + }); let tree = Arc::::new(router.into()); let mut http = Builder::new(); http.pipeline_flush(true); - println!("Started viz server at 8080"); + println!("Started vidi server at 8080"); loop { let (tcp, _) = listener.accept().await?; diff --git a/frameworks/Rust/viz/src/utils.rs b/frameworks/Rust/vidi/src/utils.rs similarity index 100% rename from frameworks/Rust/viz/src/utils.rs rename to frameworks/Rust/vidi/src/utils.rs diff --git a/frameworks/Rust/viz/templates/fortune.hbs b/frameworks/Rust/vidi/templates/fortune.hbs similarity index 100% rename from frameworks/Rust/viz/templates/fortune.hbs rename to frameworks/Rust/vidi/templates/fortune.hbs diff --git a/frameworks/Rust/viz/templates/fortune.html b/frameworks/Rust/vidi/templates/fortune.html similarity index 100% rename from frameworks/Rust/viz/templates/fortune.html rename to frameworks/Rust/vidi/templates/fortune.html diff --git a/frameworks/Rust/viz/templates/fortune.stpl b/frameworks/Rust/vidi/templates/fortune.stpl similarity index 100% rename from frameworks/Rust/viz/templates/fortune.stpl rename to frameworks/Rust/vidi/templates/fortune.stpl diff --git a/frameworks/Rust/vidi/vidi-pg.dockerfile b/frameworks/Rust/vidi/vidi-pg.dockerfile new file mode 100644 index 00000000000..4b4af96db76 --- /dev/null +++ b/frameworks/Rust/vidi/vidi-pg.dockerfile @@ -0,0 +1,11 @@ +FROM rust:1.91 + +ADD ./ /vidi +WORKDIR /vidi + +RUN cargo clean +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin vidi-pg --features="tokio-postgres,yarte" + +EXPOSE 8080 + +CMD ./target/release/vidi-pg diff --git a/frameworks/Rust/viz/viz.dockerfile b/frameworks/Rust/vidi/vidi.dockerfile similarity index 56% rename from frameworks/Rust/viz/viz.dockerfile rename to frameworks/Rust/vidi/vidi.dockerfile index bf5102b2bec..cecc153db93 100644 --- a/frameworks/Rust/viz/viz.dockerfile +++ b/frameworks/Rust/vidi/vidi.dockerfile @@ -1,11 +1,11 @@ -FROM rust:1.89 +FROM rust:1.91 -ADD ./ /viz -WORKDIR /viz +ADD ./ /vidi +WORKDIR /vidi RUN cargo clean -RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin viz +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin vidi EXPOSE 8080 -CMD ./target/release/viz +CMD ./target/release/vidi diff --git a/frameworks/Rust/viz/Cargo.toml b/frameworks/Rust/viz/Cargo.toml deleted file mode 100644 index 7047dbe3666..00000000000 --- a/frameworks/Rust/viz/Cargo.toml +++ /dev/null @@ -1,72 +0,0 @@ -[package] -name = "viz" -version = "0.1.0" -edition = "2021" -authors = ["Fangdun Tsai "] - -[[bin]] -name = "viz" -path = "src/main.rs" - -[[bin]] -name = "viz-pg" -path = "src/main_pg.rs" -required-features = ["tokio-postgres", "yarte"] - -[[bin]] -name = "viz-sqlx" -path = "src/main_sqlx.rs" -required-features = ["sqlx", "markup", "v_htmlescape"] - -[[bin]] -name = "viz-diesel" -path = "src/main_diesel.rs" -required-features = ["diesel", "diesel-async", "sailfish"] - -[dependencies] -viz = "0.10" -hyper = "1.0" -hyper-util = "0.1" -http-body-util = "0.1" -atoi = "2.0" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1" -mime = "0.3" -rand = { version = "0.9", features = ["small_rng"] } -thiserror = "2.0" -futures-util = "0.3" -socket2 = { version = "0.6.0", features = ["all"] } -num_cpus = "1.16.0" - -[target.'cfg(not(unix))'.dependencies] -nanorand = { version = "0.8" } - -[target.'cfg(unix)'.dependencies] -nanorand = { version = "0.8", features = ["getrandom"] } - -tokio = { version = "1", features = ["full"] } -tokio-postgres = { version = "0.7", optional = true } -sqlx = { version = "0.8", features = [ - "postgres", - "macros", - "runtime-tokio", - "tls-native-tls", -], optional = true } -diesel = { version = "2.2", default-features = false, features = [ - "i-implement-a-third-party-backend-and-opt-into-breaking-changes", -], optional = true } -diesel-async = { version = "0.6", default-features = false, features = [ - "postgres", - "bb8", -], optional = true } - -yarte = { version = "0.15", features = ["bytes-buf", "json"], optional = true } -markup = { version = "0.15", optional = true } -v_htmlescape = { version = "0.15", optional = true } -sailfish = { version = "0.10", optional = true } - -[profile.release] -lto = true -codegen-units = 1 -strip = true -opt-level = 3 diff --git a/frameworks/Rust/viz/benchmark_config.json b/frameworks/Rust/viz/benchmark_config.json deleted file mode 100755 index 94a26df121e..00000000000 --- a/frameworks/Rust/viz/benchmark_config.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "framework": "viz", - "tests": [ - { - "default": { - "json_url": "/json", - "plaintext_url": "/plaintext", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "none", - "framework": "Viz", - "language": "Rust", - "flavor": "None", - "orm": "Raw", - "platform": "Rust", - "webserver": "Hyper", - "os": "Linux", - "database_os": "Linux", - "display_name": "Viz", - "notes": "", - "versus": "None" - }, - "pg": { - "db_url": "/db", - "fortune_url": "/fortunes", - "query_url": "/queries?q=", - "update_url": "/updates?q=", - "port": 8080, - "approach": "Realistic", - "classification": "Fullstack", - "database": "postgres", - "framework": "Viz", - "language": "Rust", - "flavor": "None", - "orm": "Raw", - "platform": "Rust", - "webserver": "Hyper", - "os": "Linux", - "database_os": "Linux", - "display_name": "Viz [Postgresql]", - "notes": "", - "versus": "None" - }, - "sqlx": { - "db_url": "/db", - "fortune_url": "/fortunes", - "query_url": "/queries?q=", - "update_url": "/updates?q=", - "port": 8080, - "approach": "Realistic", - "classification": "Fullstack", - "database": "postgres", - "framework": "Viz", - "language": "Rust", - "flavor": "None", - "orm": "Raw", - "platform": "Rust", - "webserver": "Hyper", - "os": "Linux", - "database_os": "Linux", - "display_name": "Viz [Postgresql - SQLx]", - "notes": "", - "versus": "None" - }, - "diesel": { - "db_url": "/db", - "fortune_url": "/fortunes", - "query_url": "/queries?q=", - "update_url": "/updates?q=", - "port": 8080, - "approach": "Realistic", - "classification": "Fullstack", - "database": "postgres", - "framework": "Viz", - "language": "Rust", - "flavor": "None", - "orm": "Full", - "platform": "Rust", - "webserver": "Hyper", - "os": "Linux", - "database_os": "Linux", - "display_name": "Viz [Postgresql - Diesel]", - "notes": "", - "versus": "None" - } - } - ] -} diff --git a/frameworks/Rust/viz/config.toml b/frameworks/Rust/viz/config.toml deleted file mode 100644 index b8b2bfb6bda..00000000000 --- a/frameworks/Rust/viz/config.toml +++ /dev/null @@ -1,60 +0,0 @@ -[framework] -name = "viz" - -[main] -urls.plaintext = "/plaintext" -urls.json = "/json" -approach = "Realistic" -classification = "Micro" -database = "Postgres" -database_os = "Linux" -os = "Linux" -orm = "Raw" -platform = "None" -webserver = "viz" -versus = "" - -[pg] -urls.db = "/db" -urls.query = "/queries?q=" -urls.update = "/updates?q=" -urls.fortune = "/fortunes" -approach = "Realistic" -classification = "Fullstack" -database = "Postgres" -database_os = "Linux" -os = "Linux" -orm = "Raw" -platform = "None" -webserver = "viz" -versus = "" - -[sqlx] -urls.db = "/db" -urls.query = "/queries?q=" -urls.update = "/updates?q=" -urls.fortune = "/fortunes" -approach = "Realistic" -classification = "Fullstack" -database = "Postgres" -database_os = "Linux" -os = "Linux" -orm = "Raw" -platform = "None" -webserver = "viz" -versus = "" - -[diesel] -urls.db = "/db" -urls.query = "/queries?q=" -urls.update = "/updates?q=" -urls.fortune = "/fortunes" -approach = "Realistic" -classification = "Fullstack" -database = "Postgres" -database_os = "Linux" -os = "Linux" -orm = "Full" -platform = "None" -webserver = "viz" -versus = "" diff --git a/frameworks/Rust/viz/src/db_diesel.rs b/frameworks/Rust/viz/src/db_diesel.rs deleted file mode 100644 index 624000a7d1d..00000000000 --- a/frameworks/Rust/viz/src/db_diesel.rs +++ /dev/null @@ -1,120 +0,0 @@ -use diesel::prelude::*; -use diesel_async::{ - pooled_connection::bb8::{Pool, RunError}, - AsyncPgConnection, RunQueryDsl, -}; -use nanorand::{Rng, WyRand}; -use sailfish::{RenderError, TemplateOnce}; -use viz::{Error, IntoResponse, Response, StatusCode}; - -use crate::models_diesel::*; -use crate::schema::*; -use crate::RANGE; - -/// Postgres Error -#[derive(Debug, thiserror::Error)] -pub enum PgError { - #[error("missing pool")] - Missing, - #[error(transparent)] - DieselError(#[from] diesel::result::Error), - #[error(transparent)] - PoolError(#[from] RunError), - #[error(transparent)] - RenderError(#[from] RenderError), -} - -impl From for Error { - fn from(e: PgError) -> Self { - Error::Responder(e.into_response()) - } -} - -impl IntoResponse for PgError { - fn into_response(self) -> Response { - (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response() - } -} - -async fn _get_world(conn: &mut AsyncPgConnection, id: i32) -> Result { - let world = world::table.find(id).first(conn).await?; - Ok(world) -} - -pub async fn get_world( - pool: Pool, - id: i32, -) -> Result { - let mut conn = pool.get().await?; - _get_world(&mut conn, id).await -} - -pub async fn get_worlds( - pool: Pool, - mut rng: WyRand, - count: u16, -) -> Result, PgError> { - let mut conn = pool.get().await?; - - let mut worlds = Vec::::with_capacity(count as usize); - - for _ in 0..count { - let id = rng.generate_range(RANGE); - let w = _get_world(&mut conn, id).await?; - worlds.push(w); - } - - Ok(worlds) -} - -pub async fn update_worlds( - pool: Pool, - mut rng: WyRand, - count: u16, -) -> Result, PgError> { - let mut conn = pool.get().await?; - - let mut worlds = Vec::::with_capacity(count as usize); - - for _ in 0..count { - let id = rng.generate_range(RANGE); - let rid = rng.generate_range(RANGE); - let mut w = _get_world(&mut conn, id).await?; - w.randomnumber = rid; - worlds.push(w); - } - - worlds.sort_by_key(|w| w.id); - - conn.build_transaction() - .run(move |conn| { - Box::pin(async move { - for w in &worlds { - diesel::update(world::table) - .filter(world::id.eq(w.id)) - .set(world::randomnumber.eq(w.randomnumber)) - .execute(conn) - .await?; - } - - Ok::<_, PgError>(worlds) - }) - }) - .await -} - -pub async fn tell_fortune(pool: Pool) -> Result { - let mut conn = pool.get().await?; - - let mut items = fortune::table.load::(&mut conn).await?; - - items.push(Fortune { - id: 0, - message: "Additional fortune added at request time.".to_string(), - }); - items.sort_by(|it, next| it.message.cmp(&next.message)); - - let html = Fortunes::new(items).render_once()?; - - Ok(html) -} diff --git a/frameworks/Rust/viz/src/db_sqlx.rs b/frameworks/Rust/viz/src/db_sqlx.rs deleted file mode 100644 index 40c39290265..00000000000 --- a/frameworks/Rust/viz/src/db_sqlx.rs +++ /dev/null @@ -1,119 +0,0 @@ -use nanorand::{Rng, WyRand}; - -pub use sqlx::{ - pool::PoolConnection, - postgres::{PgArguments, PgPoolOptions, PgRow}, - Arguments, PgPool, Postgres, Row, -}; - -use viz::{Error, FromRequest, IntoResponse, Request, RequestExt, Response, StatusCode}; - -use crate::models_sqlx::*; -use crate::utils::get_query_param; -use crate::RANGE; - -pub struct DatabaseConnection(pub PoolConnection); - -impl FromRequest for DatabaseConnection { - type Error = PgError; - - async fn extract(req: &mut Request) -> Result { - req.state::() - .ok_or(PgError(sqlx::Error::Io(std::io::Error::from( - std::io::ErrorKind::NotConnected, - ))))? - .acquire() - .await - .map(Self) - .map_err(PgError) - } -} - -#[derive(Debug, thiserror::Error)] -#[error(transparent)] -pub struct PgError(#[from] pub sqlx::Error); - -impl From for Error { - fn from(e: PgError) -> Self { - Error::Responder(e.into_response()) - } -} - -impl IntoResponse for PgError { - fn into_response(self) -> Response { - (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response() - } -} - -pub struct Counter(pub u16); - -impl FromRequest for Counter { - type Error = Error; - - async fn extract(req: &mut Request) -> Result { - Ok(Counter(get_query_param(req.query_string()))) - } -} - -pub async fn get_world( - conn: &mut PoolConnection, - id: i32, -) -> Result { - let mut args = PgArguments::default(); - let _ = args.add(id); - - let world = - sqlx::query_as_with("SELECT id, randomnumber FROM World WHERE id = $1", args) - .fetch_one(&mut **conn) - .await?; - Ok(world) -} - -pub async fn update_worlds( - mut conn: PoolConnection, - mut rng: WyRand, - count: u16, -) -> Result, PgError> { - let mut worlds = Vec::::with_capacity(count as usize); - - for _ in 0..count { - let id = rng.generate_range(RANGE); - let rid = rng.generate_range(RANGE); - let mut w = get_world(&mut conn, id).await?; - w.randomnumber = rid; - worlds.push(w); - } - - for w in &worlds { - let mut args = PgArguments::default(); - let _ = args.add(w.randomnumber); - let _ = args.add(w.id); - - sqlx::query_with("UPDATE World SET randomNumber = $1 WHERE id = $2", args) - .execute(&mut *conn) - .await?; - } - - Ok(worlds) -} - -pub async fn get_fortunes( - mut conn: PoolConnection, -) -> Result, PgError> { - let mut items = sqlx::query("SELECT * FROM Fortune") - .map(|row: PgRow| Fortune { - id: row.get(0), - message: row.get(1), - }) - .fetch_all(&mut *conn) - .await?; - - items.push(Fortune { - id: 0, - message: "Additional fortune added at request time.".to_string(), - }); - - items.sort_by(|it, next| it.message.cmp(&next.message)); - - Ok(items) -} diff --git a/frameworks/Rust/viz/src/main_diesel.rs b/frameworks/Rust/viz/src/main_diesel.rs deleted file mode 100644 index ec3a002c2a7..00000000000 --- a/frameworks/Rust/viz/src/main_diesel.rs +++ /dev/null @@ -1,104 +0,0 @@ -#[macro_use] -extern crate diesel; - -use std::thread::available_parallelism; - -use diesel_async::{ - pooled_connection::{bb8::Pool, AsyncDieselConnectionManager}, - AsyncPgConnection, -}; -use nanorand::{Rng, WyRand}; -use viz::{ - header::{HeaderValue, SERVER}, - types::State, - Request, RequestExt, Response, ResponseExt, Result, Router, -}; - -mod db_diesel; -pub mod models_diesel; -pub mod schema; -mod server; -mod utils; - -use db_diesel::*; -use utils::RANGE; - -const DB_URL: &str = - "postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world"; - -async fn db(req: Request) -> Result { - let mut rng = req.state::().unwrap(); - let pool = req.state::>().unwrap(); - - let random_id = rng.generate_range(RANGE); - - let world = get_world(pool, random_id).await?; - - let mut res = Response::json(world)?; - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); - Ok(res) -} - -async fn fortunes(req: Request) -> Result { - let pool = req.state::>().unwrap(); - - let fortunes = tell_fortune(pool).await?; - - let mut res = Response::html(fortunes); - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); - Ok(res) -} - -async fn queries(req: Request) -> Result { - let rng = req.state::().unwrap(); - let pool = req.state::>().unwrap(); - let count = utils::get_query_param(req.query_string()); - - let worlds = get_worlds(pool, rng, count).await?; - - let mut res = Response::json(worlds)?; - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); - Ok(res) -} - -async fn updates(req: Request) -> Result { - let rng = req.state::().unwrap(); - let pool = req.state::>().unwrap(); - let count = utils::get_query_param(req.query_string()); - - let worlds = update_worlds(pool, rng, count).await?; - - let mut res = Response::json(worlds)?; - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); - Ok(res) -} - -async fn app() { - let max = available_parallelism().map(|n| n.get()).unwrap_or(16) as u32; - - let pool = Pool::::builder() - .max_size(max) - .min_idle(Some(max)) - .idle_timeout(None) - .build_unchecked(AsyncDieselConnectionManager::new(DB_URL)); - - let rng = WyRand::new(); - - let app = Router::new() - .get("/db", db) - .get("/fortunes", fortunes) - .get("/queries", queries) - .get("/updates", updates) - .with(State::new(pool)) - .with(State::new(rng)); - - server::serve(app).await.unwrap() -} - -fn main() { - server::run(app) -} diff --git a/frameworks/Rust/viz/src/main_sqlx.rs b/frameworks/Rust/viz/src/main_sqlx.rs deleted file mode 100644 index e2aff0ff98f..00000000000 --- a/frameworks/Rust/viz/src/main_sqlx.rs +++ /dev/null @@ -1,129 +0,0 @@ -use std::thread::available_parallelism; - -use nanorand::{Rng, WyRand}; -use viz::{ - header::{HeaderValue, SERVER}, - types::State, - BytesMut, Error, Request, RequestExt, Response, ResponseExt, Result, Router, -}; - -mod db_sqlx; -mod models_sqlx; -mod server; -mod utils; - -use db_sqlx::*; -use models_sqlx::{Fortune, World}; -use utils::RANGE; - -const DB_URL: &str = - "postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world"; - -async fn db(mut req: Request) -> Result { - let (State(mut rng), DatabaseConnection(mut conn)) = - req.extract::<(State, DatabaseConnection)>().await?; - - let random_id = rng.generate_range(RANGE); - - let world = get_world(&mut conn, random_id).await?; - - let mut res = Response::json(world)?; - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); - Ok(res) -} - -async fn fortunes(mut req: Request) -> Result { - let DatabaseConnection(conn) = req.extract::().await?; - - let items = get_fortunes(conn).await?; - - let mut buf = BytesMut::with_capacity(2048); - buf.extend(FortunesTemplate { items }.to_string().as_bytes()); - - let mut res = Response::html(buf.freeze()); - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); - Ok(res) -} - -async fn queries(mut req: Request) -> Result { - let (Counter(count), State(mut rng), DatabaseConnection(mut conn)) = req - .extract::<(Counter, State, DatabaseConnection)>() - .await?; - - let mut worlds = Vec::::with_capacity(count as usize); - - for _ in 0..count { - let id = rng.generate_range(RANGE); - let w = get_world(&mut conn, id).await?; - worlds.push(w); - } - - let mut res = Response::json(worlds)?; - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); - Ok(res) -} - -async fn updates(mut req: Request) -> Result { - let (Counter(count), State(rng), DatabaseConnection(conn)) = req - .extract::<(Counter, State, DatabaseConnection)>() - .await?; - - let worlds = update_worlds(conn, rng, count).await?; - - let mut res = Response::json(worlds)?; - res.headers_mut() - .insert(SERVER, HeaderValue::from_static("Viz")); - Ok(res) -} - -async fn app() -> Result<()> { - let max = available_parallelism().map(|n| n.get()).unwrap_or(16) as u32; - - let pool = PgPoolOptions::new() - .max_connections(max) - .min_connections(max) - .connect(DB_URL) - .await - .map_err(PgError)?; - - let rng = WyRand::new(); - - let app = Router::new() - .get("/db", db) - .get("/fortunes", fortunes) - .get("/queries", queries) - .get("/updates", updates) - .with(State::new(pool)) - .with(State::new(rng)); - - server::serve(app).await.map_err(Error::Boxed) -} - -fn main() { - server::run(app) -} - -markup::define! { - FortunesTemplate(items: Vec) { - {markup::doctype()} - html { - head { - title { "Fortunes" } - } - body { - table { - tr { th { "id" } th { "message" } } - @for item in items { - tr { - td { {item.id} } - td { {markup::raw(v_htmlescape::escape(&item.message).to_string())} } - } - } - } - } - } - } -} diff --git a/frameworks/Rust/viz/src/models_diesel.rs b/frameworks/Rust/viz/src/models_diesel.rs deleted file mode 100644 index 63711594223..00000000000 --- a/frameworks/Rust/viz/src/models_diesel.rs +++ /dev/null @@ -1,28 +0,0 @@ -use diesel::Queryable; -use sailfish::TemplateOnce; -use serde::Serialize; - -#[derive(Serialize, Queryable, Debug)] -pub struct World { - pub id: i32, - pub randomnumber: i32, -} - -#[derive(Serialize, Queryable, Debug)] -pub struct Fortune { - pub id: i32, - pub message: String, -} - -#[derive(TemplateOnce)] -#[template(path = "fortune.stpl", rm_whitespace = true)] -pub struct Fortunes { - items: Vec, -} - -impl Fortunes { - #[inline] - pub fn new(items: Vec) -> Self { - Self { items } - } -} diff --git a/frameworks/Rust/viz/src/models_sqlx.rs b/frameworks/Rust/viz/src/models_sqlx.rs deleted file mode 100644 index 2f3657a9936..00000000000 --- a/frameworks/Rust/viz/src/models_sqlx.rs +++ /dev/null @@ -1,14 +0,0 @@ -use serde::{Deserialize, Serialize}; -use sqlx::FromRow; - -#[derive(Debug, PartialEq, Deserialize, Serialize, FromRow)] -pub struct World { - pub id: i32, - pub randomnumber: i32, -} - -#[derive(Debug, PartialEq, Deserialize, Serialize, FromRow)] -pub struct Fortune { - pub id: i32, - pub message: String, -} diff --git a/frameworks/Rust/viz/src/schema.rs b/frameworks/Rust/viz/src/schema.rs deleted file mode 100644 index 30b1bfeb7fc..00000000000 --- a/frameworks/Rust/viz/src/schema.rs +++ /dev/null @@ -1,13 +0,0 @@ -table! { - world (id) { - id -> Integer, - randomnumber -> Integer, - } -} - -table! { - fortune (id) { - id -> Integer, - message -> Text, - } -} diff --git a/frameworks/Rust/viz/viz-diesel.dockerfile b/frameworks/Rust/viz/viz-diesel.dockerfile deleted file mode 100644 index 4d10b67baa1..00000000000 --- a/frameworks/Rust/viz/viz-diesel.dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM rust:1.89 - -ADD ./ /viz -WORKDIR /viz - -RUN cargo clean -RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin viz-diesel --features="diesel,diesel-async,sailfish" - -EXPOSE 8080 - -CMD ./target/release/viz-diesel diff --git a/frameworks/Rust/viz/viz-pg.dockerfile b/frameworks/Rust/viz/viz-pg.dockerfile deleted file mode 100644 index 23bc34e49c3..00000000000 --- a/frameworks/Rust/viz/viz-pg.dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM rust:1.89 - -ADD ./ /viz -WORKDIR /viz - -RUN cargo clean -RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin viz-pg --features="tokio-postgres,yarte" - -EXPOSE 8080 - -CMD ./target/release/viz-pg diff --git a/frameworks/Rust/viz/viz-sqlx.dockerfile b/frameworks/Rust/viz/viz-sqlx.dockerfile deleted file mode 100644 index c9a7685855f..00000000000 --- a/frameworks/Rust/viz/viz-sqlx.dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM rust:1.89 - -ADD ./ /viz -WORKDIR /viz - -RUN cargo clean -RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin viz-sqlx --features="sqlx,markup,v_htmlescape" - -EXPOSE 8080 - -CMD ./target/release/viz-sqlx diff --git a/frameworks/Rust/warp-rust/benchmark_config.json b/frameworks/Rust/warp-rust/benchmark_config.json index 5d91146bef5..1f159f54957 100755 --- a/frameworks/Rust/warp-rust/benchmark_config.json +++ b/frameworks/Rust/warp-rust/benchmark_config.json @@ -22,6 +22,7 @@ "database_os": "Linux", "display_name": "warp-rust", "notes": "", + "tags": ["broken"], "versus": "None" } } diff --git a/frameworks/Rust/water-http/.gitignore b/frameworks/Rust/water-http/.gitignore new file mode 100644 index 00000000000..2da6cdebaac --- /dev/null +++ b/frameworks/Rust/water-http/.gitignore @@ -0,0 +1,3 @@ +target +Cargo.lock +.idea \ No newline at end of file diff --git a/frameworks/Rust/water-http/Cargo.toml b/frameworks/Rust/water-http/Cargo.toml new file mode 100644 index 00000000000..fe22c5a9a68 --- /dev/null +++ b/frameworks/Rust/water-http/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "water-http" +version = "0.1.0" +edition = "2018" + +[dependencies] +askama = "0.14.0" +tokio = { version = "1.47.1", features = ["full"] } +water_http = {git = "https://github.com/HassanSharara/water_http.git", branch = "beta", features = ["use_only_http1"],optional = true , version = "3.0.8-beta.5" } +smallvec = "1.15.1" +nanorand = "0.8.0" +tokio-postgres = "0.7.15" +sonic-rs = "0.5.5" +bytes = "1.10.1" +serde = { version = "1.0.228", features = ["derive","rc"] } +futures-util = "0.3.31" +num_cpus = "1.17.0" +httpdate = "1.0.3" +parking_lot = "0.12.5" +yarte = { version = "0.15.7" ,features = ["bytes-buf", "json"] } +itoa = {version = "1.0.15" ,optional = true} + + +[[bin]] +name = "plaintext" +path = "src/plaintext.rs" +required-features = ["json_plaintext"] + +[[bin]] +name = "json" +path = "src/json.rs" +required-features = ["json_plaintext"] + + +[[bin]] +name = "cache" +path = "src/cached.rs" +required-features = ["cache"] + + +[features] +json_plaintext = ["water_http"] +db = ["water_http/thread_shared_struct"] +cache = ["water_http/thread_shared_struct","itoa"] +all = ["water_http/thread_shared_struct"] diff --git a/frameworks/Rust/water-http/README b/frameworks/Rust/water-http/README new file mode 100644 index 00000000000..67e4ecc228a --- /dev/null +++ b/frameworks/Rust/water-http/README @@ -0,0 +1,39 @@ +🌊 Water HTTP — TechEmpower Benchmarks + +Water HTTP is a high-performance Rust web framework built and optimized for the TechEmpower Framework Benchmarks (TFB) +. It is designed to push the limits of speed, stability, and scalability using pure asynchronous Rust and Tokio’s runtime. Every part of the framework is hand-tuned to achieve predictable latency, minimal allocations, and efficient CPU utilization under extreme concurrency. + +This repository contains the official benchmark implementations for all test types, including Plaintext, JSON serialization, Single query, Multiple queries, Fortunes, Database updates, and Cached queries. + +⚡ Highlights + +🚀 One of the fastest and most stable frameworks in the TechEmpower Benchmarks + +🧵 Built entirely on Tokio’s asynchronous runtime — no io_uring or unsafe code + +💾 Zero-copy I/O, preallocated buffers, and predictable memory layout + +🔒 100% safe Rust with no hidden synchronization overhead + +🧱 Designed for consistent high performance at scale + + +🧠 Architecture + +Water HTTP is built around a fully asynchronous, event-driven architecture that leverages non-blocking I/O and efficient request processing. The system is designed to eliminate unnecessary locks and minimize latency even under heavy load. + +[ tokio::net::TcpListener ] + ↓ + [ connection handler ] + ↓ + [ water::http::parser ] + ↓ + [ application logic ] + ↓ + [ response encoder ] +This approach ensures optimal throughput and minimal per-request overhead while keeping code simple and safe. + + +🧭 Mission + +Water HTTP’s mission is to demonstrate how Rust’s async ecosystem can reach record-breaking performance without compromising simplicity, safety, or maintainability. It shows that carefully engineered async Rust can deliver unmatched speed and reliability in real-world workloads, setting a new standard for what modern web frameworks can achieve. diff --git a/frameworks/Rust/water-http/benchmark_config.json b/frameworks/Rust/water-http/benchmark_config.json new file mode 100644 index 00000000000..2b28f0476a3 --- /dev/null +++ b/frameworks/Rust/water-http/benchmark_config.json @@ -0,0 +1,90 @@ +{ + "framework": "water-http", + "tests": [ + { + "default": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "fortune_url": "/fortunes", + "db_url": "/db", + "query_url": "/queries?q=", + "update_url": "/updates?q=", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "Postgres", + "framework": "water_http", + "language": "Rust", + "orm": "raw", + "platform": "Rust", + "webserver": "water_http", + "os": "Linux", + "database_os": "Linux", + "display_name": "water_http" + }, + + "db": { + "fortune_url": "/fortunes", + "db_url": "/db", + "query_url": "/queries?q=", + "update_url": "/updates?q=", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "Postgres", + "framework": "water_http", + "language": "Rust", + "orm": "raw", + "platform": "Rust", + "webserver": "water_http", + "os": "Linux", + "database_os": "Linux", + "display_name": "water_http" + }, + + "cached": { + "cached_query_url": "/cached-queries?q=", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "Postgres", + "framework": "water_http", + "language": "Rust", + "orm": "raw", + "platform": "Rust", + "webserver": "water_http", + "os": "Linux", + "database_os": "Linux", + "display_name": "water_http" + }, + "json": { + "json_url": "/json", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "framework": "water_http", + "language": "Rust", + "orm": "raw", + "platform": "Rust", + "webserver": "water_http", + "os": "Linux", + "database_os": "Linux", + "display_name": "water_http" + }, + "plaintext": { + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "framework": "water_http", + "language": "Rust", + "orm": "raw", + "platform": "Rust", + "webserver": "water_http", + "os": "Linux", + "database_os": "Linux", + "display_name": "water_http" + } + } + ] +} \ No newline at end of file diff --git a/frameworks/Rust/water-http/src/cached.rs b/frameworks/Rust/water-http/src/cached.rs new file mode 100644 index 00000000000..6e1cea1a77f --- /dev/null +++ b/frameworks/Rust/water-http/src/cached.rs @@ -0,0 +1,305 @@ +#![allow(static_mut_refs)] +use std::io; +use std::fmt::Arguments; +use std::io::Write; +use std::mem::MaybeUninit; +use std::rc::Rc; +use std::cell::UnsafeCell; +use std::collections::HashMap; +use nanorand::{Rng, WyRand}; +use tokio_postgres::{connect, Client, NoTls}; +use tokio_postgres::types::private::BytesMut; +use sonic_rs::prelude::WriteExt; +use std::pin::Pin; +use tokio::task::LocalSet; +use water_http::{InitControllersRoot, RunServer, WaterController}; +use water_http::http::{HttpSender, ResponseData}; +use water_http::server::{HttpContext, ServerConfigurations}; +use water_http::http::HttpSenderTrait; + +pub struct DbConnectionPool { + pub connections: Vec>, + pub next: UnsafeCell, +} + +impl DbConnectionPool { + /// Get a connection from the pool (round-robin, relaxed ordering) + #[inline(always)] + pub fn get_connection(&self) -> &Rc { + let n = unsafe{&mut *self.next.get()}; + *n +=1; + let idx = *n % self.connections.len(); + unsafe { self.connections.get_unchecked(idx) } + } + + /// Fill the pool with connections + pub async fn fill_pool(&mut self, url: &'static str, size: usize) { + let mut tasks = Vec::with_capacity(size); + for _ in 0..size { + tasks.push(tokio::task::spawn_local(async move { + for attempt in 0..5 { + match PgConnection::connect(url).await { + Ok(conn) => { + + return Ok(conn); }, + Err(_) if attempt < 4 => { + tokio::time::sleep(std::time::Duration::from_millis(100)).await; + } + Err(_) => return Err(()), + } + } + Err(()) + })); + } + for t in tasks { + if let Ok(Ok(conn)) = t.await { + self.connections.push(Rc::new(conn)); + } + } + } + + +} + + + + +pub struct PgConnection { + cl:Client, + _connection_task: tokio::task::JoinHandle<()>, +} + +// Safety: Only used within LocalSet, no cross-thread access +impl PgConnection { + /// Connect to the database + + pub async fn connect(db_url: &str) -> Result { + let (cl, c) = tokio::time::timeout( + std::time::Duration::from_secs(5), + connect(db_url, NoTls), + ) + .await + .map_err(|_| ())? + .map_err(|_| ())?; + + let connection_task = tokio::task::spawn_local(async move { + let _ = c.await; + }); + + Ok(PgConnection { + _connection_task: connection_task, + cl + }) + } +} + +/// Zero-copy writer for BytesMut +pub struct BytesMuteWriter<'a>(pub &'a mut BytesMut); + +impl BytesMuteWriter<'_> { + + #[inline(always)] + pub fn extend_from_slice(&mut self,data:&[u8]){ + self.0.extend_from_slice(data); + } +} + +impl Write for BytesMuteWriter<'_> { + #[inline(always)] + fn write(&mut self, src: &[u8]) -> Result { + self.0.extend_from_slice(src); + Ok(src.len()) + } + + #[inline(always)] + fn flush(&mut self) -> Result<(), io::Error> { + Ok(()) + } +} + +impl std::fmt::Write for BytesMuteWriter<'_> { + #[inline(always)] + fn write_str(&mut self, s: &str) -> std::fmt::Result { + self.0.extend_from_slice(s.as_bytes()); + Ok(()) + } + + #[inline(always)] + fn write_char(&mut self, c: char) -> std::fmt::Result { + let mut buf = [0u8; 4]; + self.0.extend_from_slice(c.encode_utf8(&mut buf).as_bytes()); + Ok(()) + } + + #[inline(always)] + fn write_fmt(&mut self, args: Arguments<'_>) -> std::fmt::Result { + std::fmt::write(self, args) + } +} + +impl WriteExt for BytesMuteWriter<'_> { + #[inline(always)] + fn reserve_with(&mut self, additional: usize) -> Result<&mut [MaybeUninit], io::Error> { + self.0.reserve(additional); + unsafe { + let ptr = self.0.as_mut_ptr().add(self.0.len()) as *mut MaybeUninit; + Ok(std::slice::from_raw_parts_mut(ptr, additional)) + } + } + + #[inline(always)] + unsafe fn flush_len(&mut self, additional: usize) -> io::Result<()> { + self.0.set_len(self.0.len() + additional); + Ok(()) + } +} + + +InitControllersRoot! { + name:ROOT, + holder_type:MainType, + shared_type:SH, +} + +pub struct ThreadSharedStruct{ + writing_buffer:UnsafeCell, + rng:WyRand, +} + + +impl ThreadSharedStruct { + + #[inline(always)] + pub fn get_value(id:i32)->&'static i32{ + let map = unsafe {CACHED_VALUES.as_ref().unwrap().get(&id)} ; + map.unwrap() + } + pub fn get_cached_queries(&self,num:usize)->&[u8]{ + let buf = unsafe{&mut *(self.writing_buffer.get())}; + buf.clear(); + buf.extend_from_slice(br#"["#); + let mut writer = BytesMuteWriter(buf); + let mut rn = self.rng.clone(); + for _ in 0..num { + let rd: i32 = (rn.generate::() & 0x3FFF) as i32 % 10_000 + 1; + let v = Self::get_value(rd); + writer.extend_from_slice(br"{"); + _ = write!(writer, r#""id":{},"randomnumber":{}"#, rd, v); + writer.extend_from_slice(br"},"); + } + if buf.len() >1 {buf.truncate(buf.len() - 1);} + buf.extend_from_slice(b"]"); + return &buf[..] + } +} + +pub type MainType = u8; +pub type SH = Rc; + + +static mut CACHED_VALUES:Option> = None; + +pub fn run_server(){ + + _= std::thread::spawn( + ||{ + let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(); + rt.block_on(async move { + const URL:&'static str = "postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world"; + // const URL:&'static str = "postgres://postgres:root@localhost:5432/techmpower"; + + let mut pool = DbConnectionPool{ + connections:Vec::with_capacity( 1 + ), + next:0.into(), + // rt:tokio::runtime::Builder::new_multi_thread().enable_all().worker_threads(cpu_nums).build().unwrap() + }; + + let local_set = LocalSet::new(); + + _= local_set.run_until(async move { + tokio::task::spawn_local(async move { + pool.fill_pool(URL, 1).await; + let connection = pool.get_connection(); + let statement = connection.cl.prepare("SELECT id,randomnumber FROM World").await.unwrap(); + let res = connection.cl.query(&statement,&[]).await.unwrap(); + let mut map = HashMap::new(); + for row in res { + map.insert(row.get(0),row.get(1)); + } + unsafe { + let static_map = &mut CACHED_VALUES; + *static_map = Some(map); + } + }).await + }).await; + + }); + } + ).join(); + let cpu_nums = num_cpus::get(); + + + println!("start listening on port 8080 while workers count {cpu_nums}"); + let mut conf = ServerConfigurations::bind("0.0.0.0",8080); + conf.worker_threads_count = cpu_nums * 1 ; + + // let addresses = (0..cpu_nums).map(|_| { + // ("0.0.0.0".to_string(),8080) + // }).collect::>(); + // conf.addresses = addresses; + RunServer!( + conf, + ROOT, + EntryController, + shared_factory + ); +} + +fn shared_factory()->Pin>>{ + Box::pin(async { + + // const URL:&'static str = "postgres://postgres:root@localhost:5432/techmpower"; + + Rc::new(ThreadSharedStruct{ + writing_buffer:UnsafeCell::new(BytesMut::with_capacity(100_000)), + rng:WyRand::new() + }) + }) +} + +pub async fn handle_cached_queries(context:&mut HttpContext<'_,MainType,SH,HS,QS>){ + let q = context + .get_from_path_query("q") + .and_then(|v| v.parse::().ok()) // safely parse + .unwrap_or(1) // default to 1 if missing or invalid + .clamp(1, 500); + + let connection:SH = context.thread_shared_struct.clone().unwrap().clone(); + let data = connection.get_cached_queries(q); + let mut sender:HttpSender = context.sender(); + sender.set_header_ef("Content-Type","application/json"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _= sender.send_data_as_final_response( + ResponseData::Slice(data) + ).await; +} + +WaterController! { + holder -> super::MainType, + shared -> super::SH, + name -> EntryController, + functions -> { + + GET -> "cached-queries" -> query (context) { + _=super::handle_cached_queries(context).await; + } + } +} + +fn main() { + run_server(); +} + diff --git a/frameworks/Rust/water-http/src/db.rs b/frameworks/Rust/water-http/src/db.rs new file mode 100644 index 00000000000..40640735f88 --- /dev/null +++ b/frameworks/Rust/water-http/src/db.rs @@ -0,0 +1,320 @@ +#![cfg(any(feature = "db",feature = "all"))] +use std::{borrow::Cow, io}; +use std::fmt::Arguments; +use std::io::Write; +use std::mem::MaybeUninit; +use std::rc::Rc; +use std::cell::UnsafeCell; +use bytes::Buf; +use nanorand::{Rng, WyRand}; +use tokio_postgres::{connect, Client, Statement, NoTls}; +use tokio_postgres::types::private::BytesMut; +use crate::models::{Fortune, FortuneTemplate, World}; +use sonic_rs::prelude::WriteExt; +use yarte::TemplateBytesTrait; + +/// Database connection pool with thread-local RNG +pub struct DbConnectionPool { + pub connections: Vec>, + pub next: UnsafeCell, +} + +impl DbConnectionPool { + /// Get a connection from the pool (round-robin, relaxed ordering) + #[inline(always)] + pub fn get_connection(&self) -> &Rc { + let n = unsafe{&mut *self.next.get()}; + *n +=1; + let idx = *n % self.connections.len(); + unsafe { self.connections.get_unchecked(idx) } + } + + /// Fill the pool with connections + pub async fn fill_pool(&mut self, url: &'static str, size: usize) { + let mut tasks = Vec::with_capacity(size); + for _ in 0..size { + tasks.push(tokio::task::spawn_local(async move { + for attempt in 0..5 { + match PgConnection::connect(url).await { + Ok(conn) => { + + return Ok(conn); }, + Err(_) if attempt < 4 => { + tokio::time::sleep(std::time::Duration::from_millis(100)).await; + } + Err(_) => return Err(()), + } + } + Err(()) + })); + } + for t in tasks { + if let Ok(Ok(conn)) = t.await { + self.connections.push(Rc::new(conn)); + } + } + } +} + + +/// Reusable buffer pool per connection +struct BufferPool { + body: BytesMut, + worlds: Vec, + numbers: Vec, + fortunes: Vec, + fortune_output: Vec, +} + +impl BufferPool { + fn new() -> Self { + Self { + body: BytesMut::with_capacity(4096), + worlds: Vec::with_capacity(501), + numbers: Vec::with_capacity(501), + + fortunes: Vec::with_capacity(501), + fortune_output: Vec::with_capacity(4096), + } + } + +} + +/// PostgreSQL connection wrapper with pre-allocated buffers +pub struct PgConnection { + pub cl: Client, + pub fortune: Statement, + pub world: Statement, + pub updates: Vec, + rang:WyRand, + buffers: UnsafeCell, + _connection_task: tokio::task::JoinHandle<()>, +} + +// Safety: Only used within LocalSet, no cross-thread access +impl PgConnection { + /// Connect to the database + + pub async fn connect(db_url: &str) -> Result { + let (cl, conn) = tokio::time::timeout( + std::time::Duration::from_secs(5), + connect(db_url, NoTls), + ) + .await + .map_err(|_| ())? + .map_err(|_| ())?; + + let connection_task = tokio::task::spawn_local(async move { + let _ = conn.await; + }); + + let fortune = cl.prepare("SELECT * FROM fortune").await.map_err(|_| ())?; + let world = cl.prepare("SELECT id,randomnumber FROM world WHERE id=$1 LIMIT 1").await.map_err(|_| ())?; + + // Pre-compile update statements for batch sizes 1-500 + let mut updates = vec![]; + for num in 1..=500 { + let sql = Self::generate_update_values_stmt(num); + updates.push(cl.prepare(&sql).await.unwrap()); + } + + Ok(PgConnection { + cl, + fortune, + world, + updates, + buffers: UnsafeCell::new(BufferPool::new()), + _connection_task: connection_task, + rang: WyRand::new() + }) + } /// Connect to the database + + #[inline(always)] + pub fn generate_update_values_stmt(batch_size: usize) -> String { + + let mut sql = String::from("UPDATE world SET randomNumber = w.r FROM (VALUES "); + + for i in 0..batch_size { + let id_param = i * 2 + 1; + let val_param = id_param + 1; + sql.push_str(&format!("(${}::int, ${}::int),", id_param, val_param)); + } + + // Remove the trailing comma + sql.pop(); + + sql.push_str(") AS w(i, r) WHERE world.id = w.i"); + sql + } + + /// Get mutable access to buffers (safe because connection pool ensures single access) + #[inline(always)] + fn buffers(&self) -> &mut BufferPool { + unsafe { &mut *self.buffers.get() } + } + + /// Get a single random world - optimized with buffer reuse + #[inline] + pub async fn get_world(&self) -> &[u8] { + let rd = (self.rang.clone().generate::() % 10_000 + 1) as i32; + let row = self.cl.query_one(&self.world, &[&rd]).await.unwrap(); + + let buffers = self.buffers(); + buffers.body.clear(); + + sonic_rs::to_writer( + BytesMuteWriter(&mut buffers.body), + &World { + id: row.get(0), + randomnumber: row.get(1), + }, + ).unwrap(); + + buffers.body.chunk() + } + + /// Get multiple random worlds - optimized with buffer reuse + pub async fn get_worlds(&self, num: usize) -> &[u8] { + let buffers = self.buffers(); + buffers.worlds.clear(); + let mut rn = self.rang.clone(); + for _ in 0..num { + let id: i32 = (rn.generate::() & 0x3FFF) as i32 % 10_000 + 1; + let row = self.cl.query_one(&self.world, &[&id]).await.unwrap(); + buffers.worlds.push(World { + id: row.get(0), + randomnumber: row.get(1), + }); + } + buffers.body.clear(); + sonic_rs::to_writer(BytesMuteWriter(&mut buffers.body), &buffers.worlds).unwrap(); + buffers.body.chunk() + } + /// Update worlds in batch - optimized with buffer reuse + /// Update worlds in batch - optimized with buffer reuse + + /// Update worlds in batch - optimized with buffer reuse + + /// Update worlds in batch - optimized with buffer reuse + + /// Update worlds in batch - optimized with RETURNING clause to minimize reads + /// Update worlds - fetch and update each row to handle duplicates correctly + /// Update worlds in batch using CASE statement + pub async fn update(&self, num: usize) -> &[u8] { + + let buffers = self.buffers(); + let mut ids:Vec = Vec::with_capacity(num); + let mut rng = self.rang.clone(); + let mut params: Vec<&(dyn tokio_postgres::types::ToSql + Sync)> = + Vec::with_capacity(num * 2); + let mut futures =vec![]; + for _ in 0..num { + let w_id = (rng.generate::() % 10_000 + 1) as i32; + ids.push(w_id); + } + futures.extend(ids.iter().map(|x| async move {self.cl.query_one(&self.world,&[&x]).await})); + futures_util::future::join_all(futures).await; + ids.sort_unstable(); + buffers.worlds.clear(); + for index in 0..num { + let s_id = (rng.generate::() % 10_000 + 1 ) as i32; + buffers.worlds.push(World{ + id:ids[index], + randomnumber:s_id + }); + buffers.numbers.push(s_id); + } + buffers.body.clear(); + for index in 0..num { + params.push(&ids[index]); + params.push(&buffers.numbers[index]); + } + + _=self.cl.execute(&self.updates[num - 1], ¶ms).await.unwrap(); + sonic_rs::to_writer(BytesMuteWriter(&mut buffers.body), &buffers.worlds).unwrap(); + buffers.body.chunk() + } + + + /// Tell fortunes - optimized with buffer reuse + pub async fn tell_fortune(&self) -> Result<&[u8], ()> { + let res = self.cl.query(&self.fortune, &[]).await.map_err(|_| ())?; + + let buffers = self.buffers(); + buffers.fortunes.clear(); + buffers.fortune_output.clear(); + + buffers.fortunes.push(Fortune { + id: 0, + message: Cow::Borrowed("Additional fortune added at request time."), + }); + + for row in res { + buffers.fortunes.push(Fortune { + id: row.get(0), + message: Cow::Owned(row.get(1)), + }); + } + + buffers.fortunes.sort_unstable_by(|a, b| a.message.cmp(&b.message)); + + let template = FortuneTemplate { items: &buffers.fortunes }; + template.write_call(&mut buffers.fortune_output); + + // Return reference to buffer - zero-copy! + Ok(&buffers.fortune_output) + } +} + +/// Zero-copy writer for BytesMut +pub struct BytesMuteWriter<'a>(pub &'a mut BytesMut); + +impl Write for BytesMuteWriter<'_> { + #[inline(always)] + fn write(&mut self, src: &[u8]) -> Result { + self.0.extend_from_slice(src); + Ok(src.len()) + } + + #[inline(always)] + fn flush(&mut self) -> Result<(), io::Error> { + Ok(()) + } +} + +impl std::fmt::Write for BytesMuteWriter<'_> { + #[inline(always)] + fn write_str(&mut self, s: &str) -> std::fmt::Result { + self.0.extend_from_slice(s.as_bytes()); + Ok(()) + } + + #[inline(always)] + fn write_char(&mut self, c: char) -> std::fmt::Result { + let mut buf = [0u8; 4]; + self.0.extend_from_slice(c.encode_utf8(&mut buf).as_bytes()); + Ok(()) + } + + #[inline(always)] + fn write_fmt(&mut self, args: Arguments<'_>) -> std::fmt::Result { + std::fmt::write(self, args) + } +} + +impl WriteExt for BytesMuteWriter<'_> { + #[inline(always)] + fn reserve_with(&mut self, additional: usize) -> Result<&mut [MaybeUninit], io::Error> { + self.0.reserve(additional); + unsafe { + let ptr = self.0.as_mut_ptr().add(self.0.len()) as *mut MaybeUninit; + Ok(std::slice::from_raw_parts_mut(ptr, additional)) + } + } + + #[inline(always)] + unsafe fn flush_len(&mut self, additional: usize) -> io::Result<()> { + self.0.set_len(self.0.len() + additional); + Ok(()) + } +} \ No newline at end of file diff --git a/frameworks/Rust/water-http/src/json.rs b/frameworks/Rust/water-http/src/json.rs new file mode 100644 index 00000000000..71f406b6051 --- /dev/null +++ b/frameworks/Rust/water-http/src/json.rs @@ -0,0 +1,55 @@ +use water_http::{InitControllersRoot, RunServer, WaterController}; +use water_http::server::ServerConfigurations; + +InitControllersRoot! { + name:ROOT, + holder_type:MainType, +} + + + +pub type MainType = u8; + + +fn main() { + run_server(); +} + + +pub fn run_server(){ + + let cpu_nums = num_cpus::get(); + + + println!("start listening on port 8080 while workers count {cpu_nums}"); + let mut conf = ServerConfigurations::bind("0.0.0.0",8080); + conf.worker_threads_count = cpu_nums * 2 ; + + RunServer!( + conf, + ROOT, + EntryController + ); +} + +const JSON_RESPONSE:&'static [u8] = br#"{"message":"Hello, World!"}"#; + + +WaterController! { + holder -> super::MainType, + name -> EntryController, + functions -> { + + + GET => json => j(cx){ + let mut sender = cx.sender(); + sender.set_header_ef("Content-Type","application/json"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _=sender.send_data_as_final_response(http::ResponseData::Slice(super::JSON_RESPONSE)).await; + } + + } +} + diff --git a/frameworks/Rust/water-http/src/main.rs b/frameworks/Rust/water-http/src/main.rs new file mode 100644 index 00000000000..487409af1d6 --- /dev/null +++ b/frameworks/Rust/water-http/src/main.rs @@ -0,0 +1,7 @@ +mod server; +pub mod models; +mod db; + +fn main() { + server::run_server(); +} diff --git a/frameworks/Rust/water-http/src/models.rs b/frameworks/Rust/water-http/src/models.rs new file mode 100644 index 00000000000..1fee7283ba9 --- /dev/null +++ b/frameworks/Rust/water-http/src/models.rs @@ -0,0 +1,25 @@ +use std::borrow::Cow; +use sonic_rs::{Serialize}; +// use askama::Template; +#[derive(Serialize)] +pub struct World { + pub id: i32, + pub randomnumber: i32, +} +#[derive(Serialize,Debug)] +pub struct Fortune { + pub id: i32, + pub message: Cow<'static, str>, +} + +#[derive(yarte::TemplateBytes)] +#[template(path = "fortune.hbs")] +pub struct FortuneTemplate<'a>{ + pub items:&'a Vec +} + + + +// pub async fn to(model:FortuneTemplate<'_>){ +// model.r +// } \ No newline at end of file diff --git a/frameworks/Rust/water-http/src/plaintext.rs b/frameworks/Rust/water-http/src/plaintext.rs new file mode 100644 index 00000000000..197da216e9c --- /dev/null +++ b/frameworks/Rust/water-http/src/plaintext.rs @@ -0,0 +1,54 @@ +use water_http::{InitControllersRoot, RunServer, WaterController}; +use water_http::server::ServerConfigurations; + +InitControllersRoot! { + name:ROOT, + holder_type:MainType, +} + + + +pub type MainType = u8; + + +fn main() { + run_server(); +} + + +pub fn run_server(){ + + let cpu_nums = num_cpus::get(); + + + println!("start listening on port 8080 while workers count {cpu_nums}"); + let mut conf = ServerConfigurations::bind("0.0.0.0",8080); + conf.worker_threads_count = cpu_nums * 1 ; + + RunServer!( + conf, + ROOT, + EntryController + ); +} + +const JSON_RESPONSE:&'static [u8] = br#"{"message":"Hello, World!"}"#; +const P:&'static [u8] = br#"Hello, World!"#; + + +WaterController! { + holder -> super::MainType, + name -> EntryController, + functions -> { + + GET => plaintext => p(cx) { + let mut sender = cx.sender(); + sender.set_header_ef("Content-Type","text/plain; charset=utf-8"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _=sender.send_data_as_final_response(http::ResponseData::Str("Hello, World!")).await; + } + } +} + diff --git a/frameworks/Rust/water-http/src/server.rs b/frameworks/Rust/water-http/src/server.rs new file mode 100644 index 00000000000..be464a0e3d6 --- /dev/null +++ b/frameworks/Rust/water-http/src/server.rs @@ -0,0 +1,290 @@ + +use std::pin::Pin; +use std::rc::Rc; +use water_http::{InitControllersRoot, RunServer, WaterController}; +use water_http::server::ServerConfigurations; +use crate::db::{DbConnectionPool}; +InitControllersRoot! { + name:ROOT, + holder_type:MainType, + shared_type:SharedType, +} + +pub struct ThreadSharedStruct{ + pg_connection: DbConnectionPool +} + +pub type MainType = u8; +pub type SharedType = Rc; + + + + +pub fn run_server(){ + + let cpu_nums = num_cpus::get(); + + + println!("start listening on port 8080 while workers count {cpu_nums}"); + let mut conf = ServerConfigurations::bind("0.0.0.0",8080); + #[cfg(feature = "json_plaintext")] + { + conf.worker_threads_count = cpu_nums * 2 ; + } + #[cfg(not(feature = "json_plaintext"))] + { + conf.worker_threads_count = cpu_nums * 1 ; + } + + // let addresses = (0..cpu_nums).map(|_| { + // ("0.0.0.0".to_string(),8080) + // }).collect::>(); + // conf.addresses = addresses; + RunServer!( + conf, + ROOT, + EntryController, + shared_factory + ); +} + +fn shared_factory()->Pin>>{ + Box::pin(async { + + // const URL:&'static str = "postgres://postgres:root@localhost:5432/techmpower"; + const URL:&'static str = "postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world"; + let mut pool = DbConnectionPool{ + connections:Vec::with_capacity( 1 + ), + next:0.into(), + // rt:tokio::runtime::Builder::new_multi_thread().enable_all().worker_threads(cpu_nums).build().unwrap() + }; + pool.fill_pool(URL, 1).await; + Rc::new(ThreadSharedStruct{ + pg_connection:pool + }) + }) +} + +#[cfg(any(feature = "json_plaintext",feature = "all"))] +const JSON_RESPONSE:&'static [u8] = br#"{"message":"Hello, World!"}"#; +#[cfg(any(feature = "json_plaintext",feature = "all"))] +const P:&'static [u8] = br#"Hello, World!"#; + +#[cfg(feature = "all")] +WaterController! { + holder -> super::MainType, + shared -> super::SharedType, + name -> EntryController, + functions -> { + + + GET => json => j(cx){ + let mut sender = cx.sender(); + sender.set_header_ef("Content-Type","application/json"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _=sender.send_data_as_final_response(http::ResponseData::Slice(super::JSON_RESPONSE)).await; + } + + GET => plaintext => p(cx){ + let mut sender = cx.sender(); + sender.set_header_ef("Content-Type","text/plain; charset=utf-8"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _=sender.send_data_as_final_response(http::ResponseData::Slice(super::P)).await; + } + + + GET -> db -> db (context){ + let connection:Shared = context.thread_shared_struct.clone().unwrap().clone(); + let connection = connection.pg_connection.get_connection(); + let data = connection.get_world().await; + let mut sender = context.sender(); + sender.set_header_ef("Content-Type","application/json"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _= sender.send_data_as_final_response( + http::ResponseData::Slice(data) + ).await; + } + GET -> queries -> query (context){ + let q = context + .get_from_path_query("q") + .and_then(|v| v.parse::().ok()) // safely parse + .unwrap_or(1) // default to 1 if missing or invalid + .clamp(1, 500); + + let connection:Shared = context.thread_shared_struct.clone().unwrap().clone(); + let connection = connection.pg_connection.get_connection(); + let data = connection.get_worlds(q).await; + let mut sender = context.sender(); + sender.set_header_ef("Content-Type","application/json"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _= sender.send_data_as_final_response( + http::ResponseData::Slice(data) + ).await; + } + + GET -> updates -> update (context){ + let q = context + .get_from_path_query("q") + .and_then(|v| v.parse::().ok()) // safely parse + .unwrap_or(1) // default to 1 if missing or invalid + .clamp(1, 500); + let connection:Shared = context.thread_shared_struct.clone().unwrap().clone(); + let connection = connection.pg_connection.get_connection(); + let data = connection.update(q).await; + let mut sender = context.sender(); + sender.set_header_ef("Content-Type","application/json"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _= sender.send_data_as_final_response( + http::ResponseData::Slice(data) + ).await; + } + + + GET -> fortunes -> ft (context){ + + let connection:Shared = context.thread_shared_struct.clone().unwrap().clone(); + let connection = connection.pg_connection.get_connection(); + let data = match connection.tell_fortune().await { + Ok(r)=>{r}, + _=>{ + _= context.send_str("failed to connect").await; + return + } + }; + let mut sender = context.sender(); + sender.set_header_ef("Content-Type","text/html; charset=UTF-8"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _= sender.send_data_as_final_response( + http::ResponseData::Slice(&data) + ).await; + } + + } +} + + + +#[cfg(all(not(feature = "all"),feature = "json_plaintext"))] +WaterController! { + holder -> super::MainType, + shared -> super::SharedType, + name -> EntryController, + functions -> { + + + GET => json => j(cx){ + let mut sender = cx.sender(); + sender.set_header_ef("Content-Type","application/json"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _=sender.send_data_as_final_response(http::ResponseData::Slice(super::JSON_RESPONSE)).await; + } + + GET => plaintext => p(cx) { + let mut sender = cx.sender(); + sender.set_header_ef("Content-Type","text/plain; charset=utf-8"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _=sender.send_data_as_final_response(http::ResponseData::Slice(super::P)).await; + } + } +} + +#[cfg(all(not(feature = "all"),feature = "db"))] +WaterController! { + holder -> super::MainType, + shared -> super::SharedType, + name -> EntryController, + functions -> { + + + GET -> db -> db (context){ + let connection:Shared = context.thread_shared_struct.clone().unwrap().clone(); + let connection = connection.pg_connection.get_connection(); + let data = connection.get_world().await; + let mut sender = context.sender(); + sender.set_header_ef("Content-Type","application/json"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _= sender.send_data_as_final_response( + http::ResponseData::Slice(data) + ).await; + } + GET -> queries -> query (context){ + let q = context + .get_from_path_query("q") + .and_then(|v| v.parse::().ok()) // safely parse + .unwrap_or(1) // default to 1 if missing or invalid + .clamp(1, 500); + + let connection:Shared = context.thread_shared_struct.clone().unwrap().clone(); + let connection = connection.pg_connection.get_connection(); + let data = connection.get_worlds(q).await; + let mut sender = context.sender(); + sender.set_header_ef("Content-Type","application/json"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _= sender.send_data_as_final_response( + http::ResponseData::Slice(data) + ).await; + } + + GET -> updates -> update (context){ + let q = context + .get_from_path_query("q") + .and_then(|v| v.parse::().ok()) // safely parse + .unwrap_or(1) // default to 1 if missing or invalid + .clamp(1, 500); + let connection:Shared = context.thread_shared_struct.clone().unwrap().clone(); + let connection = connection.pg_connection.get_connection(); + let data = connection.update(q).await; + let mut sender = context.sender(); + sender.set_header_ef("Content-Type","application/json"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _= sender.send_data_as_final_response( + http::ResponseData::Slice(data) + ).await; + } + + + GET -> fortunes -> ft (context){ + + let connection:Shared = context.thread_shared_struct.clone().unwrap().clone(); + let connection = connection.pg_connection.get_connection(); + let data = match connection.tell_fortune().await { + Ok(r)=>{r}, + _=>{ + _= context.send_str("failed to connect").await; + return + } + }; + let mut sender = context.sender(); + sender.set_header_ef("Content-Type","text/html; charset=UTF-8"); + sender.set_header_ef("Server","water"); + let date = httpdate::fmt_http_date(std::time::SystemTime::now()); + sender.set_header_ef("Date",date); + _= sender.send_data_as_final_response( + http::ResponseData::Slice(&data) + ).await; + } + } +} \ No newline at end of file diff --git a/frameworks/Rust/water-http/templates/fortune.hbs b/frameworks/Rust/water-http/templates/fortune.hbs new file mode 100644 index 00000000000..b219172a075 --- /dev/null +++ b/frameworks/Rust/water-http/templates/fortune.hbs @@ -0,0 +1,5 @@ +Fortunes +{{~# each items ~}} + +{{~/each ~}} +
idmessage
{{id}}{{message}}
diff --git a/frameworks/Rust/water-http/templates/fortune.html b/frameworks/Rust/water-http/templates/fortune.html new file mode 100644 index 00000000000..35923e04b21 --- /dev/null +++ b/frameworks/Rust/water-http/templates/fortune.html @@ -0,0 +1,12 @@ + + +Fortunes + + + + {% for item in items %} + + {% endfor %} +
idmessage
{{item.id}}{{item.message}}
+ + diff --git a/frameworks/Rust/water-http/water-http-cached.dockerfile b/frameworks/Rust/water-http/water-http-cached.dockerfile new file mode 100644 index 00000000000..3c873c71520 --- /dev/null +++ b/frameworks/Rust/water-http/water-http-cached.dockerfile @@ -0,0 +1,13 @@ +FROM rust:latest + +RUN apt-get update -yqq && apt-get install -yqq cmake g++ + +ADD ./ /water +WORKDIR /water + +RUN cargo clean +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin cache --features cache + +EXPOSE 8080 + +CMD ./target/release/cache \ No newline at end of file diff --git a/frameworks/Rust/water-http/water-http-db.dockerfile b/frameworks/Rust/water-http/water-http-db.dockerfile new file mode 100644 index 00000000000..01d9507b35f --- /dev/null +++ b/frameworks/Rust/water-http/water-http-db.dockerfile @@ -0,0 +1,13 @@ +FROM rust:latest + +RUN apt-get update -yqq && apt-get install -yqq cmake g++ + +ADD ./ /water +WORKDIR /water + +RUN cargo clean +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin water-http --features db + +EXPOSE 8080 + +CMD ./target/release/water-http \ No newline at end of file diff --git a/frameworks/Rust/water-http/water-http-json.dockerfile b/frameworks/Rust/water-http/water-http-json.dockerfile new file mode 100644 index 00000000000..4c457496cec --- /dev/null +++ b/frameworks/Rust/water-http/water-http-json.dockerfile @@ -0,0 +1,13 @@ +FROM rust:latest + +RUN apt-get update -yqq && apt-get install -yqq cmake g++ + +ADD ./ /water +WORKDIR /water + +RUN cargo clean +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin json --features json_plaintext + +EXPOSE 8080 + +CMD ./target/release/json \ No newline at end of file diff --git a/frameworks/Rust/water-http/water-http-plaintext.dockerfile b/frameworks/Rust/water-http/water-http-plaintext.dockerfile new file mode 100644 index 00000000000..ab53eb54496 --- /dev/null +++ b/frameworks/Rust/water-http/water-http-plaintext.dockerfile @@ -0,0 +1,13 @@ +FROM rust:latest + +RUN apt-get update -yqq && apt-get install -yqq cmake g++ + +ADD ./ /water +WORKDIR /water + +RUN cargo clean +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin plaintext --features json_plaintext + +EXPOSE 8080 + +CMD ./target/release/plaintext \ No newline at end of file diff --git a/frameworks/Rust/water-http/water-http.dockerfile b/frameworks/Rust/water-http/water-http.dockerfile new file mode 100644 index 00000000000..5946c8b3821 --- /dev/null +++ b/frameworks/Rust/water-http/water-http.dockerfile @@ -0,0 +1,13 @@ +FROM rust:latest + +RUN apt-get update -yqq && apt-get install -yqq cmake g++ + +ADD ./ /water +WORKDIR /water + +RUN cargo clean +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --bin water-http --features all + +EXPOSE 8080 + +CMD ./target/release/water-http \ No newline at end of file diff --git a/frameworks/Rust/xitca-web/.cargo/config.toml b/frameworks/Rust/xitca-web/.cargo/config.toml index df736010a76..d56cb43d3f5 100644 --- a/frameworks/Rust/xitca-web/.cargo/config.toml +++ b/frameworks/Rust/xitca-web/.cargo/config.toml @@ -1,6 +1,3 @@ [build] rustflags = ["-C", "target-cpu=native", "--cfg", "tokio_unstable"] incremental = false - -[target.wasm32-wasip1-threads] -rustflags = ["-C", "target-feature=+simd128", "--cfg", "tokio_unstable"] diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock old mode 100644 new mode 100755 index 4eb82962d66..395d9b82907 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -3,25 +3,54 @@ version = 4 [[package]] -name = "addr2line" -version = "0.25.1" +name = "ahash" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ - "gimli", + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", ] [[package]] -name = "adler2" -version = "2.0.1" +name = "aho-corasick" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] [[package]] -name = "allocator-api2" -version = "0.2.21" +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "async-trait" @@ -49,21 +78,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link", -] - [[package]] name = "base64" version = "0.22.1" @@ -71,27 +85,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "bb8" -version = "0.9.0" +name = "bit-set" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d8b8e1a22743d9241575c6ba822cf9c8fef34771c86ab7e477a4fbfd254e5" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ - "futures-util", - "parking_lot", - "tokio", + "bit-vec", ] [[package]] -name = "bitflags" -version = "1.3.2" +name = "bit-vec" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" -version = "2.9.4" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "block-buffer" @@ -108,6 +120,12 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + [[package]] name = "byteorder" version = "1.5.0" @@ -116,15 +134,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "cc" -version = "1.2.40" +version = "1.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d05d92f4b1fd76aad469d46cdd858ca761576082cd37df81416691e50199fb" +checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" dependencies = [ "find-msvc-tools", "shlex", @@ -132,9 +150,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "core_affinity" @@ -158,9 +176,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -203,39 +221,35 @@ dependencies = [ [[package]] name = "diesel" -version = "2.3.2" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8496eeb328dce26ee9d9b73275d396d9bddb433fa30106cf6056dd8c3c2764c" +checksum = "0c415189028b232660655e4893e8bc25ca7aee8e96888db66d9edb400535456a" dependencies = [ - "bitflags 2.9.4", + "bitflags", "byteorder", "diesel_derives", "downcast-rs", "itoa", "pq-sys", - "r2d2", ] [[package]] name = "diesel-async" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c69eded9cb72c7e112505caec23da00149d4dd49f4c96b3c83b2b63f0aa3da5f" +checksum = "13096fb8dae53f2d411c4b523bec85f45552ed3044a2ab4d85fb2092d9cb4f34" dependencies = [ - "bb8", "diesel", "futures-core", "futures-util", "scoped-futures", - "tokio", - "tokio-postgres", ] [[package]] name = "diesel_derives" -version = "2.3.3" +version = "2.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09af0e983035368439f1383011cd87c46f41da81d0f21dc3727e2857d5a43c8e" +checksum = "8587cbca3c929fb198e7950d761d31ca72b80aa6e07c1b7bec5879d187720436" dependencies = [ "diesel_table_macro_syntax", "dsl_auto_type", @@ -264,6 +278,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "downcast-rs" version = "2.0.2" @@ -303,19 +328,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] -name = "find-msvc-tools" -version = "0.1.3" +name = "faststr" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3" +checksum = "baec6a0289d7f1fe5665586ef7340af82e3037207bef60f5785e57569776f0c8" +dependencies = [ + "bytes", + "rkyv", + "serde", + "simdutf8", +] [[package]] -name = "float-cmp" -version = "0.10.0" +name = "find-msvc-tools" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" -dependencies = [ - "num-traits", -] +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] name = "fnv" @@ -323,12 +351,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" - [[package]] name = "form_urlencoded" version = "1.2.2" @@ -338,16 +360,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - [[package]] name = "futures-core" version = "0.3.31" @@ -377,7 +389,6 @@ dependencies = [ "futures-task", "pin-project-lite", "pin-utils", - "slab", ] [[package]] @@ -392,42 +403,38 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.3" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "r-efi", - "wasi 0.14.7+wasi-0.2.4", + "wasi", ] [[package]] -name = "gimli" -version = "0.32.3" +name = "getrandom" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] [[package]] -name = "halfbrown" -version = "0.4.0" +name = "hashbrown" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ed2f2edad8a14c8186b847909a41fbb9c3eafa44f88bd891114ed5019da09" -dependencies = [ - "hashbrown", - "serde", -] +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" [[package]] name = "hashbrown" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "heck" @@ -452,12 +459,11 @@ dependencies = [ [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -473,6 +479,87 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -480,22 +567,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] -name = "io-uring" -version = "0.6.4" +name = "idna" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595a0399f411a508feb2ec1e970a4a30c249351e30208960d58298de8660b0e5" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ - "bitflags 1.3.2", - "libc", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "index_vec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44faf5bb8861a9c72e20d3fb0fdbd59233e43056e2b80475ab0aacdc2e781355" + +[[package]] +name = "indexmap" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", ] [[package]] name = "io-uring" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +checksum = "fdd7bddefd0a8833b88a4b68f90dae22c7450d11b354198baee3874fd811b344" dependencies = [ - "bitflags 2.9.4", + "bitflags", "cfg-if", "libc", ] @@ -514,19 +628,25 @@ checksum = "9028f49264629065d057f340a86acb84867925865f73bbf8d47b4d149a7e88b8" [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" -version = "0.2.176" +version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" [[package]] name = "libmimalloc-sys" @@ -539,15 +659,10 @@ dependencies = [ ] [[package]] -name = "libredox" -version = "0.1.10" +name = "litemap" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" -dependencies = [ - "bitflags 2.9.4", - "libc", - "redox_syscall", -] +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" @@ -558,12 +673,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "log" -version = "0.4.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" - [[package]] name = "md-5" version = "0.10.6" @@ -590,23 +699,34 @@ dependencies = [ ] [[package]] -name = "miniz_oxide" -version = "0.8.9" +name = "mio" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ - "adler2", + "libc", + "wasi", + "windows-sys 0.61.2", ] [[package]] -name = "mio" -version = "1.0.4" +name = "munge" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "5e17401f259eba956ca16491461b6e8f72913a0a114e39736ce404410f915a0c" dependencies = [ - "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys", + "munge_macro", +] + +[[package]] +name = "munge_macro" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -628,15 +748,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -672,25 +783,6 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" -[[package]] -name = "phf" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" -dependencies = [ - "phf_shared", - "serde", -] - -[[package]] -name = "phf_shared" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" -dependencies = [ - "siphasher", -] - [[package]] name = "pin-project-lite" version = "0.2.16" @@ -709,6 +801,16 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "pluralizer" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e4616e94b67b8b61846ea69d4bf041a62147d569d16f437689229e2677d38c" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "postgres-protocol" version = "0.6.9" @@ -722,22 +824,31 @@ dependencies = [ "hmac", "md-5", "memchr", - "rand", + "rand 0.9.2", "sha2", "stringprep", ] [[package]] name = "postgres-types" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a120daaabfcb0e324d5bf6e411e9222994cb3795c79943a0ef28ed27ea76e4" +checksum = "ef4605b7c057056dd35baeb6ac0c0338e4975b1f2bef0f65da953285eb007095" dependencies = [ "bytes", "fallible-iterator", "postgres-protocol", ] +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -749,9 +860,9 @@ dependencies = [ [[package]] name = "pq-sys" -version = "0.7.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "412a4cb9e93795c0594dab7c1c4ec1c8b42b514e1baf6e9f63d14aa376e5bd04" +checksum = "574ddd6a267294433f140b02a726b0640c43cf7c6f717084684aaa3b285aba61" dependencies = [ "libc", "pkg-config", @@ -760,18 +871,38 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] +[[package]] +name = "ptr_meta" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "quote" -version = "1.0.41" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -783,14 +914,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] -name = "r2d2" -version = "0.8.10" +name = "rancor" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +checksum = "a063ea72381527c2a0561da9c80000ef822bdd7c3241b1cc1b12100e3df081ee" dependencies = [ - "log", - "parking_lot", - "scheduled-thread-pool", + "ptr_meta", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", ] [[package]] @@ -799,8 +939,18 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "rand_chacha", - "rand_core", + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", ] [[package]] @@ -810,7 +960,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", ] [[package]] @@ -819,7 +978,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom", + "getrandom 0.3.4", ] [[package]] @@ -828,7 +987,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.4", + "bitflags", ] [[package]] @@ -852,41 +1011,90 @@ dependencies = [ ] [[package]] -name = "rustc-demangle" -version = "0.1.26" +name = "regex" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] [[package]] -name = "rustversion" -version = "1.0.22" +name = "regex-automata" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] -name = "ryu" -version = "1.0.20" +name = "regex-syntax" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] -name = "sailfish" -version = "0.10.0" +name = "rend" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40efbac4e16ca6b1a5706348ada4d8b67d7b417ac2001aa6c4ae092511bb1763" -dependencies = [ - "itoap", - "ryu", - "version_check", -] +checksum = "cadadef317c2f20755a64d7fdc48f9e7178ee6b0e1f7fce33fa60f1d68a276e6" [[package]] -name = "scheduled-thread-pool" -version = "0.2.7" +name = "rkyv" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" +checksum = "35a640b26f007713818e9a9b65d34da1cf58538207b052916a83d80e43f3ffa4" dependencies = [ - "parking_lot", + "bytes", + "hashbrown 0.15.5", + "indexmap", + "munge", + "ptr_meta", + "rancor", + "rend", + "rkyv_derive", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd83f5f173ff41e00337d97f6572e416d022ef8a19f371817259ae960324c482" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "sailfish" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bd7299cb39e7e0d9350a2f4ec0c0f2a98de9608ada54983c3c30f4d55051b8" +dependencies = [ + "itoap", + "ryu", + "version_check", ] [[package]] @@ -978,66 +1186,19 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" dependencies = [ "libc", ] -[[package]] -name = "simd-json" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4255126f310d2ba20048db6321c81ab376f6a6735608bf11f0785c41f01f64e3" -dependencies = [ - "halfbrown", - "ref-cast", - "serde", - "serde_json", - "simdutf8", - "value-trait", -] - -[[package]] -name = "simd-json-derive" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8582b571efbbb6d89a2d3807c283a42de7e2a5d92fa09c6498ac17abb3f58220" -dependencies = [ - "itoa", - "ryu", - "simd-json", - "simd-json-derive-int", - "thiserror", - "value-trait", -] - -[[package]] -name = "simd-json-derive-int" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e60b40db276e0d588874b1317a1603e0795ef38889e09111d841a9845623efd0" -dependencies = [ - "proc-macro2", - "quote", - "simd-json", - "syn", - "thiserror", -] - [[package]] name = "simdutf8" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" -[[package]] -name = "siphasher" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" - [[package]] name = "slab" version = "0.4.11" @@ -1052,22 +1213,67 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.4.10" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "winapi", + "windows-sys 0.60.2", ] [[package]] -name = "socket2" -version = "0.6.0" +name = "sonic-number" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "a8a74044c092f4f43ca7a6cfd62854cf9fb5ac8502b131347c990bf22bef1dfe" dependencies = [ - "libc", - "windows-sys", + "cfg-if", +] + +[[package]] +name = "sonic-rs" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4425ea8d66ec950e0a8f2ef52c766cc3d68d661d9a0845c353c40833179fd866" +dependencies = [ + "ahash", + "bumpalo", + "bytes", + "cfg-if", + "faststr", + "itoa", + "ref-cast", + "ryu", + "serde", + "simdutf8", + "sonic-number", + "sonic-simd", + "thiserror", +] + +[[package]] +name = "sonic-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5707edbfb34a40c9f2a55fa09a49101d9fec4e0cc171ce386086bd9616f34257" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "std-util" +version = "0.1.0" +source = "git+https://github.com/fakeshadow/toasty?branch=engine#2132c89dfd7a4698cdaaa85888c016b97c01471a" +dependencies = [ + "heck", + "pluralizer", + "rand 0.8.5", ] [[package]] @@ -1095,15 +1301,26 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.106" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thiserror" version = "2.0.17" @@ -1124,6 +1341,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.10.0" @@ -1139,84 +1366,127 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "toasty" +version = "0.1.0" +source = "git+https://github.com/fakeshadow/toasty?branch=engine#2132c89dfd7a4698cdaaa85888c016b97c01471a" +dependencies = [ + "anyhow", + "async-stream", + "by_address", + "index_vec", + "indexmap", + "toasty-core", + "toasty-macros", + "tokio", + "tokio-stream", + "url", + "uuid", +] + +[[package]] +name = "toasty-codegen" +version = "0.1.0" +source = "git+https://github.com/fakeshadow/toasty?branch=engine#2132c89dfd7a4698cdaaa85888c016b97c01471a" +dependencies = [ + "proc-macro2", + "quote", + "std-util", + "syn", +] + +[[package]] +name = "toasty-core" +version = "0.1.0" +source = "git+https://github.com/fakeshadow/toasty?branch=engine#2132c89dfd7a4698cdaaa85888c016b97c01471a" +dependencies = [ + "anyhow", + "async-trait", + "bit-set", + "indexmap", + "std-util", + "tokio-stream", + "uuid", +] + +[[package]] +name = "toasty-macros" +version = "0.1.0" +source = "git+https://github.com/fakeshadow/toasty?branch=engine#2132c89dfd7a4698cdaaa85888c016b97c01471a" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "toasty-codegen", + "toasty-core", +] + +[[package]] +name = "toasty-sql" +version = "0.1.0" +source = "git+https://github.com/fakeshadow/toasty?branch=engine#2132c89dfd7a4698cdaaa85888c016b97c01471a" +dependencies = [ + "anyhow", + "toasty-core", +] + [[package]] name = "tokio" -version = "1.47.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring 0.7.10", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2 0.6.0", - "windows-sys", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", ] [[package]] -name = "tokio-postgres" -version = "0.7.14" +name = "tokio-macros" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156efe7fff213168257853e1dfde202eed5f487522cbbbf7d219941d753d853" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ - "async-trait", - "byteorder", - "bytes", - "fallible-iterator", - "futures-channel", - "futures-util", - "log", - "parking_lot", - "percent-encoding", - "phf", - "pin-project-lite", - "postgres-protocol", - "postgres-types", - "rand", - "socket2 0.6.0", - "tokio", - "tokio-util", - "whoami", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "tokio-uring" -version = "0.5.0" +name = "tokio-stream" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "748482e3e13584a34664a710168ad5068e8cb1d968aa4ffa887e83ca6dd27967" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ - "bytes", - "futures-util", - "io-uring 0.6.4", - "libc", - "slab", - "socket2 0.4.10", + "futures-core", + "pin-project-lite", "tokio", ] [[package]] -name = "tokio-util" -version = "0.7.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +name = "tokio-uring" +version = "0.5.1" +source = "git+http://github.com/fakeshadow/tokio-uring?rev=97d9a98#97d9a988704b5466809633b3ca6ba07acba3f38b" dependencies = [ "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", + "io-uring", + "libc", + "slab", + "socket2", "tokio", ] [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" dependencies = [ "pin-project-lite", "tracing-core", @@ -1224,9 +1494,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" [[package]] name = "typenum" @@ -1242,35 +1512,53 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] -name = "value-trait" -version = "0.12.0" +name = "url" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d93718a3c9696765926b8acd98588727b285ae969901f76fcf1b6cad5d5d9" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ - "float-cmp", - "halfbrown", - "itoa", - "ryu", + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +dependencies = [ + "getrandom 0.3.4", + "js-sys", + "rand 0.9.2", + "wasm-bindgen", ] [[package]] @@ -1291,15 +1579,6 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasi" -version = "0.14.7+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" -dependencies = [ - "wasip2", -] - [[package]] name = "wasip2" version = "1.0.1+wasi-0.2.4" @@ -1309,17 +1588,11 @@ dependencies = [ "wit-bindgen", ] -[[package]] -name = "wasite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" - [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", @@ -1328,25 +1601,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1354,47 +1613,26 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] -[[package]] -name = "web-sys" -version = "0.3.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "whoami" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" -dependencies = [ - "libredox", - "wasite", - "web-sys", -] - [[package]] name = "winapi" version = "0.3.9" @@ -1425,19 +1663,29 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" -version = "0.59.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" -version = "0.52.6" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ + "windows-link", "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", @@ -1450,51 +1698,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "wit-bindgen" @@ -1502,10 +1750,16 @@ version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + [[package]] name = "xitca-codegen" version = "0.4.0" -source = "git+http://github.com/HFQR/xitca-web?rev=7c22b4a#7c22b4a8a23500368be2c9e30e81bd8fb39ebc12" +source = "git+http://github.com/HFQR/xitca-web?rev=83b4a60#83b4a607a9a704a4286dd190209e567316589afc" dependencies = [ "quote", "syn", @@ -1514,7 +1768,7 @@ dependencies = [ [[package]] name = "xitca-http" version = "0.7.1" -source = "git+http://github.com/HFQR/xitca-web?rev=7c22b4a#7c22b4a8a23500368be2c9e30e81bd8fb39ebc12" +source = "git+http://github.com/HFQR/xitca-web?rev=83b4a60#83b4a607a9a704a4286dd190209e567316589afc" dependencies = [ "futures-core", "http", @@ -1522,7 +1776,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.6.0", + "socket2", "tokio", "tokio-uring", "tracing", @@ -1547,7 +1801,7 @@ dependencies = [ [[package]] name = "xitca-postgres" version = "0.3.0" -source = "git+http://github.com/HFQR/xitca-web?rev=7c22b4a#7c22b4a8a23500368be2c9e30e81bd8fb39ebc12" +source = "git+http://github.com/HFQR/xitca-web?rev=83b4a60#83b4a607a9a704a4286dd190209e567316589afc" dependencies = [ "fallible-iterator", "futures-core", @@ -1563,7 +1817,7 @@ dependencies = [ [[package]] name = "xitca-postgres-diesel" version = "0.2.0" -source = "git+https://github.com/fakeshadow/xitca-postgres-diesel?rev=8ce4e5b#8ce4e5bb138765bc1780642adfefc4d3b8427bb7" +source = "git+https://github.com/fakeshadow/xitca-postgres-diesel?rev=fb5dcba#fb5dcba5a89164a880a3e82d62dcb3ae5e99ae6e" dependencies = [ "diesel", "diesel-async", @@ -1573,6 +1827,21 @@ dependencies = [ "xitca-postgres", ] +[[package]] +name = "xitca-postgres-toasty" +version = "0.1.0" +source = "git+https://github.com/fakeshadow/xitca-postgres-toasty?rev=04bedb8#04bedb8641a13b61f13c85a1fd0b8318dd5454a8" +dependencies = [ + "anyhow", + "futures-core", + "pin-project-lite", + "postgres-types", + "toasty-core", + "toasty-sql", + "tokio", + "xitca-postgres", +] + [[package]] name = "xitca-router" version = "0.3.0" @@ -1585,9 +1854,9 @@ dependencies = [ [[package]] name = "xitca-server" version = "0.5.0" -source = "git+http://github.com/HFQR/xitca-web?rev=7c22b4a#7c22b4a8a23500368be2c9e30e81bd8fb39ebc12" +source = "git+http://github.com/HFQR/xitca-web?rev=83b4a60#83b4a607a9a704a4286dd190209e567316589afc" dependencies = [ - "socket2 0.6.0", + "socket2", "tokio", "tokio-uring", "tracing", @@ -1599,7 +1868,7 @@ dependencies = [ [[package]] name = "xitca-service" version = "0.3.0" -source = "git+http://github.com/HFQR/xitca-web?rev=7c22b4a#7c22b4a8a23500368be2c9e30e81bd8fb39ebc12" +source = "git+http://github.com/HFQR/xitca-web?rev=83b4a60#83b4a607a9a704a4286dd190209e567316589afc" [[package]] name = "xitca-unsafe-collection" @@ -1622,18 +1891,19 @@ dependencies = [ "futures-util", "httparse", "mimalloc", - "rand", + "rand 0.9.2", "sailfish", - "serde", + "serde_core", "serde_json", - "simd-json", - "simd-json-derive", + "sonic-rs", + "toasty", "tokio", "tokio-uring", "xitca-http", "xitca-io", "xitca-postgres", "xitca-postgres-diesel", + "xitca-postgres-toasty", "xitca-server", "xitca-service", "xitca-unsafe-collection", @@ -1643,7 +1913,7 @@ dependencies = [ [[package]] name = "xitca-web" version = "0.7.1" -source = "git+http://github.com/HFQR/xitca-web?rev=7c22b4a#7c22b4a8a23500368be2c9e30e81bd8fb39ebc12" +source = "git+http://github.com/HFQR/xitca-web?rev=83b4a60#83b4a607a9a704a4286dd190209e567316589afc" dependencies = [ "futures-core", "pin-project-lite", @@ -1658,20 +1928,97 @@ dependencies = [ "xitca-unsafe-collection", ] +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zerocopy" -version = "0.8.27" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.27" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml old mode 100644 new mode 100755 index dd95fc7b92a..153519e5575 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -6,30 +6,30 @@ edition = "2024" [[bin]] name = "xitca-web" path = "./src/main.rs" -required-features = ["io-uring", "pg", "router", "template"] +required-features = ["io-uring", "json", "pg", "router", "template"] [[bin]] -name = "xitca-web-unrealistic" -path = "./src/main_unrealistic.rs" -required-features = ["perf", "pg", "template"] +name = "xitca-web-barebone" +path = "./src/main_barebone.rs" +required-features = ["perf", "perf-json", "pg", "template"] [[bin]] -name = "xitca-web-orm" +name = "xitca-web-diesel" path = "./src/main_orm.rs" -required-features = ["pg-orm-async", "template", "web-codegen"] +required-features = ["diesel", "perf", "template", "web-codegen"] [[bin]] -name = "xitca-web-sync" -path = "./src/main_sync.rs" -required-features = ["pg-orm", "template", "web-codegen"] +name = "xitca-web-toasty" +path = "./src/main_orm.rs" +required-features = ["perf", "template", "toasty", "web-codegen"] [features] # pg client optional pg = ["dep:xitca-postgres"] # diesel orm optional -pg-orm = ["diesel/r2d2"] -# diesel async orm optional -pg-orm-async = ["dep:diesel", "dep:diesel-async", "dep:xitca-postgres-diesel", "dep:futures-util"] +diesel = ["dep:diesel", "dep:diesel-async", "dep:xitca-postgres-diesel", "dep:futures-util"] +# toasty orm optional +toasty = ["dep:toasty", "dep:xitca-postgres-toasty", "futures-util/alloc"] # http router optional router = ["xitca-http/router"] # web optional @@ -41,7 +41,11 @@ template = ["dep:sailfish"] # io-uring optional io-uring = ["dep:tokio-uring", "xitca-http/io-uring", "xitca-server/io-uring"] # unrealistic performance optimization -perf = ["dep:core_affinity", "dep:mimalloc", "tokio/parking_lot", "simd-json", "simd-json-derive"] +perf = ["dep:core_affinity", "dep:mimalloc", "tokio/parking_lot"] +# regular json serializer +json = ["serde_json"] +# performance optimization json serializer +perf-json = ["sonic-rs"] [dependencies] xitca-http = "0.7" @@ -52,8 +56,7 @@ xitca-unsafe-collection = "0.2" atoi = "2" httparse = "1" -serde = { version = "1" } -serde_json = { version = "1" } +serde_core = { version = "1" } # web optional xitca-web = { version = "0.7", features = ["json"], optional = true } @@ -61,14 +64,16 @@ xitca-web = { version = "0.7", features = ["json"], optional = true } # raw-pg optional xitca-postgres = { version = "0.3", optional = true } -# orm optional +# diesel orm optional diesel = { version = "2", features = ["postgres"], optional = true } - -# orm async optional -diesel-async = { version = "0.7", features = ["bb8", "postgres"], optional = true } -xitca-postgres-diesel = { version = "0.2", optional = true } +diesel-async = { version = "0.7", optional = true } +xitca-postgres-diesel = { version = "0.2", default-features = false, optional = true } futures-util = { version = "0.3", default-features = false, optional = true } +# toasty orm optional +xitca-postgres-toasty = { version = "0.1", optional = true } +toasty = { version = "0.1", optional = true } + # template optional sailfish = { version = "0.10", default-features = false, features = ["perf-inline"], optional = true } @@ -78,12 +83,14 @@ tokio-uring = { version = "0.5", optional = true } # perf optional core_affinity = { version = "0.8.1", optional = true } mimalloc = { version = "0.1", default-features = false, optional = true } -simd-json = { version = "0.17", optional = true } -simd-json-derive = { version = "0.18", default-features = false, optional = true } + +# json optioanl +serde_json = { version = "1", optional = true } +sonic-rs = { version = "0.5.6", optional = true } futures-core = { version = "0.3", default-features = false } rand = { version = "0.9", features = ["os_rng", "small_rng"], default-features = false } -tokio = "1.41" +tokio = "1.48" [profile.release] lto = true @@ -92,11 +99,18 @@ codegen-units = 1 panic = "abort" [patch.crates-io] -xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "8ce4e5b" } - -xitca-codegen = { git = "http://github.com/HFQR/xitca-web", rev = "7c22b4a" } -xitca-http = { git = "http://github.com/HFQR/xitca-web", rev = "7c22b4a" } -xitca-postgres = { git = "http://github.com/HFQR/xitca-web", rev = "7c22b4a" } -xitca-server = { git = "http://github.com/HFQR/xitca-web", rev = "7c22b4a" } -xitca-service = { git = "http://github.com/HFQR/xitca-web", rev = "7c22b4a" } -xitca-web = { git = "http://github.com/HFQR/xitca-web", rev = "7c22b4a" } +xitca-postgres-diesel = { git = "https://github.com/fakeshadow/xitca-postgres-diesel", rev = "fb5dcba" } +xitca-postgres-toasty = { git = "https://github.com/fakeshadow/xitca-postgres-toasty", rev = "04bedb8" } + +# personal fork for efficient toasty engine fine tuned with pipelined xitca-postgres client +toasty = { git = "https://github.com/fakeshadow/toasty", branch = "engine" } +toasty-core = { git = "https://github.com/fakeshadow/toasty", branch = "engine" } +toasty-sql = { git = "https://github.com/fakeshadow/toasty", branch = "engine" } +tokio-uring = { git = "http://github.com/fakeshadow/tokio-uring", rev = "97d9a98" } + +xitca-codegen = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" } +xitca-http = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" } +xitca-postgres = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" } +xitca-server = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" } +xitca-service = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" } +xitca-web = { git = "http://github.com/HFQR/xitca-web", rev = "83b4a60" } diff --git a/frameworks/Rust/xitca-web/benchmark_config.json b/frameworks/Rust/xitca-web/benchmark_config.json index c60cf0bc3b2..b1b96249711 100755 --- a/frameworks/Rust/xitca-web/benchmark_config.json +++ b/frameworks/Rust/xitca-web/benchmark_config.json @@ -24,7 +24,7 @@ "notes": "", "versus": "" }, - "unrealistic": { + "barebone": { "json_url": "/json", "plaintext_url": "/plaintext", "db_url": "/db", @@ -32,7 +32,7 @@ "query_url": "/queries?q=", "update_url": "/updates?q=", "port": 8080, - "approach": "Stripped", + "approach": "Realistic", "classification": "Platform", "database": "Postgres", "framework": "xitca-web", @@ -42,13 +42,11 @@ "webserver": "xitca-server", "os": "Linux", "database_os": "Linux", - "display_name": "xitca-web [unrealistic]", + "display_name": "xitca-web [barebone]", "notes": "", "versus": "" }, - "orm": { - "json_url": "/json", - "plaintext_url": "/plaintext", + "diesel": { "db_url": "/db", "fortune_url": "/fortunes", "query_url": "/queries?q=", @@ -64,20 +62,18 @@ "webserver": "xitca-server", "os": "linux", "database_os": "linux", - "display_name": "xitca-web [orm]", + "display_name": "xitca-web [diesel]", "notes": "", "versus": "" }, - "sync": { - "json_url": "/json", - "plaintext_url": "/plaintext", + "toasty": { "db_url": "/db", "fortune_url": "/fortunes", "query_url": "/queries?q=", "update_url": "/updates?q=", "port": 8080, "approach": "realistic", - "classification": "micro", + "classification": "fullstack", "database": "postgres", "framework": "xitca-web", "language": "rust", @@ -86,7 +82,7 @@ "webserver": "xitca-server", "os": "linux", "database_os": "linux", - "display_name": "xitca-web [sync]", + "display_name": "xitca-web [toasty]", "notes": "", "versus": "" } diff --git a/frameworks/Rust/xitca-web/src/db.rs b/frameworks/Rust/xitca-web/src/db.rs old mode 100644 new mode 100755 index b35affdc61b..7a380357cd5 --- a/frameworks/Rust/xitca-web/src/db.rs +++ b/frameworks/Rust/xitca-web/src/db.rs @@ -1,30 +1,24 @@ #[path = "./db_util.rs"] mod db_util; -use core::cell::RefCell; - -use xitca_postgres::{Execute, iter::AsyncLendingIterator, pipeline::Pipeline, pool::Pool, statement::Statement}; +use xitca_postgres::{Execute, iter::AsyncLendingIterator, pool::Pool}; use super::{ ser::{Fortune, Fortunes, World}, - util::{DB_URL, HandleResult}, + util::{DB_URL, HandleResult, Rand}, }; -use db_util::{FORTUNE_STMT, Shared, WORLD_STMT, not_found, sort_update_params, update_query_from_num}; +use db_util::{FORTUNE_STMT, UPDATE_STMT, WORLD_STMT, not_found}; pub struct Client { pool: Pool, - shared: RefCell, - updates: Box<[Box]>, + rng: core::cell::RefCell, } pub async fn create() -> HandleResult { Ok(Client { pool: Pool::builder(DB_URL).capacity(1).build()?, - shared: Default::default(), - updates: core::iter::once(Box::from("")) - .chain((1..=500).map(update_query_from_num)) - .collect(), + rng: Default::default(), }) } @@ -32,29 +26,31 @@ impl Client { pub async fn get_world(&self) -> HandleResult { let mut conn = self.pool.get().await?; let stmt = WORLD_STMT.execute(&mut conn).await?; - let id = self.shared.borrow_mut().0.gen_id(); + let id = self.rng.borrow_mut().gen_id(); let mut res = stmt.bind([id]).query(&conn.consume()).await?; let row = res.try_next().await?.ok_or_else(not_found)?; Ok(World::new(row.get(0), row.get(1))) } pub async fn get_worlds(&self, num: u16) -> HandleResult> { - let len = num as usize; - let mut conn = self.pool.get().await?; let stmt = WORLD_STMT.execute(&mut conn).await?; - let mut res = { - let (ref mut rng, ref mut buf) = *self.shared.borrow_mut(); - let mut pipe = Pipeline::with_capacity_from_buf(len, buf); - (0..num).try_for_each(|_| stmt.bind([rng.gen_id()]).query(&mut pipe))?; - pipe.query(&conn.consume())? - }; + let get = self + .rng + .borrow_mut() + .gen_multi() + .take(num as _) + .map(|id| stmt.bind([id]).query(&conn)) + .collect::>(); - let mut worlds = Vec::with_capacity(len); + drop(conn); - while let Some(mut item) = res.try_next().await? { - let row = item.try_next().await?.ok_or_else(not_found)?; + let mut worlds = Vec::with_capacity(num as _); + + for get in get { + let mut res = get.await?; + let row = res.try_next().await?.ok_or_else(not_found)?; worlds.push(World::new(row.get(0), row.get(1))); } @@ -62,56 +58,50 @@ impl Client { } pub async fn update(&self, num: u16) -> HandleResult> { - let len = num as usize; - - let update = self.updates.get(len).ok_or("request num is out of range")?; let mut conn = self.pool.get().await?; let world_stmt = WORLD_STMT.execute(&mut conn).await?; - let update_stmt = Statement::named(update, &[]).execute(&mut conn).await?; - - let mut params = Vec::with_capacity(len); - - let mut res = { - let (ref mut rng, ref mut buf) = *self.shared.borrow_mut(); - let mut pipe = Pipeline::with_capacity_from_buf(len + 1, buf); - (0..num).try_for_each(|_| { - let w_id = rng.gen_id(); - let r_id = rng.gen_id(); - params.push([w_id, r_id]); - world_stmt.bind([w_id]).query(&mut pipe) - })?; - update_stmt.bind(sort_update_params(¶ms)).query(&mut pipe)?; - pipe.query(&conn.consume())? + let update_stmt = UPDATE_STMT.execute(&mut conn).await?; + + let (get, update, worlds) = { + let mut rng = self.rng.borrow_mut(); + let mut ids = rng.gen_multi().take(num as _).collect::>(); + ids.sort(); + + let (get, rngs, worlds) = ids + .iter() + .cloned() + .zip(rng.gen_multi()) + .map(|(id, rand)| { + let get = world_stmt.bind([id]).query(&conn); + (get, rand, World::new(id, rand)) + }) + .collect::<(Vec<_>, Vec<_>, Vec<_>)>(); + + let update = update_stmt.bind([&ids, &rngs]).query(&conn.consume()); + + (get, update, worlds) }; - let mut worlds = Vec::with_capacity(len); - - let mut r_ids = params.into_iter(); - - while let Some(mut item) = res.try_next().await? { - while let Some(row) = item.try_next().await? { - let r_id = r_ids.next().unwrap()[1]; - worlds.push(World::new(row.get(0), r_id)) - } + for fut in get { + let _rand = fut.await?.try_next().await?.ok_or_else(not_found)?.get::(1); } + update.await?; + Ok(worlds) } pub async fn tell_fortune(&self) -> HandleResult { - let mut items = Vec::with_capacity(32); - items.push(Fortune::new(0, "Additional fortune added at request time.")); + let mut fortunes = Vec::with_capacity(16); let mut conn = self.pool.get().await?; let stmt = FORTUNE_STMT.execute(&mut conn).await?; let mut res = stmt.query(&conn.consume()).await?; while let Some(row) = res.try_next().await? { - items.push(Fortune::new(row.get(0), row.get::(1))); + fortunes.push(Fortune::new(row.get(0), row.get::(1))); } - items.sort_by(|it, next| it.message.cmp(&next.message)); - - Ok(Fortunes::new(items)) + Ok(Fortunes::new(fortunes)) } } diff --git a/frameworks/Rust/xitca-web/src/db_diesel.rs b/frameworks/Rust/xitca-web/src/db_diesel.rs old mode 100644 new mode 100755 index f187afc54e1..19231abee85 --- a/frameworks/Rust/xitca-web/src/db_diesel.rs +++ b/frameworks/Rust/xitca-web/src/db_diesel.rs @@ -1,104 +1,133 @@ -#[path = "./db_util.rs"] -mod db_util; - -use std::{ - io, - sync::{Arc, Mutex}, -}; - -use diesel::{prelude::*, r2d2}; +use diesel::prelude::*; +use diesel_async::{AsyncConnection, RunQueryDsl}; +use futures_util::future::{TryFutureExt, TryJoinAll, try_join}; +use xitca_postgres_diesel::AsyncPgConnection; use crate::{ - ser::{Fortune, Fortunes, World}, + ser::{Fortunes, World}, util::{DB_URL, HandleResult, Rand}, }; -use db_util::{not_found, update_query_from_ids}; - -pub type Pool = Arc<_Pool>; - -pub struct _Pool { - pool: r2d2::Pool>, - rng: Mutex, +pub struct Pool { + pool: AsyncPgConnection, + rng: core::cell::RefCell, } -pub fn create() -> io::Result> { - r2d2::Builder::new() - .max_size(100) - .min_idle(Some(100)) - .test_on_check_out(false) - .idle_timeout(None) - .max_lifetime(None) - .build(r2d2::ConnectionManager::new(DB_URL)) - .map_err(io::Error::other) - .map(|pool| { - Arc::new(_Pool { - pool, - rng: Mutex::new(Rand::default()), - }) +impl Pool { + pub async fn create() -> HandleResult { + let pool = AsyncPgConnection::establish(DB_URL).await?; + + Ok(Self { + pool, + rng: Default::default(), }) -} + } -impl _Pool { - pub fn get_world(&self) -> HandleResult { - use crate::schema::world::dsl::*; + pub async fn get_world(&self) -> HandleResult { + { + use schema::world::dsl::*; - let w_id = self.rng.lock().unwrap().gen_id(); - let mut conn = self.pool.get()?; - world.filter(id.eq(w_id)).load(&mut conn)?.pop().ok_or_else(not_found) + let w_id = self.rng.borrow_mut().gen_id(); + world.filter(id.eq(w_id)).first(&mut &self.pool).map_err(Into::into) + } + .await } - pub fn get_worlds(&self, num: u16) -> HandleResult> { - use crate::schema::world::dsl::*; - - let mut conn = self.pool.get()?; - core::iter::repeat_with(|| { - let w_id = self.rng.lock().unwrap().gen_id(); - world.filter(id.eq(w_id)).load(&mut conn)?.pop().ok_or_else(not_found) - }) - .take(num as _) - .collect() + pub async fn get_worlds(&self, num: u16) -> HandleResult> { + { + use schema::world::dsl::*; + + self.rng + .borrow_mut() + .gen_multi() + .take(num as _) + .map(|w_id| world.filter(id.eq(w_id)).first(&mut &self.pool).map_err(Into::into)) + .collect::>() + } + .await } - pub fn update(&self, num: u16) -> HandleResult> { - use crate::schema::world::dsl::*; + pub async fn update(&self, num: u16) -> HandleResult> { + { + use schema::world::dsl::*; + + let mut rng = self.rng.borrow_mut(); + let mut params = Vec::with_capacity(num as _); + + let get = rng + .clone() + .gen_multi() + .take(num as _) + .zip(rng.gen_multi()) + .map(|(w_id, rng)| { + let get = world.filter(id.eq(w_id)).first::(&mut &self.pool); + + params.push((w_id, rng)); + + async move { + let mut w = get.await?; + w.randomnumber = rng; + HandleResult::Ok(w) + } + }) + .collect::>(); + + let sql = update_query_from_ids(params); + let update = diesel::sql_query(sql).execute(&mut &self.pool).map_err(Into::into); + + try_join(get, update) + } + .await + .map(|(worlds, _)| worlds) + } - let mut rngs = { - let mut rng = self.rng.lock().unwrap(); - (0..num).map(|_| (rng.gen_id(), rng.gen_id())).collect::>() - }; + pub async fn tell_fortune(&self) -> HandleResult { + { + use schema::fortune::dsl::*; - rngs.sort_by(|(a, _), (b, _)| a.cmp(b)); + fortune.load(&mut &self.pool).map_err(Into::into) + } + .await + .map(Fortunes::new) + } +} - let update_sql = update_query_from_ids(&rngs); +mod schema { + diesel::table! { + world (id) { + id -> Integer, + randomnumber -> Integer, + } + } - let mut conn = self.pool.get()?; + diesel::table! { + fortune (id) { + id -> Integer, + message -> Text, + } + } +} - let worlds = rngs - .into_iter() - .map(|(w_id, num)| { - let mut w: World = world.filter(id.eq(w_id)).load(&mut conn)?.pop().ok_or_else(not_found)?; - w.randomnumber = num; - Ok(w) - }) - .collect::>>()?; +// diesel does not support high level bulk update api. use raw sql to bypass the limitation. +// relate discussion: https://github.com/diesel-rs/diesel/discussions/2879 +fn update_query_from_ids(mut rngs: Vec<(i32, i32)>) -> String { + rngs.sort_by(|(a, _), (b, _)| a.cmp(b)); - diesel::sql_query(update_sql).execute(&mut conn)?; + const PREFIX: &str = "UPDATE world SET randomNumber=w.r FROM (VALUES "; + const SUFFIX: &str = ") AS w (i,r) WHERE world.id=w.i"; - Ok(worlds) - } + let mut query = String::from(PREFIX); - pub fn tell_fortune(&self) -> HandleResult { - use crate::schema::fortune::dsl::*; + use core::fmt::Write; + rngs.iter().for_each(|(w_id, num)| { + write!(query, "({}::int,{}::int),", w_id, num).unwrap(); + }); - let mut items = { - let mut conn = self.pool.get()?; - fortune.load(&mut conn)? - }; + if query.ends_with(',') { + query.pop(); + } - items.push(Fortune::new(0, "Additional fortune added at request time.")); - items.sort_by(|it, next| it.message.cmp(&next.message)); + query.push_str(SUFFIX); - Ok(Fortunes::new(items)) - } + query } diff --git a/frameworks/Rust/xitca-web/src/db_diesel_async.rs b/frameworks/Rust/xitca-web/src/db_diesel_async.rs deleted file mode 100644 index edae0afec03..00000000000 --- a/frameworks/Rust/xitca-web/src/db_diesel_async.rs +++ /dev/null @@ -1,122 +0,0 @@ -#[path = "./db_util.rs"] -mod db_util; - -use std::{io, sync::Mutex}; - -use diesel::prelude::*; -use diesel_async::{ - RunQueryDsl, - pooled_connection::{AsyncDieselConnectionManager, bb8}, -}; -use futures_util::{ - future::join, - stream::{FuturesUnordered, TryStreamExt}, -}; -use xitca_postgres_diesel::AsyncPgConnection; - -use crate::{ - ser::{Fortune, Fortunes, World}, - util::{DB_URL, HandleResult, Rand}, -}; - -use db_util::{not_found, update_query_from_ids}; - -pub struct Pool { - pool: bb8::Pool, - rng: Mutex, -} - -pub async fn create() -> io::Result { - bb8::Pool::builder() - .max_size(1) - .min_idle(Some(1)) - .test_on_check_out(false) - .build(AsyncDieselConnectionManager::new(DB_URL)) - .await - .map_err(io::Error::other) - .map(|pool| Pool { - pool, - rng: Mutex::new(Rand::default()), - }) -} - -impl Pool { - pub async fn get_world(&self) -> HandleResult { - use crate::schema::world::dsl::*; - { - let w_id = self.rng.lock().unwrap().gen_id(); - let mut conn = self.pool.get().await?; - world.filter(id.eq(w_id)).load(&mut conn) - } - .await? - .pop() - .ok_or_else(not_found) - } - - pub async fn get_worlds(&self, num: u16) -> HandleResult> { - use crate::schema::world::dsl::*; - { - let mut conn = self.pool.get().await?; - let mut rng = self.rng.lock().unwrap(); - core::iter::repeat_with(|| { - let w_id = rng.gen_id(); - let fut = world.filter(id.eq(w_id)).load(&mut conn); - async { fut.await?.pop().ok_or_else(not_found) } - }) - .take(num as _) - .collect::>() - } - .try_collect() - .await - } - - pub async fn update(&self, num: u16) -> HandleResult> { - use crate::schema::world::dsl::*; - - let (select_res, update_res) = { - let mut conn = self.pool.get().await?; - let mut rng = self.rng.lock().unwrap(); - - let (select, mut rngs) = core::iter::repeat_with(|| { - let w_id = rng.gen_id(); - let num = rng.gen_id(); - - let fut = world.filter(id.eq(w_id)).load::(&mut conn); - let select = async move { - let mut w = fut.await?.pop().ok_or_else(not_found)?; - w.randomnumber = num; - HandleResult::Ok(w) - }; - - (select, (w_id, num)) - }) - .take(num as _) - .collect::<(FuturesUnordered<_>, Vec<_>)>(); - - rngs.sort_by(|(a, _), (b, _)| a.cmp(b)); - - let update = diesel::sql_query(update_query_from_ids(&rngs)).execute(&mut conn); - - join(select.try_collect::>(), update) - } - .await; - - update_res?; - select_res - } - - pub async fn tell_fortune(&self) -> HandleResult { - use crate::schema::fortune::dsl::*; - - let mut items = { - let mut conn = self.pool.get().await?; - fortune.load(&mut conn) - } - .await?; - - items.push(Fortune::new(0, "Additional fortune added at request time.")); - items.sort_by(|it, next| it.message.cmp(&next.message)); - - Ok(Fortunes::new(items)) - } -} diff --git a/frameworks/Rust/xitca-web/src/db_toasty.rs b/frameworks/Rust/xitca-web/src/db_toasty.rs new file mode 100755 index 00000000000..092f483a61b --- /dev/null +++ b/frameworks/Rust/xitca-web/src/db_toasty.rs @@ -0,0 +1,57 @@ +use futures_util::future::try_join_all; +use toasty::Db; + +use crate::{ + ser::{Fortune, Fortunes, World}, + util::{DB_URL, HandleResult, Rand}, +}; + +pub struct Pool { + db: Db, + rng: core::cell::RefCell, +} + +impl Pool { + pub async fn create() -> HandleResult { + let conn = xitca_postgres_toasty::PostgreSQL::connect(DB_URL).await?; + + let db = Db::builder() + .register::() + .register::() + .build(conn) + .await?; + + Ok(Self { + db, + rng: Default::default(), + }) + } + + pub async fn get_world(&self) -> HandleResult { + let id = self.rng.borrow_mut().gen_id(); + World::get_by_id(&self.db, id).await.map_err(Into::into) + } + + pub async fn get_worlds(&self, num: u16) -> HandleResult> { + try_join_all(core::iter::repeat_with(|| self.get_world()).take(num as _)).await + } + + pub async fn update(&self, num: u16) -> HandleResult> { + let mut worlds = self.get_worlds(num).await?; + + try_join_all({ + let mut rng = self.rng.borrow_mut(); + worlds + .iter_mut() + .map(move |world| world.update().randomnumber(rng.gen_id()).exec(&self.db)) + }) + .await?; + + Ok(worlds) + } + + pub async fn tell_fortune(&self) -> HandleResult { + let fortunes = Fortune::all().all(&self.db).await?.collect().await?; + Ok(Fortunes::new(fortunes)) + } +} diff --git a/frameworks/Rust/xitca-web/src/db_unrealistic.rs b/frameworks/Rust/xitca-web/src/db_unrealistic.rs old mode 100644 new mode 100755 index cacd6367656..364e020b3b0 --- a/frameworks/Rust/xitca-web/src/db_unrealistic.rs +++ b/frameworks/Rust/xitca-web/src/db_unrealistic.rs @@ -4,118 +4,104 @@ #[path = "./db_util.rs"] mod db_util; -use std::cell::RefCell; - -use xitca_postgres::{Execute, iter::AsyncLendingIterator, pipeline::Pipeline, statement::Statement}; +use xitca_postgres::{Execute, iter::AsyncLendingIterator, statement::Statement}; use super::{ ser::{Fortune, Fortunes, World}, - util::{DB_URL, HandleResult}, + util::{DB_URL, HandleResult, Rand}, }; -use db_util::{FORTUNE_STMT, Shared, WORLD_STMT, not_found, sort_update_params, update_query_from_num}; +use db_util::{FORTUNE_STMT, UPDATE_STMT, WORLD_STMT, not_found}; pub struct Client { cli: xitca_postgres::Client, - shared: RefCell, + rng: core::cell::RefCell, fortune: Statement, world: Statement, - updates: Box<[Statement]>, + update: Statement, } pub async fn create() -> HandleResult { let (cli, mut drv) = xitca_postgres::Postgres::new(DB_URL).connect().await?; - tokio::task::spawn(tokio::task::unconstrained(async move { + tokio::task::spawn(async move { while drv.try_next().await?.is_some() {} HandleResult::Ok(()) - })); + }); let world = WORLD_STMT.execute(&cli).await?.leak(); let fortune = FORTUNE_STMT.execute(&cli).await?.leak(); - - let mut updates = vec![Statement::default()]; - - for update in (1..=500).map(update_query_from_num) { - let stmt = Statement::named(&update, &[]).execute(&cli).await?.leak(); - updates.push(stmt); - } + let update = UPDATE_STMT.execute(&cli).await?.leak(); Ok(Client { cli, - shared: Default::default(), + rng: Default::default(), world, fortune, - updates: updates.into_boxed_slice(), + update, }) } impl Client { pub async fn get_world(&self) -> HandleResult { - let id = self.shared.borrow_mut().0.gen_id(); + let id = self.rng.borrow_mut().gen_id(); let mut res = self.world.bind([id]).query(&self.cli).await?; let row = res.try_next().await?.ok_or_else(not_found)?; Ok(World::new(row.get(0), row.get(1))) } pub async fn get_worlds(&self, num: u16) -> HandleResult> { - let len = num as usize; - - let mut res = { - let (ref mut rng, ref mut buf) = *self.shared.borrow_mut(); - // unrealistic as all queries are sent with only one sync point. - let mut pipe = Pipeline::unsync_with_capacity_from_buf(len, buf); - (0..num).try_for_each(|_| self.world.bind([rng.gen_id()]).query(&mut pipe))?; - pipe.query(&self.cli)? - }; - - let mut worlds = Vec::with_capacity(len); - - while let Some(mut item) = res.try_next().await? { - while let Some(row) = item.try_next().await? { - worlds.push(World::new(row.get(0), row.get(1))); - } + let get = self + .rng + .borrow_mut() + .gen_multi() + .take(num as _) + .map(|id| self.world.bind([id]).query(&self.cli)) + .collect::>(); + + let mut worlds = Vec::with_capacity(num as _); + + for query in get { + let mut res = query.await?; + let row = res.try_next().await?.ok_or_else(not_found)?; + worlds.push(World::new(row.get(0), row.get(1))); } Ok(worlds) } pub async fn update(&self, num: u16) -> HandleResult> { - let len = num as usize; - - let mut params = Vec::with_capacity(len); - - let mut res = { - let (ref mut rng, ref mut buf) = *self.shared.borrow_mut(); - // unrealistic as all queries are sent with only one sync point. - let mut pipe = Pipeline::unsync_with_capacity_from_buf(len + 1, buf); - (0..num).try_for_each(|_| { - let w_id = rng.gen_id(); - let r_id = rng.gen_id(); - params.push([w_id, r_id]); - self.world.bind([w_id]).query(&mut pipe) - })?; - self.updates[len].bind(sort_update_params(¶ms)).query(&mut pipe)?; - pipe.query(&self.cli)? + let (get, update, worlds) = { + let mut rng = self.rng.borrow_mut(); + let mut ids = rng.gen_multi().take(num as _).collect::>(); + ids.sort(); + + let (get, rngs, worlds) = ids + .iter() + .cloned() + .zip(rng.gen_multi()) + .map(|(id, rand)| { + let get = self.world.bind([id]).query(&self.cli); + (get, rand, World::new(id, rand)) + }) + .collect::<(Vec<_>, Vec<_>, Vec<_>)>(); + + let update = self.update.bind([&ids, &rngs]).query(&self.cli); + + (get, update, worlds) }; - let mut worlds = Vec::with_capacity(len); - - let mut r_ids = params.into_iter(); - - while let Some(mut item) = res.try_next().await? { - while let Some(row) = item.try_next().await? { - let r_id = r_ids.next().unwrap()[1]; - worlds.push(World::new(row.get(0), r_id)) - } + for fut in get { + let _rand = fut.await?.try_next().await?.ok_or_else(not_found)?.get::(1); } + update.await?; + Ok(worlds) } pub async fn tell_fortune(&self) -> HandleResult { - let mut items = Vec::with_capacity(32); - items.push(Fortune::new(0, "Additional fortune added at request time.")); + let mut items = Vec::with_capacity(16); let mut res = self.fortune.query(&self.cli).await?; @@ -123,8 +109,6 @@ impl Client { items.push(Fortune::new(row.get(0), row.get::(1))); } - items.sort_by(|it, next| it.message.cmp(&next.message)); - Ok(Fortunes::new(items)) } } diff --git a/frameworks/Rust/xitca-web/src/db_util.rs b/frameworks/Rust/xitca-web/src/db_util.rs old mode 100644 new mode 100755 index 74936ab14e4..afde4496d9e --- a/frameworks/Rust/xitca-web/src/db_util.rs +++ b/frameworks/Rust/xitca-web/src/db_util.rs @@ -1,97 +1,21 @@ -use crate::util::Error; - -#[cfg(any(feature = "pg-orm", feature = "pg-orm-async"))] -// diesel does not support high level bulk update api. use raw sql to bypass the limitation. -// relate discussion: https://github.com/diesel-rs/diesel/discussions/2879 -pub fn update_query_from_ids(ids: &[(i32, i32)]) -> String { - update_query(|query| { - use core::fmt::Write; - ids.iter().for_each(|(w_id, num)| { - write!(query, "({}::int,{}::int),", w_id, num).unwrap(); - }); - }) -} +use xitca_postgres::{ + statement::{Statement, StatementNamed}, + types::Type, +}; -fn update_query(func: impl FnOnce(&mut String)) -> String { - const PREFIX: &str = "UPDATE world SET randomNumber = w.r FROM (VALUES "; - const SUFFIX: &str = ") AS w (i,r) WHERE world.id = w.i"; - - let mut query = String::from(PREFIX); +use crate::util::Error; - func(&mut query); +pub const FORTUNE_STMT: StatementNamed = Statement::named("SELECT id,message FROM fortune", &[]); - if query.ends_with(',') { - query.pop(); - } +pub const WORLD_STMT: StatementNamed = Statement::named("SELECT id,randomnumber FROM world WHERE id=$1", &[Type::INT4]); - query.push_str(SUFFIX); - - query -} +pub const UPDATE_STMT: StatementNamed = Statement::named( + "UPDATE world SET randomnumber=w.r FROM (SELECT unnest($1) as i,unnest($2) as r) w WHERE world.id=w.i", + &[Type::INT4_ARRAY, Type::INT4_ARRAY], +); #[cold] #[inline(never)] pub fn not_found() -> Error { "request World does not exist".into() } - -#[cfg(feature = "pg")] -pub use pg::*; - -#[cfg(feature = "pg")] -pub mod pg { - use xitca_io::bytes::BytesMut; - use xitca_postgres::{ - statement::{Statement, StatementNamed}, - types::Type, - }; - - use crate::util::Rand; - - pub type Shared = (Rand, BytesMut); - - pub const FORTUNE_STMT: StatementNamed = Statement::named("SELECT * FROM fortune", &[]); - pub const WORLD_STMT: StatementNamed = Statement::named("SELECT * FROM world WHERE id=$1", &[Type::INT4]); - - pub fn update_query_from_num(num: usize) -> Box { - super::update_query(|query| { - use core::fmt::Write; - (1..=num).fold(1, |idx, _| { - write!(query, "(${}::int,${}::int),", idx, idx + 1).unwrap(); - idx + 2 - }); - }) - .into_boxed_str() - } - - pub fn sort_update_params(params: &[[i32; 2]]) -> impl ExactSizeIterator + Clone { - let mut params = params.to_owned(); - params.sort_by(|a, b| a[0].cmp(&b[0])); - - #[derive(Clone)] - struct ParamIter(I); - - impl Iterator for ParamIter - where - I: Iterator, - { - type Item = I::Item; - - #[inline] - fn next(&mut self) -> Option { - self.0.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() - } - } - - // impl depends on compiler optimization to flat Vec<[T]> to Vec when inferring - // it's size hint. possible to cause runtime panic. - impl ExactSizeIterator for ParamIter where I: Iterator {} - - ParamIter(params.into_iter().flatten()) - } -} diff --git a/frameworks/Rust/xitca-web/src/main.rs b/frameworks/Rust/xitca-web/src/main.rs index 449651ed129..30fded2d8d9 100755 --- a/frameworks/Rust/xitca-web/src/main.rs +++ b/frameworks/Rust/xitca-web/src/main.rs @@ -47,7 +47,6 @@ fn main() -> std::io::Result<()> { "/fortunes", get(fn_service(async |ctx: Ctx| { let (req, state) = ctx.into_parts(); - use sailfish::TemplateOnce; let fortunes = state.client.tell_fortune().await?.render_once()?; req.html_response(fortunes) })), diff --git a/frameworks/Rust/xitca-web/src/main_unrealistic.rs b/frameworks/Rust/xitca-web/src/main_barebone.rs similarity index 92% rename from frameworks/Rust/xitca-web/src/main_unrealistic.rs rename to frameworks/Rust/xitca-web/src/main_barebone.rs index 2b45164fd8d..8e603ad05e1 100644 --- a/frameworks/Rust/xitca-web/src/main_unrealistic.rs +++ b/frameworks/Rust/xitca-web/src/main_barebone.rs @@ -13,14 +13,11 @@ mod util; use std::io; use xitca_http::{ - bytes::BufMutWriter, + bytes::BufMut, h1::dispatcher_unreal::{Dispatcher, Request, Response}, http::StatusCode, }; use xitca_service::Service; -// simd-json crate is realistic approach to json serializer. -// That said xitca-web by default utilize serde-json as serializer making it an unrealistic representation of framework performance -use simd_json_derive::Serialize; use self::{ ser::Message, @@ -109,11 +106,12 @@ async fn handler<'h>(req: Request<'h, State>, res: Response<'h>) -> .header("server", "X") // unrealistic content length header. .header("content-length", "27") - .body_writer(|buf| Message::new().json_write(&mut BufMutWriter(buf)).unwrap()), + // snoic-rs crate is realistic approach to json serializer. + // That said xitca-web by default utilize serde-json as serializer making it an unrealistic representation of framework performance + .body_writer(|buf| sonic_rs::to_writer(buf.writer(), &Message::new()).unwrap()), // all database related categories are unrealistic. please reference db_unrealistic module for detail. "/fortunes" => { - use sailfish::TemplateOnce; let fortunes = req.ctx.client.tell_fortune().await.unwrap().render_once().unwrap(); res.status(StatusCode::OK) .header("content-type", "text/html; charset=utf-8") @@ -142,10 +140,10 @@ async fn handler<'h>(req: Request<'h, State>, res: Response<'h>) -> fn json_response<'r, DB, T>(res: Response<'r>, state: &State, val: &T) -> Response<'r, 3> where - T: Serialize, + T: serde_core::Serialize, { let buf = &mut *state.write_buf.borrow_mut(); - val.json_write(&mut BufMutWriter(buf)).unwrap(); + sonic_rs::to_writer(buf.writer(), val).unwrap(); let res = res .status(StatusCode::OK) .header("content-type", "application/json") diff --git a/frameworks/Rust/xitca-web/src/main_orm.rs b/frameworks/Rust/xitca-web/src/main_orm.rs old mode 100644 new mode 100755 index ed5a51069a7..6fd0e7a3732 --- a/frameworks/Rust/xitca-web/src/main_orm.rs +++ b/frameworks/Rust/xitca-web/src/main_orm.rs @@ -1,25 +1,31 @@ -mod db_diesel_async; -mod schema; +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + mod ser; mod util; +#[cfg(all(feature = "diesel", not(feature = "toasty")))] +#[path = "./db_diesel.rs"] +mod orm; + +#[cfg(all(feature = "toasty", not(feature = "diesel")))] +#[path = "./db_toasty.rs"] +mod orm; + +use ser::{Num, World}; +use util::{HandleResult, SERVER_HEADER_VALUE}; use xitca_web::{ App, codegen::route, - handler::{html::Html, json::Json, query::Query, state::StateRef, text::Text}, + handler::{html::Html, json::Json, query::Query, state::StateRef}, http::{WebResponse, header::SERVER}, - route::get, }; -use db_diesel_async::Pool; -use ser::{Num, World}; -use util::{HandleResult, SERVER_HEADER_VALUE}; +use orm::Pool; fn main() -> std::io::Result<()> { App::new() - .with_async_state(db_diesel_async::create) - .at("/plaintext", get(Text("Hello, World!"))) - .at("/json", get(Json(ser::Message::new()))) + .with_async_state(Pool::create) .at_typed(db) .at_typed(fortunes) .at_typed(queries) @@ -44,7 +50,6 @@ async fn db(StateRef(pool): StateRef<'_, Pool>) -> HandleResult> { #[route("/fortunes", method = get)] async fn fortunes(StateRef(pool): StateRef<'_, Pool>) -> HandleResult> { - use sailfish::TemplateOnce; let html = pool.tell_fortune().await?.render_once()?; Ok(Html(html)) } diff --git a/frameworks/Rust/xitca-web/src/main_sync.rs b/frameworks/Rust/xitca-web/src/main_sync.rs deleted file mode 100644 index 48ac2520bd1..00000000000 --- a/frameworks/Rust/xitca-web/src/main_sync.rs +++ /dev/null @@ -1,61 +0,0 @@ -mod db_diesel; -mod schema; -mod ser; -mod util; - -use serde::Serialize; -use xitca_web::{ - App, - codegen::route, - handler::{html::Html, json::Json, query::Query, state::StateOwn, text::Text}, - http::{WebResponse, header::SERVER}, - route::get, -}; - -use db_diesel::Pool; -use ser::Num; -use util::{HandleResult, SERVER_HEADER_VALUE}; - -fn main() -> std::io::Result<()> { - App::new() - .with_state(db_diesel::create()?) - .at("/plaintext", get(Text("Hello, World!"))) - .at("/json", get(Json(ser::Message::new()))) - .at_typed(db) - .at_typed(fortunes) - .at_typed(queries) - .at_typed(updates) - .map(header) - .serve() - .disable_vectored_write() - .bind("0.0.0.0:8080")? - .run() - .wait() -} - -fn header(mut res: WebResponse) -> WebResponse { - res.headers_mut().insert(SERVER, SERVER_HEADER_VALUE); - res -} - -#[route("/db", method = get)] -fn db(StateOwn(pool): StateOwn) -> HandleResult> { - pool.get_world().map(Json) -} - -#[route("/fortunes", method = get)] -fn fortunes(StateOwn(pool): StateOwn) -> HandleResult> { - use sailfish::TemplateOnce; - let html = pool.tell_fortune()?.render_once()?; - Ok(Html(html)) -} - -#[route("/queries", method = get)] -fn queries(Query(Num(num)): Query, StateOwn(pool): StateOwn) -> HandleResult> { - pool.get_worlds(num).map(Json) -} - -#[route("/updates", method = get)] -fn updates(Query(Num(num)): Query, StateOwn(pool): StateOwn) -> HandleResult> { - pool.update(num).map(Json) -} diff --git a/frameworks/Rust/xitca-web/src/schema.rs b/frameworks/Rust/xitca-web/src/schema.rs deleted file mode 100644 index 758acfe9927..00000000000 --- a/frameworks/Rust/xitca-web/src/schema.rs +++ /dev/null @@ -1,13 +0,0 @@ -diesel::table! { - world (id) { - id -> Integer, - randomnumber -> Integer, - } -} - -diesel::table! { - fortune (id) { - id -> Integer, - message -> Text, - } -} diff --git a/frameworks/Rust/xitca-web/src/ser.rs b/frameworks/Rust/xitca-web/src/ser.rs old mode 100644 new mode 100755 index 8eadc873e2c..1597e19ab09 --- a/frameworks/Rust/xitca-web/src/ser.rs +++ b/frameworks/Rust/xitca-web/src/ser.rs @@ -2,23 +2,22 @@ use std::borrow::Cow; -use serde::{Deserialize, Deserializer, Serialize, Serializer, ser::SerializeStruct}; +use serde_core::{Deserialize, Deserializer, Serialize, Serializer, ser::SerializeStruct}; use xitca_http::{ body::Once, - bytes::{BufMutWriter, Bytes}, + bytes::Bytes, http::{ self, IntoResponse as _, RequestExt, StatusCode, - const_header_value::{JSON, TEXT_HTML_UTF8, TEXT_UTF8}, + const_header_value::{TEXT_HTML_UTF8, TEXT_UTF8}, header::CONTENT_TYPE, }, }; -use crate::util::{Error, State}; +use crate::util::Error; const HELLO: &str = "Hello, World!"; const HELLO_BYTES: &[u8] = HELLO.as_bytes(); -#[cfg_attr(feature = "perf", derive(simd_json_derive::Serialize))] #[derive(Clone)] pub struct Message { message: &'static str, @@ -33,9 +32,11 @@ impl Message { pub struct Num(pub u16); -#[cfg_attr(any(feature = "pg-orm", feature = "pg-orm-async"), derive(diesel::Queryable))] -#[cfg_attr(feature = "perf", derive(simd_json_derive::Serialize))] +#[cfg_attr(feature = "diesel", derive(diesel::Queryable))] +#[cfg_attr(feature = "toasty", derive(toasty::Model))] +#[cfg_attr(feature = "toasty", table = "world")] pub struct World { + #[cfg_attr(feature = "toasty", key)] pub id: i32, pub randomnumber: i32, } @@ -47,8 +48,11 @@ impl World { } } -#[cfg_attr(any(feature = "pg-orm", feature = "pg-orm-async"), derive(diesel::Queryable))] +#[cfg_attr(feature = "diesel", derive(diesel::Queryable))] +#[cfg_attr(feature = "toasty", derive(toasty::Model))] +#[cfg_attr(feature = "toasty", table = "fortune")] pub struct Fortune { + #[cfg_attr(feature = "toasty", key)] pub id: i32, pub message: Cow<'static, str>, } @@ -71,8 +75,8 @@ pub struct Fortunes { // using the macro does not have any perf cost and this piece of code is expanded manually to speed up compile time of // bench to reduce resource usage of bench runner #[cfg(feature = "template")] -impl sailfish::TemplateOnce for Fortunes { - fn render_once(self) -> sailfish::RenderResult { +impl Fortunes { + pub fn render_once(self) -> sailfish::RenderResult { use sailfish::runtime::{Buffer, Render}; const PREFIX: &str = "\n\nFortunes\n\n\n\n"; @@ -92,15 +96,13 @@ impl sailfish::TemplateOnce for Fortunes { Ok(buf.into_string()) } - - fn render_once_to(self, _: &mut sailfish::runtime::Buffer) -> Result<(), sailfish::runtime::RenderError> { - unimplemented!("") - } } impl Fortunes { #[inline] - pub const fn new(items: Vec) -> Self { + pub fn new(mut items: Vec) -> Self { + items.push(Fortune::new(0, "Additional fortune added at request time.")); + items.sort_by(|a, b| a.message.cmp(&b.message)); Self { items } } } @@ -112,7 +114,7 @@ impl<'de> Deserialize<'de> for Num { { use core::fmt; - use serde::de::{Error, MapAccess, Visitor}; + use serde_core::de::{Error, MapAccess, Visitor}; const FIELDS: &[&str] = &["q"]; @@ -196,7 +198,8 @@ pub type Request = http::Request>; pub type Response = http::Response>; pub trait IntoResponse: Sized { - fn json_response(self, state: &State, val: &impl Serialize) -> Result; + #[cfg(any(feature = "json", feature = "perf-json"))] + fn json_response(self, state: &crate::util::State, val: &impl Serialize) -> Result; fn text_response(self) -> Result; @@ -204,11 +207,18 @@ pub trait IntoResponse: Sized { } impl IntoResponse for Request { - fn json_response(self, state: &State, val: &impl Serialize) -> Result { + #[cfg(any(feature = "json", feature = "perf-json"))] + fn json_response(self, state: &crate::util::State, val: &impl Serialize) -> Result { let buf = &mut *state.write_buf.borrow_mut(); - serde_json::to_writer(BufMutWriter(buf), val)?; + #[cfg(all(feature = "json", not(feature = "perf-json")))] + serde_json::to_writer(xitca_http::bytes::BufMutWriter(buf), val)?; + + #[cfg(all(feature = "perf-json", not(feature = "json")))] + sonic_rs::to_writer(xitca_http::bytes::BufMut::writer(&mut *buf), val)?; + let mut res = self.into_response(buf.split().freeze()); - res.headers_mut().insert(CONTENT_TYPE, JSON); + res.headers_mut() + .insert(CONTENT_TYPE, xitca_http::http::const_header_value::JSON); Ok(res) } diff --git a/frameworks/Rust/xitca-web/src/util.rs b/frameworks/Rust/xitca-web/src/util.rs index 48e2c24cc68..bccb7549ac6 100755 --- a/frameworks/Rust/xitca-web/src/util.rs +++ b/frameworks/Rust/xitca-web/src/util.rs @@ -1,7 +1,6 @@ #![allow(dead_code)] -use core::cell::RefCell; - +use rand::{Rng, SeedableRng, distr::Uniform, rngs::SmallRng}; use xitca_http::{bytes::BytesMut, http::header::HeaderValue}; pub trait QueryParse { @@ -33,7 +32,7 @@ pub const DB_URL: &str = "postgres://benchmarkdbuser:benchmarkdbpass@tfb-databas pub struct State { pub client: DB, - pub write_buf: RefCell, + pub write_buf: core::cell::RefCell, } impl State { @@ -45,8 +44,6 @@ impl State { } } -use rand::{Rng, SeedableRng, rngs::SmallRng}; - pub struct Rand(SmallRng); impl Default for Rand { @@ -55,9 +52,21 @@ impl Default for Rand { } } +impl Clone for Rand { + #[inline] + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + impl Rand { #[inline] pub fn gen_id(&mut self) -> i32 { self.0.random_range(1..=10000) } + + #[inline] + pub fn gen_multi(&mut self) -> impl Iterator { + (&mut self.0).sample_iter(Uniform::new(1, 10001).unwrap()) + } } diff --git a/frameworks/Rust/xitca-web/templates/fortune.stpl b/frameworks/Rust/xitca-web/templates/fortune.stpl deleted file mode 100644 index 28227945b4c..00000000000 --- a/frameworks/Rust/xitca-web/templates/fortune.stpl +++ /dev/null @@ -1,10 +0,0 @@ - - - Fortunes - -
idmessage
- - <% for item in self.items { %><% } %> -
idmessage
<%= item.id %><%= &*item.message %>
- - \ No newline at end of file diff --git a/frameworks/Rust/xitca-web/xitca-web-barebone.dockerfile b/frameworks/Rust/xitca-web/xitca-web-barebone.dockerfile new file mode 100644 index 00000000000..4a5bbf9d898 --- /dev/null +++ b/frameworks/Rust/xitca-web/xitca-web-barebone.dockerfile @@ -0,0 +1,10 @@ +FROM rust:1.91.1 + +ADD ./ /xitca-web +WORKDIR /xitca-web + +RUN cargo build --release --bin xitca-web-barebone --features perf,perf-json,pg,template + +EXPOSE 8080 + +CMD ./target/release/xitca-web-barebone diff --git a/frameworks/Rust/xitca-web/xitca-web-diesel.dockerfile b/frameworks/Rust/xitca-web/xitca-web-diesel.dockerfile new file mode 100755 index 00000000000..66ff80b5dfd --- /dev/null +++ b/frameworks/Rust/xitca-web/xitca-web-diesel.dockerfile @@ -0,0 +1,10 @@ +FROM rust:1.91.1 + +ADD ./ /xitca-web +WORKDIR /xitca-web + +RUN cargo build --release --bin xitca-web-diesel --features diesel,perf,template,web-codegen + +EXPOSE 8080 + +CMD ./target/release/xitca-web-diesel diff --git a/frameworks/Rust/xitca-web/xitca-web-orm.dockerfile b/frameworks/Rust/xitca-web/xitca-web-orm.dockerfile deleted file mode 100644 index 19a4adad80f..00000000000 --- a/frameworks/Rust/xitca-web/xitca-web-orm.dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM rust:1.90 - -ADD ./ /xitca-web -WORKDIR /xitca-web - -RUN cargo build --release --bin xitca-web-orm --features pg-orm-async,template,web-codegen - -EXPOSE 8080 - -CMD ./target/release/xitca-web-orm diff --git a/frameworks/Rust/xitca-web/xitca-web-sync.dockerfile b/frameworks/Rust/xitca-web/xitca-web-sync.dockerfile deleted file mode 100644 index b2f2b128395..00000000000 --- a/frameworks/Rust/xitca-web/xitca-web-sync.dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM rust:1.90 - -ADD ./ /xitca-web -WORKDIR /xitca-web - -RUN cargo build --release --bin xitca-web-sync --features pg-orm,template,web-codegen - -EXPOSE 8080 - -CMD ./target/release/xitca-web-sync diff --git a/frameworks/Rust/xitca-web/xitca-web-toasty.dockerfile b/frameworks/Rust/xitca-web/xitca-web-toasty.dockerfile new file mode 100755 index 00000000000..30a2cea648d --- /dev/null +++ b/frameworks/Rust/xitca-web/xitca-web-toasty.dockerfile @@ -0,0 +1,10 @@ +FROM rust:1.91.1 + +ADD ./ /xitca-web +WORKDIR /xitca-web + +RUN cargo build --release --bin xitca-web-toasty --features perf,template,toasty,web-codegen + +EXPOSE 8080 + +CMD ./target/release/xitca-web-toasty diff --git a/frameworks/Rust/xitca-web/xitca-web-unrealistic.dockerfile b/frameworks/Rust/xitca-web/xitca-web-unrealistic.dockerfile deleted file mode 100644 index 6e6ed7828b6..00000000000 --- a/frameworks/Rust/xitca-web/xitca-web-unrealistic.dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM rust:1.90 - -ADD ./ /xitca-web -WORKDIR /xitca-web - -RUN cargo build --release --bin xitca-web-unrealistic --features perf,pg,template - -EXPOSE 8080 - -CMD ./target/release/xitca-web-unrealistic diff --git a/frameworks/Rust/xitca-web/xitca-web.dockerfile b/frameworks/Rust/xitca-web/xitca-web.dockerfile index 7558d46f428..86d7818009e 100644 --- a/frameworks/Rust/xitca-web/xitca-web.dockerfile +++ b/frameworks/Rust/xitca-web/xitca-web.dockerfile @@ -1,9 +1,9 @@ -FROM rust:1.90 +FROM rust:1.91.1 ADD ./ /xitca-web WORKDIR /xitca-web -RUN cargo build --release --bin xitca-web --features io-uring,pg,router,template +RUN cargo build --release --bin xitca-web --features io-uring,json,pg,router,template EXPOSE 8080 diff --git a/frameworks/TypeScript/brahma-firelight/benchmark_config.json b/frameworks/TypeScript/brahma-firelight/benchmark_config.json index 5ebbb896e7e..60db94104a9 100644 --- a/frameworks/TypeScript/brahma-firelight/benchmark_config.json +++ b/frameworks/TypeScript/brahma-firelight/benchmark_config.json @@ -1,21 +1,23 @@ { "framework": "brahma-firelight", - "tests": [{ - "default": { - "json_url": "/json", - "plaintext_url": "/plaintext", - "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "framework": "brahma-firelight", - "language": "TypeScript", - "flavor": "bun", - "platform": "bun", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "brahma-firelight", - "versus": "nodejs" + "tests": [ + { + "default": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "framework": "brahma-firelight", + "language": "TypeScript", + "flavor": "bun", + "platform": "bun", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "brahma-firelight", + "versus": "nodejs" + } } - }] + ] } diff --git a/frameworks/TypeScript/brahma-firelight/brahma-firelight.dockerfile b/frameworks/TypeScript/brahma-firelight/brahma-firelight.dockerfile index dd682eba23f..4ae04a5efbf 100644 --- a/frameworks/TypeScript/brahma-firelight/brahma-firelight.dockerfile +++ b/frameworks/TypeScript/brahma-firelight/brahma-firelight.dockerfile @@ -1,13 +1,25 @@ -FROM oven/bun:1.3 - +FROM oven/bun:1.3 AS builder WORKDIR /app -COPY . . +COPY package.json bun.lock ./ -RUN bun install +RUN bun ci +COPY . . RUN bun run build +FROM oven/bun:1.3 AS runtime +WORKDIR /app + +ENV NODE_ENV=production +ENV PORT=8080 + +COPY --from=builder /app/dist ./dist +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/package.json ./package.json + +ENV NODE_ENV=production + EXPOSE 8080 -CMD ["bun", "dist/main.js"] +ENTRYPOINT ["bun", "dist/main.js"] diff --git a/frameworks/TypeScript/brahma-firelight/bun.lock b/frameworks/TypeScript/brahma-firelight/bun.lock index a24e46c51c5..cca959f6240 100644 --- a/frameworks/TypeScript/brahma-firelight/bun.lock +++ b/frameworks/TypeScript/brahma-firelight/bun.lock @@ -4,7 +4,7 @@ "": { "name": "brahma-firelight", "dependencies": { - "brahma-firelight": "1.5.16", + "brahma-firelight": "^1.5.20", }, "devDependencies": { "@types/bun": "latest", @@ -21,7 +21,7 @@ "@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="], - "brahma-firelight": ["brahma-firelight@1.5.16", "", {}, "sha512-KwqrG3EHBcEYiOjjx7UvZ4TDxnKTP+DPjnQQqblKuHQcS/mw35NzIYf01YnBZLRM/9VZrb5+UrDaNmrAPZGYlw=="], + "brahma-firelight": ["brahma-firelight@1.5.20", "", {}, "sha512-ACx1E77gepT1WvHskT3AP4fGoxcp2i0Wt7/0DdornEZr5R+emrA1M8YfuA9JGfpVe0bH5L1E6lZxkpldcd3YHQ=="], "bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="], diff --git a/frameworks/TypeScript/brahma-firelight/package.json b/frameworks/TypeScript/brahma-firelight/package.json index dbe9f089100..80835f2981c 100644 --- a/frameworks/TypeScript/brahma-firelight/package.json +++ b/frameworks/TypeScript/brahma-firelight/package.json @@ -14,6 +14,6 @@ "typescript": "^5" }, "dependencies": { - "brahma-firelight": "1.5.16" + "brahma-firelight": "^1.5.20" } } \ No newline at end of file diff --git a/frameworks/TypeScript/brahma-firelight/src/main.ts b/frameworks/TypeScript/brahma-firelight/src/main.ts index 639d33f3085..e7af361746b 100644 --- a/frameworks/TypeScript/brahma-firelight/src/main.ts +++ b/frameworks/TypeScript/brahma-firelight/src/main.ts @@ -1,37 +1,79 @@ -import { createApp, type Response, type Request, type App, type NextFunction, type Handler } from "brahma-firelight"; +import { createApp, type Response, type Request, type App, type NextFunction, type Handler, registerRustHotpath } from "brahma-firelight"; +import cluster from "node:cluster"; +import os from "node:os"; const app: App = createApp(); // Server Config Middleware -const serverInfo: Handler = (_req: Request, res: Response, next?: NextFunction) => { - res.setHeader("Server", "brahma-firelight"); - next?.(); -}; +// const serverInfo: Handler = (_req: Request, res: Response, next?: NextFunction) => { +// res.setHeader("Server", "brahma-firelight"); +// res.setHeader("Connection", "keep-alive") +// next?.(); +// }; // JSON compute -app.get("/json", serverInfo, (_req: Request, res: Response) => { - res.json({ message: "Hello, World!" }); -}); +// app.get("/json", serverInfo, (_req: Request, res: Response) => { +// res.json({ message: "Hello, World!" }); +// }); // PLAIN-TEXT -app.get("/plaintext", serverInfo, (_req: Request, res: Response) => { - res.text("Hello, World!"); -}); +// app.get("/plaintext", serverInfo, (_req: Request, res: Response) => { +// res.text("Hello, World!"); +// }); + + +// JSON compute +registerRustHotpath( + "GET", + "/json", + 200, + '{"Content-Type": "application/json", "Server": "brahma-firelight"}', + Buffer.from(JSON.stringify({ message: "Hello, World!" })) +); + +// PLAIN-TEXT +registerRustHotpath( + "GET", + "/plaintext", + 200, + '{"Content-Type": "text/plain", "Server": "brahma-firelight"}', + Buffer.from("Hello, World!") +); // Port & Host +const PORT = process.env.PORT || 8080; +const HOST = process.env.HOST || "0.0.0.0"; + +// Single CORE +//app.listen(HOST, +PORT); + +// Multi CORE (cluster with max cpus available) +if (cluster.isPrimary) { + const cpuCount = os.cpus().length; + console.log(`Primary ${process.pid} running → forking ${cpuCount} workers...`); + + for (let i = 0; i < cpuCount; i++) { + cluster.fork(); + } -app.listen("0.0.0.0", 8080); + cluster.on("exit", (worker) => { + console.log(`Worker ${worker.process.pid} died → restarting...`); + cluster.fork(); + }); +} else { + app.listen(HOST, +PORT); +} -// Enable built in Graceful Shutdown (optional for production use) +// // Enable built in Graceful Shutdown (optional for production use) -process.on('SIGINT', async () => { - console.log('SIGINT → shutting down...'); - await app.close(2000); // wait up to 2s for requests - process.exit(0); -}); +// process.on('SIGINT', async () => { +// console.log('SIGINT → shutting down...'); +// await app.close(2000); // wait up to 2s for requests +// process.exit(0); +// }); -process.on('SIGTERM', async () => { - console.log('SIGTERM → shutting down...'); - await app.close(2000); - process.exit(0); -}); \ No newline at end of file +// process.on('SIGTERM', async () => { +// console.log('SIGTERM → shutting down...'); +// await app.close(2000); +// process.exit(0); +// }); \ No newline at end of file diff --git a/frameworks/Zig/httpz/build.zig b/frameworks/Zig/httpz/build.zig index 16a4bb64845..420e696ae8c 100644 --- a/frameworks/Zig/httpz/build.zig +++ b/frameworks/Zig/httpz/build.zig @@ -6,16 +6,20 @@ pub fn build(b: *std.Build) !void { const dep_opts = .{ .target = target, .optimize = optimize }; - const exe = b.addExecutable(.{ - .name = "httpz", - .root_source_file = b.path("src/main.zig"), + const root_module = b.addModule("root_mod", .{ .target = target, .optimize = optimize, + .root_source_file = b.path("src/main.zig"), }); const httpz_module = b.dependency("httpz", dep_opts).module("httpz"); const pg_module = b.dependency("pg", dep_opts).module("pg"); - const datetimez_module = b.dependency("datetimez", dep_opts).module("zig-datetime"); + const datetimez_module = b.dependency("datetimez", dep_opts).module("datetime"); + + const exe = b.addExecutable(.{ + .name = "httpz", + .root_module = root_module, + }); exe.root_module.addImport("httpz", httpz_module); exe.root_module.addImport("pg", pg_module); diff --git a/frameworks/Zig/httpz/build.zig.zon b/frameworks/Zig/httpz/build.zig.zon index 83c29e48929..ed67e4a7d99 100644 --- a/frameworks/Zig/httpz/build.zig.zon +++ b/frameworks/Zig/httpz/build.zig.zon @@ -1,15 +1,24 @@ -.{ .name = "Zap testing", .version = "0.1.1", .paths = .{ - "build.zig", - "build.zig.zon", - "src", -}, .dependencies = .{ - .pg = .{ .url = "https://github.com/karlseguin/pg.zig/archive/239a4468163a49d8c0d03285632eabe96003e9e2.tar.gz", .hash = "1220a1d7e51e2fa45e547c76a9e099c09d06e14b0b9bfc6baa89367f56f1ded399a0" }, - .httpz = .{ - .url = "git+https://github.com/karlseguin/http.zig?ref=zig-0.13#7d2ddae87af9b110783085c0ea6b03985faa4584", - .hash = "12208c1f2c5f730c4c03aabeb0632ade7e21914af03e6510311b449458198d0835d6", +.{ + .name = .httpz_testing, + .fingerprint = 0x586e7c8a23a7e7c2, + .version = "0.1.1", + .paths = .{ + "build.zig", + "build.zig.zon", + "src", }, - .datetimez = .{ - .url = "git+https://github.com/frmdstryr/zig-datetime#70aebf28fb3e137cd84123a9349d157a74708721", - .hash = "122077215ce36e125a490e59ec1748ffd4f6ba00d4d14f7308978e5360711d72d77f", + .dependencies = .{ + .pg = .{ + .url = "git+https://github.com/karlseguin/pg.zig.git#f8d4892387fbad2abdf775783e101e50a7114335", + .hash = "pg-0.0.0-Wp_7gag6BgD_QAZrPhNNEGpnUZR_LEkKT40Ura3p-4yX", + }, + .httpz = .{ + .url = "git+https://github.com/karlseguin/http.zig.git#a4477b1dbdc5b820fd4ad301797ca6399f7eb6e4", + .hash = "httpz-0.0.0-PNVzrBgtBwCVkSJyophIX6WHwDR0r8XhBGQr96Kk-1El", + }, + .datetimez = .{ + .url = "git+https://github.com/frmdstryr/zig-datetime.git#3a39a21e6e34dcb0ade0ff828d0914d40ba535f3", + .hash = "datetime-0.8.0-cJNXzP_YAQBxQ5hkNNP6ScnG5XsqciJmeP5RVV4xwCBA", + }, }, -} } +} diff --git a/frameworks/Zig/httpz/httpz.dockerfile b/frameworks/Zig/httpz/httpz.dockerfile index ea4f9a7f76d..c2d0776025f 100644 --- a/frameworks/Zig/httpz/httpz.dockerfile +++ b/frameworks/Zig/httpz/httpz.dockerfile @@ -12,17 +12,19 @@ COPY src src COPY build.zig.zon build.zig.zon COPY build.zig build.zig -ARG ZIG_VER=0.13.0 +ARG ZIG_VER=0.15.2 -RUN apt-get update && apt-get install -y curl xz-utils ca-certificates +RUN apt-get update && apt-get install -y wget xz-utils ca-certificates -RUN curl https://ziglang.org/download/${ZIG_VER}/zig-linux-$(uname -m)-${ZIG_VER}.tar.xz -o zig-linux.tar.xz && \ - tar xf zig-linux.tar.xz && \ - mv zig-linux-$(uname -m)-${ZIG_VER}/ /opt/zig +RUN wget https://ziglang.org/download/${ZIG_VER}/zig-$(uname -m)-linux-${ZIG_VER}.tar.xz -RUN /opt/zig/zig build -Doptimize=ReleaseFast +RUN tar -xvf zig-$(uname -m)-linux-${ZIG_VER}.tar.xz + +RUN mv zig-$(uname -m)-linux-${ZIG_VER} /usr/local/zig + +ENV PATH="/usr/local/zig:$PATH" +RUN zig build -Doptimize=ReleaseFast EXPOSE 3000 -RUN ls CMD ["zig-out/bin/httpz"] diff --git a/frameworks/Zig/httpz/src/endpoints.zig b/frameworks/Zig/httpz/src/endpoints.zig index b8cfe9757fb..62b9c8be39f 100644 --- a/frameworks/Zig/httpz/src/endpoints.zig +++ b/frameworks/Zig/httpz/src/endpoints.zig @@ -3,11 +3,11 @@ const httpz = @import("httpz"); const pg = @import("pg"); const datetimez = @import("datetimez"); -pub var date_str: []u8 = ""; +pub var date_str: [29]u8 = undefined; pub const Global = struct { pool: *pg.Pool, - rand: *std.rand.Random, + rand: *std.Random, }; const World = struct { @@ -70,17 +70,7 @@ fn getWorld(pool: *pg.Pool, random_number: u32) !World { fn setHeaders(allocator: std.mem.Allocator, res: *httpz.Response) !void { res.header("Server", "Httpz"); - //const now = datetimez.datetime.Date.now(); - //const time = datetimez.datetime.Time.now(); - - // Wed, 17 Apr 2013 12:00:00 GMT - // Return date in ISO format YYYY-MM-DD - //const TB_DATE_FMT = "{s:0>3}, {d:0>2} {s:0>3} {d:0>4} {d:0>2}:{d:0>2}:{d:0>2} GMT"; - //const now_str = try std.fmt.allocPrint(allocator, TB_DATE_FMT, .{ now.weekdayName()[0..3], now.day, now.monthName()[0..3], now.year, time.hour, time.minute, time.second }); - - //defer allocator.free(now_str); - - res.header("Date", try allocator.dupe(u8, date_str)); + res.header("Date", try allocator.dupe(u8, &date_str)); } fn getFortunesHtml(allocator: std.mem.Allocator, pool: *pg.Pool) ![]const u8 { diff --git a/frameworks/Zig/httpz/src/main.zig b/frameworks/Zig/httpz/src/main.zig index dd5b3966b2f..0089c1f2ef2 100644 --- a/frameworks/Zig/httpz/src/main.zig +++ b/frameworks/Zig/httpz/src/main.zig @@ -7,22 +7,24 @@ const pool = @import("pool.zig"); const endpoints = @import("endpoints.zig"); -var server: httpz.ServerCtx(*endpoints.Global, *endpoints.Global) = undefined; +var server: httpz.Server(*endpoints.Global) = undefined; pub fn main() !void { const cpu_count = try std.Thread.getCpuCount(); var gpa = std.heap.GeneralPurposeAllocator(.{ .thread_safe = true, }){}; + defer { + if (builtin.mode == .Debug) _ = gpa.deinit(); + } - const allocator = gpa.allocator(); + const allocator = if (builtin.mode == .Debug) gpa.allocator() else std.heap.smp_allocator; var pg_pool = try pool.initPool(allocator); defer pg_pool.deinit(); const date_thread = try std.Thread.spawn(.{}, struct { fn update() !void { - const ally = std.heap.page_allocator; while (true) { const now = datetimez.datetime.Date.now(); const time = datetimez.datetime.Time.now(); @@ -30,15 +32,15 @@ pub fn main() !void { // Wed, 17 Apr 2013 12:00:00 GMT // Return date in ISO format YYYY-MM-DD const TB_DATE_FMT = "{s:0>3}, {d:0>2} {s:0>3} {d:0>4} {d:0>2}:{d:0>2}:{d:0>2} GMT"; - endpoints.date_str = try std.fmt.allocPrint(ally, TB_DATE_FMT, .{ now.weekdayName()[0..3], now.day, now.monthName()[0..3], now.year, time.hour, time.minute, time.second }); - std.time.sleep(std.time.ns_per_ms * 980); + _ = try std.fmt.bufPrint(&endpoints.date_str, TB_DATE_FMT, .{ now.weekdayName()[0..3], now.day, now.monthName()[0..3], now.year, time.hour, time.minute, time.second }); + std.Thread.sleep(std.time.ns_per_ms * 980); } } }.update, .{}); date_thread.detach(); - var prng = std.rand.DefaultPrng.init(@as(u64, @bitCast(std.time.milliTimestamp()))); + var prng: std.Random.DefaultPrng = .init(@as(u64, @bitCast(std.time.milliTimestamp()))); var rand = prng.random(); @@ -50,7 +52,7 @@ pub fn main() !void { const port: u16 = 3000; const workers = @as(u16, @intCast(16 * cpu_count)); - server = try httpz.ServerApp(*endpoints.Global).init(allocator, .{ + server = try httpz.Server(*endpoints.Global).init(allocator, .{ .port = port, .address = "0.0.0.0", .workers = .{ @@ -118,24 +120,24 @@ pub fn main() !void { defer server.deinit(); // now that our server is up, we register our intent to handle SIGINT - try std.posix.sigaction(std.posix.SIG.INT, &.{ + std.posix.sigaction(std.posix.SIG.INT, &.{ .handler = .{ .handler = shutdown }, - .mask = std.posix.empty_sigset, + .mask = std.posix.sigemptyset(), .flags = 0, }, null); - var router = server.router(); - router.get("/json", endpoints.json); - router.get("/plaintext", endpoints.plaintext); - router.get("/db", endpoints.db); - router.get("/fortunes", endpoints.fortune); + var router = try server.router(.{}); + router.get("/json", endpoints.json, .{}); + router.get("/plaintext", endpoints.plaintext, .{}); + router.get("/db", endpoints.db, .{}); + router.get("/fortunes", endpoints.fortune, .{}); std.debug.print("Httpz using {d} workers listening at 0.0.0.0:{d}\n", .{ workers, port }); try server.listen(); } -fn shutdown(_: c_int) callconv(.C) void { +fn shutdown(_: c_int) callconv(.c) void { server.stop(); } diff --git a/frameworks/Zig/httpz/src/pool.zig b/frameworks/Zig/httpz/src/pool.zig index 91867be7906..b8944b547db 100644 --- a/frameworks/Zig/httpz/src/pool.zig +++ b/frameworks/Zig/httpz/src/pool.zig @@ -1,14 +1,11 @@ const std = @import("std"); -const regex = @import("regex"); const pg = @import("pg"); const Allocator = std.mem.Allocator; const Pool = pg.Pool; -const ArrayList = std.ArrayList; pub fn initPool(allocator: Allocator) !*pg.Pool { const info = try parsePostgresConnStr(allocator); - //std.debug.print("Connection: {s}:{s}@{s}:{d}/{s}\n", .{ info.username, info.password, info.hostname, info.port, info.database }); const pg_pool = try Pool.init(allocator, .{ .size = 56, diff --git a/toolset/__init__.py b/toolset/__init__.py old mode 100755 new mode 100644 diff --git a/toolset/continuous/tfb-shutdown.sh b/toolset/continuous/tfb-shutdown.sh old mode 100644 new mode 100755 diff --git a/toolset/continuous/tfb-startup.sh b/toolset/continuous/tfb-startup.sh old mode 100644 new mode 100755 diff --git a/toolset/databases/postgres/config.sh b/toolset/databases/postgres/config.sh index ea3d95e4b7c..8ed1efc94e3 100755 --- a/toolset/databases/postgres/config.sh +++ b/toolset/databases/postgres/config.sh @@ -2,4 +2,11 @@ set -e -cat /tmp/postgresql.conf >> "${PGDATA}/postgresql.conf" +cat /docker-entrypoint-initdb.d/postgresql.conf >> "${PGDATA}/postgresql.conf" + +IO_WORKERS="$(( (`nproc` + 3) / 4 ))" + +# The maximum valid value for the io_workers configuration parameter is 32. +if [[ "$IO_WORKERS" -lt 32 ]]; then + sed -i "s/io_workers = 32/io_workers = ${IO_WORKERS}/" "${PGDATA}/postgresql.conf" +fi diff --git a/toolset/databases/postgres/postgres.dockerfile b/toolset/databases/postgres/postgres.dockerfile index 0573b85b2ca..c5d1db814b3 100644 --- a/toolset/databases/postgres/postgres.dockerfile +++ b/toolset/databases/postgres/postgres.dockerfile @@ -1,10 +1,8 @@ FROM postgres:18-trixie -ENV PGDATA=/ssd/postgresql \ - POSTGRES_DB=hello_world \ +ENV POSTGRES_DB=hello_world \ POSTGRES_PASSWORD=benchmarkdbpass \ POSTGRES_USER=benchmarkdbuser COPY 60-postgresql-shm.conf /etc/sysctl.d/ -COPY config.sh create-postgres.sql /docker-entrypoint-initdb.d/ -COPY postgresql.conf /tmp/ +COPY config.sh create-postgres.sql postgresql.conf /docker-entrypoint-initdb.d/ diff --git a/toolset/databases/postgres/postgresql.conf b/toolset/databases/postgres/postgresql.conf index 72c94956692..5000f5193e5 100644 --- a/toolset/databases/postgres/postgresql.conf +++ b/toolset/databases/postgres/postgresql.conf @@ -5,6 +5,11 @@ listen_addresses = '*' max_connections = 2000 ssl = false +# Tuning AIO in PostgreSQL 18: +# https://vondra.me/posts/tuning-aio-in-postgresql-18 +# The config.sh script sets the actual value based on that article and the runtime environment. +io_workers = 32 + # values from: http://blog.pgaddict.com/posts/performance-since-postgresql-7-4-to-9-4-pgbench # details: http://www.postgresql.org/docs/9.4/static/runtime-config-resource.html # http://www.postgresql.org/docs/9.4/static/runtime-config-wal.html diff --git a/toolset/run-tests.py b/toolset/run-tests.py index a70fff3a490..9e65cec801d 100644 --- a/toolset/run-tests.py +++ b/toolset/run-tests.py @@ -208,6 +208,10 @@ def main(argv=None): nargs='*', default=None, help='Extra docker arguments to be passed to the test container') + parser.add_argument( + '--force-rm', + action='store_true', + help='Remove intermediate docker containers after running.') # Network options parser.add_argument( diff --git a/toolset/scaffolding/README.md b/toolset/scaffolding/README.md old mode 100755 new mode 100644 diff --git a/toolset/scaffolding/benchmark_config.json b/toolset/scaffolding/benchmark_config.json old mode 100755 new mode 100644 diff --git a/toolset/utils/__init__.py b/toolset/utils/__init__.py old mode 100755 new mode 100644 diff --git a/toolset/utils/benchmark_config.py b/toolset/utils/benchmark_config.py old mode 100755 new mode 100644 index 04dcc2c6cc3..d73dcb4125c --- a/toolset/utils/benchmark_config.py +++ b/toolset/utils/benchmark_config.py @@ -57,6 +57,7 @@ def __init__(self, args): self.cpuset_cpus = args.cpuset_cpus self.test_container_memory = args.test_container_memory self.extra_docker_runtime_args = args.extra_docker_runtime_args + self.force_rm_intermediate_docker_layers = args.force_rm if self.network_mode is None: self.network = 'tfb' diff --git a/toolset/utils/docker_helper.py b/toolset/utils/docker_helper.py index e48a910e99d..f25a9d133a0 100644 --- a/toolset/utils/docker_helper.py +++ b/toolset/utils/docker_helper.py @@ -39,7 +39,7 @@ def __build(self, base_url, path, build_log_file, log_prefix, dockerfile, path=path, dockerfile=dockerfile, tag=tag, - forcerm=True, + forcerm=self.benchmarker.config.force_rm_intermediate_docker_layers, timeout=3600, pull=True, buildargs=buildargs, diff --git a/toolset/utils/metadata.py b/toolset/utils/metadata.py index 6e440fc23ab..6f7388828b8 100644 --- a/toolset/utils/metadata.py +++ b/toolset/utils/metadata.py @@ -191,6 +191,18 @@ def parse_config(self, config, directory): % config['framework'], color=Fore.YELLOW) + # Check that each framework does not have more than the maximum number of tests + maximum_tests = 10 + non_broken_tests_filter = lambda test: (not hasattr(test, "tags")) or ("broken" not in test.tags) + non_broken_tests_to_run = list(filter(non_broken_tests_filter, tests_to_run)) + if len(non_broken_tests_to_run) > maximum_tests: + message = [ + "Framework %s defines %s tests in benchmark_config.json (max is %s)." + % (config['framework'], len(non_broken_tests_to_run), maximum_tests), + "Contact maintainers and remove deprecated or discarded ones to make room." + ] + log("\n".join(message), color=Fore.YELLOW) + # Check that each test configuration is acceptable # Throw exceptions if a field is missing, or how to improve the field for test_name, test_keys in test.items(): diff --git a/toolset/utils/output_helper.py b/toolset/utils/output_helper.py old mode 100755 new mode 100644 diff --git a/toolset/utils/results.py b/toolset/utils/results.py index 0df26636404..28bfae16ff6 100644 --- a/toolset/utils/results.py +++ b/toolset/utils/results.py @@ -12,6 +12,7 @@ import math import csv import traceback +import platform from datetime import datetime # Cross-platform colored text @@ -52,6 +53,10 @@ def __init__(self, benchmarker): except Exception: #Could not read local git repository, which is fine. self.git = None + # OS information - only set once during initialization + self.operatingSystem = dict() + self.operatingSystem['name'] = platform.system() + self.operatingSystem['version'] = platform.release() self.startTime = int(round(time.time() * 1000)) self.completionTime = None self.concurrencyLevels = self.config.concurrency_levels @@ -320,6 +325,7 @@ def __to_jsonable(self): toRet['name'] = self.name toRet['environmentDescription'] = self.environmentDescription toRet['git'] = self.git + toRet['operatingSystem'] = self.operatingSystem toRet['startTime'] = self.startTime toRet['completionTime'] = self.completionTime toRet['concurrencyLevels'] = self.concurrencyLevels diff --git a/toolset/utils/scaffolding.py b/toolset/utils/scaffolding.py old mode 100755 new mode 100644 diff --git a/toolset/wrk/concurrency.sh b/toolset/wrk/concurrency.sh old mode 100644 new mode 100755 diff --git a/toolset/wrk/pipeline.sh b/toolset/wrk/pipeline.sh old mode 100644 new mode 100755 diff --git a/toolset/wrk/query.sh b/toolset/wrk/query.sh old mode 100644 new mode 100755 diff --git a/toolset/wrk/wrk.dockerfile b/toolset/wrk/wrk.dockerfile index 9bcf42f7b38..9d65d1108b8 100644 --- a/toolset/wrk/wrk.dockerfile +++ b/toolset/wrk/wrk.dockerfile @@ -1,21 +1,7 @@ FROM ubuntu:24.04 -# Required scripts for benchmarking -COPY concurrency.sh pipeline.lua pipeline.sh query.sh ./ - ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get -yqq update >/dev/null && \ - apt-get -yqq install >/dev/null \ - curl \ - wrk && \ - chmod 777 concurrency.sh pipeline.sh query.sh +RUN apt-get install --no-install-recommends -qqUy curl wrk > /dev/null -# Environment vars required by the wrk scripts with nonsense defaults -ENV accept=accept \ - duration=duration \ - levels=levels \ - max_concurrency=max_concurrency \ - max_threads=max_threads \ - name=name \ - pipeline=pipeline \ - server_host=server_host +# Required scripts for benchmarking +COPY concurrency.sh pipeline.lua pipeline.sh query.sh ./