Browse Source

Merge pull request #36 from TechEmpower/master

aa
三刀 9 months ago
parent
commit
e515c62872
100 changed files with 2063 additions and 2570 deletions
  1. 133 0
      CODE_OF_CONDUCT.md
  2. 1 0
      frameworks/C++/libsniper/libs/core
  3. 5 4
      frameworks/C++/userver/README.md
  4. 0 24
      frameworks/C++/userver/benchmark_config.json
  5. 0 18
      frameworks/C++/userver/config.toml
  6. 0 29
      frameworks/C++/userver/userver-bare.dockerfile
  7. 2 2
      frameworks/C++/userver/userver.dockerfile
  8. 2 17
      frameworks/C++/userver/userver_benchmark/userver_techempower.cpp
  9. 2 5
      frameworks/C++/userver/userver_configs/static_config.yaml
  10. 28 18
      frameworks/C/h2o/h2o.dockerfile
  11. 5 3
      frameworks/C/h2o/src/handlers/world.c
  12. 0 17
      frameworks/CSharp/appmpower/appmpower-ado-pg.dockerfile
  13. 51 0
      frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile
  14. 7 1
      frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile
  15. 6 0
      frameworks/CSharp/appmpower/appmpower.dockerfile
  16. 4 4
      frameworks/CSharp/appmpower/benchmark_config.json
  17. 2 2
      frameworks/CSharp/appmpower/config.toml
  18. 10 0
      frameworks/CSharp/appmpower/odbcinst.ini
  19. 0 15
      frameworks/CSharp/appmpower/src/CachedWorldSerializer.cs
  20. 0 200
      frameworks/CSharp/appmpower/src/Data/DbConnection.cs
  21. 0 67
      frameworks/CSharp/appmpower/src/Data/DbConnections.cs
  22. 0 17
      frameworks/CSharp/appmpower/src/Data/DbProviderFactory.cs
  23. 0 16
      frameworks/CSharp/appmpower/src/Data/InternalConnection.cs
  24. 0 117
      frameworks/CSharp/appmpower/src/HttpApplication.cs
  25. 0 7
      frameworks/CSharp/appmpower/src/JsonMessage.cs
  26. 0 58
      frameworks/CSharp/appmpower/src/Kestrel/Json.cs
  27. 0 38
      frameworks/CSharp/appmpower/src/Kestrel/PlainText.cs
  28. 0 25
      frameworks/CSharp/appmpower/src/Kestrel/ServiceProvider.cs
  29. 0 257
      frameworks/CSharp/appmpower/src/Memory/CacheEntry.cs
  30. 0 32
      frameworks/CSharp/appmpower/src/Memory/CacheEntryHelper.cs
  31. 0 62
      frameworks/CSharp/appmpower/src/Memory/CacheEntryState.cs
  32. 0 140
      frameworks/CSharp/appmpower/src/Memory/CacheEntryTokens.cs
  33. 0 520
      frameworks/CSharp/appmpower/src/Memory/MemoryCache.cs
  34. 0 67
      frameworks/CSharp/appmpower/src/Memory/MemoryCacheOptions.cs
  35. 0 24
      frameworks/CSharp/appmpower/src/Microsoft/CachKey.cs
  36. 0 59
      frameworks/CSharp/appmpower/src/Microsoft/StringBuilderCache.cs
  37. 0 42
      frameworks/CSharp/appmpower/src/Program.cs
  38. 10 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Constants.cs
  39. 40 63
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbCommand.cs
  40. 174 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnection.cs
  41. 61 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnections.cs
  42. 61 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnectionsKeyed.cs
  43. 8 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProvider.cs
  44. 21 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProviderFactory.cs
  45. 9 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/Dbms.cs
  46. 66 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/DotnetMethods.cs
  47. 4 17
      frameworks/CSharp/appmpower/src/appMpower.Orm/FortunesView.cs
  48. 19 37
      frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/BatchUpdateString.cs
  49. 0 2
      frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/ConcurrentRandom.cs
  50. 54 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/StringBuilderCache.cs
  51. 144 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs
  52. 1 1
      frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/CachedWorld.cs
  53. 1 3
      frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/Fortune.cs
  54. 1 1
      frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/World.cs
  55. 50 131
      frameworks/CSharp/appmpower/src/appMpower.Orm/RawDb.cs
  56. 9 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/IJsonSerializer.cs
  57. 4 2
      frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/WorldSerializer.cs
  58. 24 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/WorldsSerizalizer.cs
  59. 42 55
      frameworks/CSharp/appmpower/src/appMpower.Orm/appMpower.Orm.csproj
  60. 7 0
      frameworks/CSharp/appmpower/src/appMpower/JsonMessage.cs
  61. 120 0
      frameworks/CSharp/appmpower/src/appMpower/Middleware/CachingMiddelware.cs
  62. 58 0
      frameworks/CSharp/appmpower/src/appMpower/Middleware/FortunesMiddleware.cs
  63. 64 0
      frameworks/CSharp/appmpower/src/appMpower/Middleware/JsonMiddleware.cs
  64. 62 0
      frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleQueriesMiddleware.cs
  65. 62 0
      frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleUpdatesMiddleware.cs
  66. 50 0
      frameworks/CSharp/appmpower/src/appMpower/Middleware/PlaintextMiddleware.cs
  67. 57 0
      frameworks/CSharp/appmpower/src/appMpower/Middleware/SingleQueryMiddleware.cs
  68. 62 0
      frameworks/CSharp/appmpower/src/appMpower/NativeMethods.cs
  69. 44 0
      frameworks/CSharp/appmpower/src/appMpower/Program.cs
  70. 1 1
      frameworks/CSharp/appmpower/src/appMpower/Serializers/IJsonSerializer.cs
  71. 3 3
      frameworks/CSharp/appmpower/src/appMpower/Serializers/JsonMessageSerializer.cs
  72. 56 0
      frameworks/CSharp/appmpower/src/appMpower/Startup.cs
  73. 35 0
      frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj
  74. 9 0
      frameworks/CSharp/appmpower/src/appMpower/appsettings.json
  75. 0 0
      frameworks/CSharp/appmpower/src/appMpower/nuget.config
  76. 28 0
      frameworks/CSharp/appmpower/src/src.sln
  77. 1 1
      frameworks/CSharp/aspnetcore/appsettings.postgresql.json
  78. 3 3
      frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile
  79. 5 2
      frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile
  80. 5 2
      frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile
  81. 5 2
      frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile
  82. 6 3
      frameworks/CSharp/aspnetcore/aspnetcore.dockerfile
  83. 4 4
      frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj
  84. 6 8
      frameworks/CSharp/aspnetcore/src/Minimal/Program.cs
  85. 0 0
      frameworks/CSharp/aspnetcore/src/Minimal/Slices/Fortunes.cshtml
  86. 0 0
      frameworks/CSharp/aspnetcore/src/Minimal/Slices/_ViewImports.cshtml
  87. 3 3
      frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj
  88. 4 4
      frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj
  89. 0 1
      frameworks/CSharp/aspnetcore/src/Platform/Program.cs
  90. 177 248
      frameworks/CSharp/beetlex/PlatformBenchmarks/DBRaw.cs
  91. 8 6
      frameworks/CSharp/beetlex/PlatformBenchmarks/GMTDate.cs
  92. 1 1
      frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.Caching.cs
  93. 4 18
      frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.cs
  94. 2 2
      frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.db.cs
  95. 12 12
      frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.fortunes.cs
  96. 7 3
      frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.json.cs
  97. 19 4
      frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.plaintext.cs
  98. 1 1
      frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.queries.cs
  99. 1 1
      frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.updates.cs
  100. 10 18
      frameworks/CSharp/beetlex/PlatformBenchmarks/HttpServer.cs

+ 133 - 0
CODE_OF_CONDUCT.md

@@ -0,0 +1,133 @@
+
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+  and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall
+  community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or advances of
+  any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email address,
+  without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official email address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
[email protected].
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
+[https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations

+ 1 - 0
frameworks/C++/libsniper/libs/core

@@ -0,0 +1 @@
+Subproject commit a792ecfebb02f98bbdd8db232fba69f3f92907b3

+ 5 - 4
frameworks/C++/userver/README.md

@@ -2,14 +2,11 @@
 
 This is the [userver](https://github.com/userver-framework/userver) portion of a [benchmarking test suite](https://github.com/TechEmpower/FrameworkBenchmarks) comparing a variety of web development platforms.
 
-This benchmarks comes in two configurations: **userver** and **userver-bare**, where both configurations use exactly the same handlers code, but **userver-bare** replaces default http implementation of **userver** with custom one.  
-You see, **userver** being feature-rich framework widely used in production comes with a lot of useful functionality built-in (metrics, dynamic configuring, logging/tracing, congestion control etc...) none of which is of any use in benchmarks; although most of that can be disabled via configs, some parts remain, and these parts aren't free.  
-The aim of **userver-bare** is to explore practical limits of lower-level **userver** functionality when performance is an absolute must, while still being idiomatic userver code.
-
 ### Test Type Implementation Source Code
 
 * [Plaintext](userver_benchmark/controllers/plaintext/handler.cpp)
 * [Json](userver_benchmark/controllers/json/handler.cpp)
+* [Fortunes](userver_benchmark/controllers/fortunes/handler.cpp)
 * [Single Database Query](userver_benchmark/controllers/single_query/handler.cpp)
 * [Multiple Database Queries](userver_benchmark/controllers/multiple_queries/handler.cpp)
 * [Database Updates](userver_benchmark/controllers/updates/handler.cpp)
@@ -24,6 +21,10 @@ http://localhost:8080/plaintext
 
 http://localhost:8080/json
 
+### Fortunes
+
+http://localhost:8080/fortunes
+
 ### Single Database Query
 
 http://localhost:8080/db

+ 0 - 24
frameworks/C++/userver/benchmark_config.json

@@ -25,30 +25,6 @@
         "display_name": "userver",
         "notes": "",
         "versus": "None"
-      },
-      "bare": {
-        "json_url": "/json",
-        "plaintext_url": "/plaintext",
-        "db_url": "/db",
-        "query_url": "/queries?queries=",
-        "update_url": "/updates?queries=",
-        "cached_query_url": "/cached-queries?count=",
-	"fortune_url": "/fortunes",
-        "port": 8081,
-        "approach": "Realistic",
-        "classification": "Micro",
-        "database": "postgres",
-        "framework": "userver",
-        "language": "C++",
-        "flavor": "None",
-        "orm": "Micro",
-        "platform": "None",
-        "webserver": "None",
-        "os": "Linux",
-        "database_os": "Linux",
-        "display_name": "userver[bare]",
-        "notes": "",
-        "versus": "None"
       }
     }
   ]

+ 0 - 18
frameworks/C++/userver/config.toml

@@ -18,21 +18,3 @@ orm = "Micro"
 platform = "None"
 webserver = "None"
 versus = "None"
-
-[bare]
-urls.plaintext = "/plaintext"
-urls.json = "/json"
-urls.db = "/db"
-urls.query = "/queries?queries="
-urls.update = "/updates?queries="
-urls.cached_query = "/cached-queries?count="
-urls.fortune = "/fortunes"
-approach = "Realistic"
-classification = "Micro"
-database = "Postgres"
-database_os = "Linux"
-os = "Linux"
-orm = "Micro"
-platform = "None"
-webserver = "None"
-versus = "None"

+ 0 - 29
frameworks/C++/userver/userver-bare.dockerfile

@@ -1,29 +0,0 @@
-FROM ghcr.io/userver-framework/ubuntu-22.04-userver-pg AS builder
-
-RUN apt update && \
-    apt install -y lsb-release wget software-properties-common gnupg && \
-        wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 16
-
-WORKDIR /src
-RUN git clone https://github.com/userver-framework/userver.git && \
-    cd userver && git checkout ec1a3b07793f8d4cd0968cd61d8e6079d667a1e7
-
-COPY userver_benchmark/ ./
-RUN mkdir build && cd build && \
-    cmake -DUSERVER_IS_THE_ROOT_PROJECT=0 -DUSERVER_FEATURE_CRYPTOPP_BLAKE2=0 \
-          -DUSERVER_FEATURE_UTEST=0 \
-          -DUSERVER_FEATURE_POSTGRESQL=1 \
-          -DUSERVER_FEATURE_ERASE_LOG_WITH_LEVEL=warning \
-          -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native -flto=thin" -DCMAKE_C_FLAGS="-march=native -flto=thin" \
-          -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_C_COMPILER=clang-16 -DUSERVER_USE_LD=lld-16 \
-          -DUSERVER_LTO=0 .. && \
-    make -j $(nproc)
-
-FROM builder AS runner
-WORKDIR /app
-COPY userver_configs/* ./
-COPY --from=builder /src/build/userver_techempower ./
-
-EXPOSE 8081
-CMD ./userver_techempower -c ./static_config.yaml
-

+ 2 - 2
frameworks/C++/userver/userver.dockerfile

@@ -6,7 +6,7 @@ RUN apt update && \
 
 WORKDIR /src
 RUN git clone https://github.com/userver-framework/userver.git && \
-    cd userver && git checkout ec1a3b07793f8d4cd0968cd61d8e6079d667a1e7
+    cd userver && git checkout bdd5e1e03921ff378b062f86a189c3cfa3d66332
 
 COPY userver_benchmark/ ./
 RUN mkdir build && cd build && \
@@ -14,7 +14,7 @@ RUN mkdir build && cd build && \
           -DUSERVER_FEATURE_UTEST=0 \
           -DUSERVER_FEATURE_POSTGRESQL=1 \
           -DUSERVER_FEATURE_ERASE_LOG_WITH_LEVEL=warning \
-          -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native -flto=thin" -DCMAKE_C_FLAGS="-march=native -flto=thin" \
+          -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native" -DCMAKE_C_FLAGS="-march=native" \
           -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_C_COMPILER=clang-16 -DUSERVER_USE_LD=lld-16 \
           -DUSERVER_LTO=0 .. && \
     make -j $(nproc)

+ 2 - 17
frameworks/C++/userver/userver_benchmark/userver_techempower.cpp

@@ -46,20 +46,6 @@ class NoopTracingManager final
       userver::server::http::HttpResponse&) const final {}
 };
 
-class MinimalMiddlewarePipelineBuilder final
-    : public userver::server::middlewares::PipelineBuilder {
- public:
-  static constexpr std::string_view kName{
-      "minimal-middleware-pipeline-builder"};
-  using userver::server::middlewares::PipelineBuilder::PipelineBuilder;
-
- private:
-  userver::server::middlewares::MiddlewaresList BuildPipeline(
-      userver::server::middlewares::MiddlewaresList) const override {
-    return {"userver-unknown-exceptions-handling-middleware"};
-  }
-};
-
 int Main(int argc, char* argv[]) {
   auto component_list =
       userver::components::MinimalServerComponentList()
@@ -78,10 +64,9 @@ int Main(int argc, char* argv[]) {
           .Append<cached_queries::WorldCacheComponent>()  // cache component
           .Append<cached_queries::Handler>()
           .Append<fortunes::Handler>()
-          // tracing and metrics tweaks
+          // tracing tweaks
           .Append<NoopTracingManager>()
-          .Append<MinimalMiddlewarePipelineBuilder>()
-          // bare
+          // bare (not used in the benchmark currently)
           .Append<bare::SimpleRouter>()
           .Append<bare::SimpleServer>();
 

+ 2 - 5
frameworks/C++/userver/userver_configs/static_config.yaml

@@ -1,8 +1,7 @@
 # yaml
 components_manager:
     event_thread_pool:
-        threads: 9
-        dedicated_timer_threads: 1
+        threads: 8
     coro_pool:
         initial_size: 10000              # Preallocate 10000 coroutines at startup.
         max_size: 300000                 # Do not keep more than 300000 preallocated coroutines.
@@ -12,7 +11,7 @@ components_manager:
 
         main-task-processor:            # Make a task processor for CPU-bound couroutine tasks.
             thread_name: main-worker    # OS will show the threads of this task processor with 'main-worker' prefix.
-            worker_threads: 46
+            worker_threads: 48
             guess-cpu-limit: true
 
         fs-task-processor:              # Make a separate task processor for filesystem bound tasks.
@@ -29,7 +28,6 @@ components_manager:
                 handler-defaults:
                     set_tracing_headers: false
             server-name: us
-            middleware-pipeline-builder: minimal-middleware-pipeline-builder
         simple-router:
         simple-server:
             port: 8081
@@ -63,7 +61,6 @@ components_manager:
         noop-tracing-manager:
         tracing-manager-locator:
             component-name: noop-tracing-manager
-        minimal-middleware-pipeline-builder:
 
         plaintext-handler:
             path: /plaintext

+ 28 - 18
frameworks/C/h2o/h2o.dockerfile

@@ -6,19 +6,28 @@ FROM "ubuntu:${UBUNTU_VERSION}" AS compile
 
 ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get -yqq update && \
+    apt-get -yqq install \
+      ca-certificates \
+      curl \
+      lsb-release && \
+    install -dm755 /usr/share/postgresql-common/pgdg && \
+    curl --fail -LSso /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
+      "https://www.postgresql.org/media/keys/ACCC4CF8.asc" && \
+    sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
+      https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > \
+      /etc/apt/sources.list.d/pgdg.list' && \
+    apt-get -yqq update && \
     apt-get -yqq install \
       autoconf \
       bison \
       cmake \
-      curl \
       flex \
       g++ \
       libbpfcc-dev \
       libbrotli-dev \
       libcap-dev \
-      libicu-dev \
       libnuma-dev \
-      libreadline-dev \
+      libpq-dev \
       libssl-dev \
       libtool \
       libuv1-dev \
@@ -33,7 +42,7 @@ RUN apt-get -yqq update && \
       ruby \
       systemtap-sdt-dev
 
-ARG H2O_VERSION=18b175f71ede08b50d3e5ae8303dacef3ea510fc
+ARG H2O_VERSION=c54c63285b52421da2782f028022647fc2ea3dd1
 
 WORKDIR /tmp/h2o-build
 RUN curl -LSs "https://github.com/h2o/h2o/archive/${H2O_VERSION}.tar.gz" | \
@@ -57,18 +66,6 @@ RUN curl -LSs "https://github.com/x86-64/mustache-c/archive/${MUSTACHE_C_REVISIO
     CFLAGS="-flto -march=native -mtune=native -O3" ./autogen.sh && \
     make -j "$(nproc)" install
 
-ARG POSTGRESQL_VERSION=a37bb7c13995b834095d9d064cad1023a6f99b10
-
-WORKDIR /tmp/postgresql-build
-RUN curl -LSs "https://github.com/postgres/postgres/archive/${POSTGRESQL_VERSION}.tar.gz" | \
-      tar --strip-components=1 -xz && \
-    CFLAGS="-flto -march=native -mtune=native -O3" ./configure \
-      --includedir=/usr/local/include/postgresql \
-      --prefix=/usr/local \
-      --with-ssl=openssl && \
-    make -j "$(nproc)" -C src/include install && \
-    make -j "$(nproc)" -C src/interfaces/libpq install
-
 ARG H2O_APP_PREFIX
 WORKDIR /tmp/build
 COPY CMakeLists.txt ../
@@ -85,15 +82,28 @@ RUN cmake \
 
 FROM "ubuntu:${UBUNTU_VERSION}"
 
+ARG POSTGRESQL_VERSION=17
+
 ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get -yqq update && \
+    apt-get -yqq install \
+      ca-certificates \
+      curl \
+      lsb-release && \
+    install -dm755 /usr/share/postgresql-common/pgdg && \
+    curl --fail -LSso /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
+      "https://www.postgresql.org/media/keys/ACCC4CF8.asc" && \
+    sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
+      https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > \
+      /etc/apt/sources.list.d/pgdg.list' && \
+    apt-get -yqq update && \
     apt-get -yqq install \
       libnuma1 \
-      libyajl2
+      libyajl2 \
+      "postgresql-client-${POSTGRESQL_VERSION}"
 ARG H2O_APP_PREFIX
 COPY --from=compile "${H2O_APP_PREFIX}" "${H2O_APP_PREFIX}/"
 COPY --from=compile /usr/local/lib/libmustache_c.so "${H2O_APP_PREFIX}/lib/"
-COPY --from=compile /usr/local/lib/libpq.so.5.17 "${H2O_APP_PREFIX}/lib/libpq.so.5"
 ENV LD_LIBRARY_PATH="${H2O_APP_PREFIX}/lib"
 EXPOSE 8080
 ARG BENCHMARK_ENV

+ 5 - 3
frameworks/C/h2o/src/handlers/world.c

@@ -237,8 +237,10 @@ static int do_multiple_queries(bool do_update, bool use_cache, h2o_req_t *req)
 
 	const size_t num_query = get_query_number(req);
 
-	// MAX_QUERIES is a relatively small number, so assume no overflow in the following
-	// arithmetic operations.
+	// MAX_QUERIES is a relatively small number, say less than or equal to UINT16_MAX, so assume no
+	// unsigned overflow in the following arithmetic operations.
+	static_assert(MAX_QUERIES <= UINT16_MAX,
+	              "potential out-of-bounds memory accesses in the following code");
 	assert(num_query && num_query <= MAX_QUERIES);
 
 	size_t base_size = offsetof(multiple_query_ctx_t, res) + num_query * sizeof(query_result_t);
@@ -373,7 +375,7 @@ static void do_updates(multiple_query_ctx_t *query_ctx)
 	for (size_t i = 0; i < query_ctx->num_result; i++) {
 		query_ctx->res[i].id = htonl(query_ctx->res[i].id);
 		query_ctx->res[i].random_number =
-				htonl(1 + get_random_number(MAX_ID, &query_ctx->ctx->random_seed));
+			htonl(1 + get_random_number(MAX_ID, &query_ctx->ctx->random_seed));
 		paramFormats[2 * i] = 1;
 		paramFormats[2 * i + 1] = 1;
 		paramLengths[2 * i] = sizeof(query_ctx->res[i].id);

+ 0 - 17
frameworks/CSharp/appmpower/appmpower-ado-pg.dockerfile

@@ -1,17 +0,0 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0.100 AS build
-RUN apt-get update
-RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
-
-WORKDIR /app
-COPY src .
-RUN dotnet publish -c Release -o out /p:Driver=ado
-
-# Construct the actual image that will run
-FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime
-
-WORKDIR /app
-COPY --from=build /app/out ./
-
-EXPOSE 8080
-
-ENTRYPOINT ["./appMpower"]

+ 51 - 0
frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile

@@ -0,0 +1,51 @@
+FROM mcr.microsoft.com/dotnet/sdk:8.0.100 AS build
+RUN apt-get update
+RUN apt-get -yqq install clang zlib1g-dev
+RUN apt-get update
+
+WORKDIR /app
+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:8.0.0 AS runtime
+
+RUN apt-get update
+# The following installs standard versions unixodbc and pgsqlodbc
+# unixodbc still needs to be installed even if compiled locally
+RUN apt-get install -y unixodbc wget curl
+RUN apt-get update
+
+WORKDIR /odbc
+
+RUN curl -L -o mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz https://downloads.mariadb.com/Connectors/odbc/connector-odbc-3.1.20/mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz
+RUN tar -xvzf mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz
+RUN cp mariadb-connector-odbc-3.1.20-debian-bookworm-amd64/lib/mariadb/libm* /usr/lib/
+RUN cp -r /odbc/mariadb-connector-odbc-3.1.20-debian-bookworm-amd64/lib/mariadb /usr/local/lib/mariadb
+RUN rm mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz
+#TODOLOCAL
+#RUN curl -L -o mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz https://downloads.mariadb.com/Connectors/odbc/connector-odbc-3.1.20/mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz
+#RUN tar -xvzf mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz
+#RUN cp mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64/lib/mariadb/libm* /usr/lib/
+#RUN cp -r /odbc/mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64/lib/mariadb /usr/local/lib/mariadb
+#RUN rm mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz
+
+ENV PATH=/usr/local/unixODBC/bin:$PATH
+
+WORKDIR /etc/
+COPY odbcinst.ini .
+
+# Full PGO
+ENV DOTNET_TieredPGO 1 
+ENV DOTNET_TC_QuickJitForLoops 1 
+ENV DOTNET_ReadyToRun 0
+
+ENV ASPNETCORE_URLS http://+:8080
+WORKDIR /app
+COPY --from=build /app/out ./
+
+RUN cp /usr/lib/libm* /app
+
+EXPOSE 8080
+
+ENTRYPOINT ["./appMpower"]

+ 7 - 1
frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile

@@ -4,7 +4,7 @@ RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
 
 WORKDIR /app
 COPY src .
-RUN dotnet publish -c Release -o out /p:Driver=odbc
+RUN dotnet publish -c Release -o out /p:Database=postgresql
 
 # Construct the actual image that will run
 FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime
@@ -18,6 +18,12 @@ ENV PATH=/usr/local/unixODBC/bin:$PATH
 WORKDIR /etc/
 COPY odbcinst.ini .
 
+# Full PGO
+ENV DOTNET_TieredPGO 1 
+ENV DOTNET_TC_QuickJitForLoops 1 
+ENV DOTNET_ReadyToRun 0
+
+ENV ASPNETCORE_URLS http://+:8080
 WORKDIR /app
 COPY --from=build /app/out ./
 

+ 6 - 0
frameworks/CSharp/appmpower/appmpower.dockerfile

@@ -4,11 +4,17 @@ RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
 
 WORKDIR /app
 COPY src .
+#RUN dotnet publish appMpower/appMpower.csproj -c Release -o out
 RUN dotnet publish -c Release -o out
 
 # Construct the actual image that will run
 FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime
+# Full PGO
+ENV DOTNET_TieredPGO 1 
+ENV DOTNET_TC_QuickJitForLoops 1 
+ENV DOTNET_ReadyToRun 0
 
+ENV ASPNETCORE_URLS http://+:8080
 WORKDIR /app
 COPY --from=build /app/out ./
 

+ 4 - 4
frameworks/CSharp/appmpower/benchmark_config.json

@@ -39,11 +39,11 @@
         "webserver": "Kestrel",
         "os": "Linux",
         "database_os": "Linux",
-        "display_name": "appMpower [aot-no-reflection,odbc]",
+        "display_name": "appMpower [aot-no-reflection,pg,odbc]",
         "notes": "",
         "versus": "aspnetcore-minimal"
       },
-      "ado-pg": {
+      "odbc-my": {
         "db_url": "/db",
         "query_url": "/queries?c=",
         "update_url": "/updates?c=",
@@ -52,7 +52,7 @@
         "port": 8080,
         "approach": "Realistic",
         "classification": "Platform",
-        "database": "Postgres",
+        "database": "MySQL",
         "framework": "appmpower",
         "language": "C#",
         "orm": "Raw",
@@ -61,7 +61,7 @@
         "webserver": "Kestrel",
         "os": "Linux",
         "database_os": "Linux",
-        "display_name": "appMpower [aot-no-reflection,ado]",
+        "display_name": "appMpower [aot-no-reflection,my,odbc]",
         "notes": "",
         "versus": "aspnetcore-minimal"
       }

+ 2 - 2
frameworks/CSharp/appmpower/config.toml

@@ -30,7 +30,7 @@ platform = ".NET"
 webserver = "Kestrel"
 versus = "aspnetcore-minimal"
 
-[ado-pg]
+[odbc-my]
 urls.db = "/db"
 urls.query = "/queries?c="
 urls.update = "/updates?c="
@@ -38,7 +38,7 @@ urls.fortune = "/fortunes"
 urls.cached_query = "/cached-worlds?c="
 approach = "Realistic"
 classification = "Micro"
-database = "Postgres"
+database = "MySQL"
 database_os = "Linux"
 os = "Linux"
 orm = "Raw"

+ 10 - 0
frameworks/CSharp/appmpower/odbcinst.ini

@@ -5,6 +5,7 @@ Pooling=0
 
 [ODBC Drivers]
 PostgreSQL = Installed
+MariaDB = Installed
 
 ;
 ;  odbcinst.ini
@@ -15,7 +16,16 @@ Description=ODBC for PostgreSQL
 ; in version 08.x. Note that the library can also be installed under an other
 ; path than /usr/local/lib/ following your installation.
 ; This is the standard location used by apt-get install -y unixodbc
+;ON SERVER
 Driver = /usr/lib/x86_64-linux-gnu/odbc/psqlodbcw.so
+;TODOLOCAL: ON MAC
+;Driver =/usr/lib/aarch64-linux-gnu/odbc/psqlodbcw.so
+
 ;Driver =/usr/local/pgsqlodbc/lib/psqlodbcw.so
 Threading = 0
 CPTimeout = 0
+
+[MariaDB]
+Description=MariaDB ODBC for MySQL
+Driver = /usr/lib/libmaodbc.so
+Threading   = 0

+ 0 - 15
frameworks/CSharp/appmpower/src/CachedWorldSerializer.cs

@@ -1,15 +0,0 @@
-using System.Text.Json;
-
-namespace appMpower
-{
-   public class CachedWorldSerializer : Kestrel.IJsonSerializer<CachedWorld>
-   {
-      public void Serialize(Utf8JsonWriter utf8JsonWriter, CachedWorld world)
-      {
-         utf8JsonWriter.WriteStartObject();
-         utf8JsonWriter.WriteNumber("id", world.Id);
-         utf8JsonWriter.WriteNumber("randomNumber", world.RandomNumber);
-         utf8JsonWriter.WriteEndObject();
-      }
-   }
-}

+ 0 - 200
frameworks/CSharp/appmpower/src/Data/DbConnection.cs

@@ -1,200 +0,0 @@
-using System.Collections.Concurrent;
-using System.Data;
-using System.Threading.Tasks;
-
-namespace appMpower.Data
-{
-   public class DbConnection : IDbConnection
-   {
-      private string _connectionString;
-      internal InternalConnection _internalConnection;
-
-      public DbConnection()
-      {
-         _connectionString = DbProviderFactory.ConnectionString;
-      }
-
-      public DbConnection(string connectionString)
-      {
-         _connectionString = connectionString;
-      }
-
-      internal ConcurrentDictionary<string, DbCommand> DbCommands
-      {
-         get
-         {
-            return _internalConnection.DbCommands;
-         }
-         set
-         {
-            _internalConnection.DbCommands = value;
-         }
-      }
-
-      public short Number
-      {
-         get
-         {
-            return _internalConnection.Number;
-         }
-         set
-         {
-            _internalConnection.Number = value;
-         }
-      }
-
-      public IDbConnection Connection
-      {
-         get
-         {
-            return _internalConnection.DbConnection;
-         }
-         set
-         {
-            _internalConnection.DbConnection = value;
-         }
-      }
-
-      public string ConnectionString
-      {
-         get
-         {
-            return _internalConnection.DbConnection.ConnectionString;
-         }
-         set
-         {
-            _internalConnection.DbConnection.ConnectionString = value;
-         }
-      }
-
-      public int ConnectionTimeout
-      {
-         get
-         {
-            return _internalConnection.DbConnection.ConnectionTimeout;
-         }
-      }
-
-      public string Database
-      {
-         get
-         {
-            return _internalConnection.DbConnection.Database;
-         }
-      }
-
-      public ConnectionState State
-      {
-         get
-         {
-            if (_internalConnection is null) return ConnectionState.Closed;
-            return _internalConnection.DbConnection.State;
-         }
-      }
-
-      public IDbTransaction BeginTransaction()
-      {
-         return _internalConnection.DbConnection.BeginTransaction();
-      }
-
-      public IDbTransaction BeginTransaction(IsolationLevel il)
-      {
-         return _internalConnection.DbConnection.BeginTransaction(il);
-      }
-
-      public void ChangeDatabase(string databaseName)
-      {
-         _internalConnection.DbConnection.ChangeDatabase(databaseName);
-      }
-
-      public void Close()
-      {
-         _internalConnection.DbConnection.Close();
-      }
-
-      public async Task CloseAsync()
-      {
-         await (_internalConnection.DbConnection as System.Data.Common.DbConnection).CloseAsync();
-      }
-
-      public IDbCommand CreateCommand()
-      {
-         return _internalConnection.DbConnection.CreateCommand();
-      }
-
-      public void Open()
-      {
-         if (_internalConnection.DbConnection.State == ConnectionState.Closed)
-         {
-            _internalConnection.DbConnection.Open();
-         }
-      }
-
-      public void Dispose()
-      {
-#if ADO
-         _internalConnection.DbConnection.Dispose();
-         _internalConnection.Dispose();
-#else
-         DbConnections.Release(_internalConnection);
-#endif
-      }
-
-      public async Task OpenAsync()
-      {
-#if ADO && POSTGRESQL
-         _internalConnection = new(); 
-         _internalConnection.DbConnection = new Npgsql.NpgsqlConnection(_connectionString);
-#else
-         if (_internalConnection is null)
-         {
-            _internalConnection = await DbConnections.GetConnection(_connectionString);
-         }
-#endif
-
-         if (_internalConnection.DbConnection.State == ConnectionState.Closed)
-         {
-            await (_internalConnection.DbConnection as System.Data.Common.DbConnection).OpenAsync();
-         }
-      }
-
-      internal DbCommand GetCommand(string commandText, CommandType commandType, DbCommand dbCommand)
-      {
-#if ADO
-         dbCommand.Command = _internalConnection.DbConnection.CreateCommand();
-         dbCommand.Command.CommandText = commandText;
-         dbCommand.Command.CommandType = commandType;
-         dbCommand.DbConnection = this;
-#else
-         DbCommand internalCommand;
-
-         if (_internalConnection.DbCommands.TryRemove(commandText, out internalCommand))
-         {
-            dbCommand.Command = internalCommand.Command;
-            dbCommand.DbConnection = internalCommand.DbConnection;
-         }
-         else
-         {
-            dbCommand.Command = _internalConnection.DbConnection.CreateCommand();
-            dbCommand.Command.CommandText = commandText;
-            dbCommand.Command.CommandType = commandType;
-            dbCommand.DbConnection = this;
-
-            //For non odbc drivers like Npgsql which do not support Prepare
-            dbCommand.Command.Prepare();
-
-            //Console.WriteLine("prepare pool connection: " + this._internalConnection.Number + " for command " + _internalConnection.DbCommands.Count);
-         }
-#endif
-
-         return dbCommand;
-      }
-
-      public void ReleaseCommand(DbCommand dbCommand)
-      {
-#if !ADO
-         _internalConnection.DbCommands.TryAdd(dbCommand.CommandText, dbCommand);
-#endif
-      }
-   }
-}

+ 0 - 67
frameworks/CSharp/appmpower/src/Data/DbConnections.cs

@@ -1,67 +0,0 @@
-using System.Collections.Concurrent;
-using System.Threading.Tasks;
-
-namespace appMpower.Data
-{
-   public static class DbConnections
-   {
-      private static bool _connectionsCreated = false;
-      private static short _createdConnections = 0;
-      private static short _maxConnections = 500;
-
-      private static ConcurrentStack<InternalConnection> _stack = new();
-      private static ConcurrentQueue<TaskCompletionSource<InternalConnection>> _waitingQueue = new();
-
-      public static async Task<InternalConnection> GetConnection(string connectionString)
-      {
-         InternalConnection internalConnection = null;
-
-         if (_connectionsCreated)
-         {
-            if (!_stack.TryPop(out internalConnection))
-            {
-               internalConnection = await GetDbConnectionAsync();
-            }
-
-            return internalConnection;
-         }
-         else
-         {
-            internalConnection = new InternalConnection();
-            internalConnection.DbConnection = new System.Data.Odbc.OdbcConnection(connectionString);
-
-            _createdConnections++;
-
-            if (_createdConnections == _maxConnections) _connectionsCreated = true;
-
-            internalConnection.Number = _createdConnections;
-            internalConnection.DbCommands = new ConcurrentDictionary<string, DbCommand>();
-            //Console.WriteLine("opened connection number: " + dbConnection.Number);
-
-            return internalConnection;
-         }
-      }
-
-      public static Task<InternalConnection> GetDbConnectionAsync()
-      {
-         var taskCompletionSource = new TaskCompletionSource<InternalConnection>(TaskCreationOptions.RunContinuationsAsynchronously);
-
-         _waitingQueue.Enqueue(taskCompletionSource);
-         return taskCompletionSource.Task;
-      }
-
-      public static void Release(InternalConnection internalConnection)
-      {
-         TaskCompletionSource<InternalConnection> taskCompletionSource;
-
-         if (_waitingQueue.TryDequeue(out taskCompletionSource))
-         {
-            taskCompletionSource.SetResult(internalConnection);
-         }
-         else
-         {
-            _stack.Push(internalConnection);
-         }
-      }
-   }
-}

+ 0 - 17
frameworks/CSharp/appmpower/src/Data/DbProviderFactory.cs

@@ -1,17 +0,0 @@
-using System.Data;
-
-namespace appMpower.Data
-{
-   public static class DbProviderFactory
-   {
-#if MYSQL
-      public const string ConnectionString = "Driver={MariaDB};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;Pooling=false;OPTIONS=67108864;FLAG_FORWARD_CURSOR=1"; 
-#elif ADO
-      public const string ConnectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=0;Maximum Pool Size=18;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000"; 
-      //public const string ConnectionString = "Server=localhost;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=18;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000"; 
-#else
-      public const string ConnectionString = "Driver={PostgreSQL};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;UseServerSidePrepare=1;Pooling=false";
-      //public const string ConnectionString = "Driver={PostgreSQL};Server=localhost;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;UseServerSidePrepare=1;Pooling=false";
-#endif
-   }
-}

+ 0 - 16
frameworks/CSharp/appmpower/src/Data/InternalConnection.cs

@@ -1,16 +0,0 @@
-using System.Collections.Concurrent;
-using System.Data;
-
-namespace appMpower.Data
-{
-   public class InternalConnection : System.IDisposable
-   {
-      public short Number { get; set; }
-      public IDbConnection DbConnection { get; set; }
-      public ConcurrentDictionary<string, DbCommand> DbCommands { get; set; }
-
-      public void Dispose()
-      {
-      }
-   }
-}

+ 0 - 117
frameworks/CSharp/appmpower/src/HttpApplication.cs

@@ -1,117 +0,0 @@
-using System;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Hosting.Server;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Http.Features;
-using appMpower.Kestrel;
-
-namespace appMpower
-{
-   public class HttpApplication : IHttpApplication<IFeatureCollection>
-   {
-      public static readonly byte[] _plainText = Encoding.UTF8.GetBytes("Hello, World!");
-      private readonly static JsonMessageSerializer _jsonMessageSerializer = new JsonMessageSerializer();
-      private readonly static WorldSerializer _worldSerializer = new WorldSerializer();
-      private readonly static CachedWorldSerializer _cachedWorldSerializer = new CachedWorldSerializer();
-
-      public IFeatureCollection CreateContext(IFeatureCollection featureCollection)
-      {
-         return featureCollection;
-      }
-
-      public async Task ProcessRequestAsync(IFeatureCollection featureCollection)
-      {
-         var request = featureCollection as IHttpRequestFeature;
-         var httpResponse = featureCollection as IHttpResponseFeature;
-         var httpResponseBody = featureCollection as IHttpResponseBodyFeature;
-
-         PathString pathString = request.Path;
-
-         if (pathString.HasValue)
-         {
-            int pathStringLength = pathString.Value.Length;
-            string pathStringStart = pathString.Value.Substring(1, 1);
-
-            if (pathStringLength == 10 && pathStringStart == "p")
-            {
-               //await PlainText.RenderAsync(httpResponse.Headers, httpResponseBody.Writer, _plainText);
-               PlainText.Render(httpResponse.Headers, httpResponseBody, _plainText);
-               return;
-            }
-            else if (pathStringLength == 5 && pathStringStart == "j")
-            {
-               Json.RenderOne(httpResponse.Headers, httpResponseBody.Writer, new JsonMessage { message = "Hello, World!" }, _jsonMessageSerializer);
-               return;
-            }
-            else if (pathStringLength == 3 && pathStringStart == "d")
-            {
-               Json.RenderOne(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadSingleQueryRow(), _worldSerializer);
-               return;
-            }
-            else if (pathStringLength == 8 && pathStringStart == "q")
-            {
-               int count = 1;
-
-               if (!Int32.TryParse(request.QueryString.Substring(request.QueryString.LastIndexOf("=") + 1), out count) || count < 1)
-               {
-                  count = 1;
-               }
-               else if (count > 500)
-               {
-                  count = 500;
-               }
-
-#if ADO
-               Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadMultipleQueriesRows(count), _worldSerializer);
-#else
-               Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.ReadMultipleRows(count), _worldSerializer);
-#endif
-
-               return;
-            }
-            else if (pathStringLength == 9 && pathStringStart == "f")
-            {
-               await FortunesView.Render(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadFortunesRows());
-               return;
-            }
-            else if (pathStringLength == 8 && pathStringStart == "u")
-            {
-               int count = 1;
-
-               if (!Int32.TryParse(request.QueryString.Substring(request.QueryString.LastIndexOf("=") + 1), out count) || count < 1)
-               {
-                  count = 1;
-               }
-               else if (count > 500)
-               {
-                  count = 500;
-               }
-
-               Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadMultipleUpdatesRows(count), _worldSerializer);
-               return;
-            }
-            else if (pathStringLength == 14 && pathStringStart == "c")
-            {
-               int count = 1;
-
-               if (!Int32.TryParse(request.QueryString.Substring(request.QueryString.LastIndexOf("=") + 1), out count) || count < 1)
-               {
-                  count = 1;
-               }
-               else if (count > 500)
-               {
-                  count = 500;
-               }
-
-               Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadCachedQueries(count), _cachedWorldSerializer);
-               return;
-            }
-         }
-      }
-
-      public void DisposeContext(IFeatureCollection featureCollection, Exception exception)
-      {
-      }
-   }
-}

+ 0 - 7
frameworks/CSharp/appmpower/src/JsonMessage.cs

@@ -1,7 +0,0 @@
-namespace appMpower
-{
-   public struct JsonMessage
-   {
-      public string message { get; set; }
-   }
-}

+ 0 - 58
frameworks/CSharp/appmpower/src/Kestrel/Json.cs

@@ -1,58 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO.Pipelines;
-using System.Text.Json;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Primitives;
-
-namespace appMpower.Kestrel
-{
-   public static class Json
-   {
-      private readonly static KeyValuePair<string, StringValues> _headerServer =
-         new KeyValuePair<string, StringValues>("Server", "k");
-      private readonly static KeyValuePair<string, StringValues> _headerContentType =
-         new KeyValuePair<string, StringValues>("Content-Type", "application/json");
-
-      [ThreadStatic]
-      private static Utf8JsonWriter _utf8JsonWriter;
-
-      public static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions
-      {
-         SkipValidation = true
-      };
-
-      public static void RenderOne<T>(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, T t, IJsonSerializer<T> jsonSerializer)
-      {
-         headerDictionary.Add(_headerServer);
-         headerDictionary.Add(_headerContentType);
-
-         Utf8JsonWriter utf8JsonWriter = _utf8JsonWriter ??= new Utf8JsonWriter(pipeWriter, new JsonWriterOptions { SkipValidation = true });
-         utf8JsonWriter.Reset(pipeWriter);
-
-         jsonSerializer.Serialize(utf8JsonWriter, t);
-         utf8JsonWriter.Flush();
-         headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", utf8JsonWriter.BytesCommitted.ToString()));
-      }
-
-      public static void RenderMany<T>(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, T[] tArray, IJsonSerializer<T> jsonSerializer)
-      {
-         headerDictionary.Add(_headerServer);
-         headerDictionary.Add(_headerContentType);
-
-         Utf8JsonWriter utf8JsonWriter = _utf8JsonWriter ??= new Utf8JsonWriter(pipeWriter, new JsonWriterOptions { SkipValidation = true });
-         utf8JsonWriter.Reset(pipeWriter);
-
-         utf8JsonWriter.WriteStartArray();
-
-         foreach (var t in tArray)
-         {
-            jsonSerializer.Serialize(utf8JsonWriter, t);
-         }
-
-         utf8JsonWriter.WriteEndArray();
-         utf8JsonWriter.Flush();
-         headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", utf8JsonWriter.BytesCommitted.ToString()));
-      }
-   }
-}

+ 0 - 38
frameworks/CSharp/appmpower/src/Kestrel/PlainText.cs

@@ -1,38 +0,0 @@
-using System;
-using System.Threading.Tasks;
-using System.Collections.Generic;
-using System.IO.Pipelines;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Primitives;
-using Microsoft.AspNetCore.Http.Features;
-
-namespace appMpower.Kestrel
-{
-   public static class PlainText
-   {
-      private readonly static KeyValuePair<string, StringValues> _headerServer =
-         new KeyValuePair<string, StringValues>("Server", new StringValues("k"));
-      private readonly static KeyValuePair<string, StringValues> _headerContentType =
-         new KeyValuePair<string, StringValues>("Content-Type", new StringValues("text/plain"));
-
-      public static async Task RenderAsync(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, ReadOnlyMemory<byte> utf8String)
-      {
-         headerDictionary.Add(_headerServer);
-         headerDictionary.Add(_headerContentType);
-         headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", utf8String.Length.ToString()));
-
-         await pipeWriter.WriteAsync(utf8String);
-         pipeWriter.Complete();
-      }
-
-      public static void Render(IHeaderDictionary headerDictionary, IHttpResponseBodyFeature httpResponseBodyFeature, byte[] utf8String)
-      {
-         headerDictionary.Add(_headerServer);
-         headerDictionary.Add(_headerContentType);
-         int length = utf8String.Length;
-         headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", length.ToString()));
-
-         httpResponseBodyFeature.Stream.Write(utf8String, 0, length);
-      }
-   }
-}

+ 0 - 25
frameworks/CSharp/appmpower/src/Kestrel/ServiceProvider.cs

@@ -1,25 +0,0 @@
-using System;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
-
-namespace appMpower.Kestrel
-{
-   public class ServiceProvider : ISupportRequiredService, IServiceProvider
-   {
-      public object GetRequiredService(Type serviceType)
-      {
-         return GetService(serviceType);
-      }
-
-      public object GetService(Type serviceType)
-      {
-         if (serviceType == typeof(ILoggerFactory))
-         {
-            return NullLoggerFactory.Instance;
-         }
-
-         return null;
-      }
-   }
-}

+ 0 - 257
frameworks/CSharp/appmpower/src/Memory/CacheEntry.cs

@@ -1,257 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Primitives;
-using Microsoft.Extensions.Caching.Memory;
-
-namespace appMpower.Memory
-{
-   internal sealed partial class CacheEntry : ICacheEntry
-   {
-      private static readonly Action<object> ExpirationCallback = ExpirationTokensExpired;
-
-      private readonly MemoryCache _cache;
-
-      private CacheEntryTokens _tokens; // might be null if user is not using the tokens or callbacks
-      private TimeSpan? _absoluteExpirationRelativeToNow;
-      private TimeSpan? _slidingExpiration;
-      private long? _size;
-      private CacheEntry _previous; // this field is not null only before the entry is added to the cache and tracking is enabled
-      private object _value;
-      private CacheEntryState _state;
-
-      internal CacheEntry(object key, MemoryCache memoryCache)
-      {
-         Key = key ?? throw new ArgumentNullException(nameof(key));
-         _cache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache));
-         _previous = memoryCache.TrackLinkedCacheEntries ? CacheEntryHelper.EnterScope(this) : null;
-         _state = new CacheEntryState(CacheItemPriority.Normal);
-      }
-
-      /// <summary>
-      /// Gets or sets an absolute expiration date for the cache entry.
-      /// </summary>
-      public DateTimeOffset? AbsoluteExpiration { get; set; }
-
-      /// <summary>
-      /// Gets or sets an absolute expiration time, relative to now.
-      /// </summary>
-      public TimeSpan? AbsoluteExpirationRelativeToNow
-      {
-         get => _absoluteExpirationRelativeToNow;
-         set
-         {
-            // this method does not set AbsoluteExpiration as it would require calling Clock.UtcNow twice:
-            // once here and once in MemoryCache.SetEntry
-
-            if (value <= TimeSpan.Zero)
-            {
-               throw new ArgumentOutOfRangeException(
-                   nameof(AbsoluteExpirationRelativeToNow),
-                   value,
-                   "The relative expiration value must be positive.");
-            }
-
-            _absoluteExpirationRelativeToNow = value;
-         }
-      }
-
-      /// <summary>
-      /// Gets or sets how long a cache entry can be inactive (e.g. not accessed) before it will be removed.
-      /// This will not extend the entry lifetime beyond the absolute expiration (if set).
-      /// </summary>
-      public TimeSpan? SlidingExpiration
-      {
-         get => _slidingExpiration;
-         set
-         {
-            if (value <= TimeSpan.Zero)
-            {
-               throw new ArgumentOutOfRangeException(
-                   nameof(SlidingExpiration),
-                   value,
-                   "The sliding expiration value must be positive.");
-            }
-
-            _slidingExpiration = value;
-         }
-      }
-
-      /// <summary>
-      /// Gets the <see cref="IChangeToken"/> instances which cause the cache entry to expire.
-      /// </summary>
-      public IList<IChangeToken> ExpirationTokens => GetOrCreateTokens().ExpirationTokens;
-
-      /// <summary>
-      /// Gets or sets the callbacks will be fired after the cache entry is evicted from the cache.
-      /// </summary>
-      public IList<PostEvictionCallbackRegistration> PostEvictionCallbacks => GetOrCreateTokens().PostEvictionCallbacks;
-
-      /// <summary>
-      /// Gets or sets the priority for keeping the cache entry in the cache during a
-      /// memory pressure triggered cleanup. The default is <see cref="CacheItemPriority.Normal"/>.
-      /// </summary>
-      public CacheItemPriority Priority { get => _state.Priority; set => _state.Priority = value; }
-
-      /// <summary>
-      /// Gets or sets the size of the cache entry value.
-      /// </summary>
-      public long? Size
-      {
-         get => _size;
-         set
-         {
-            if (value < 0)
-            {
-               throw new ArgumentOutOfRangeException(nameof(value), value, $"{nameof(value)} must be non-negative.");
-            }
-
-            _size = value;
-         }
-      }
-
-      public object Key { get; private set; }
-
-      public object Value
-      {
-         get => _value;
-         set
-         {
-            _value = value;
-            _state.IsValueSet = true;
-         }
-      }
-
-      internal DateTimeOffset LastAccessed { get; set; }
-
-      internal EvictionReason EvictionReason { get => _state.EvictionReason; private set => _state.EvictionReason = value; }
-
-      public void Dispose()
-      {
-         if (!_state.IsDisposed)
-         {
-            _state.IsDisposed = true;
-
-            if (_cache.TrackLinkedCacheEntries)
-            {
-               CacheEntryHelper.ExitScope(this, _previous);
-            }
-
-            // Don't commit or propagate options if the CacheEntry Value was never set.
-            // We assume an exception occurred causing the caller to not set the Value successfully,
-            // so don't use this entry.
-            if (_state.IsValueSet)
-            {
-               _cache.SetEntry(this);
-
-               if (_previous != null && CanPropagateOptions())
-               {
-                  PropagateOptions(_previous);
-               }
-            }
-
-            _previous = null; // we don't want to root unnecessary objects
-         }
-      }
-
-      [MethodImpl(MethodImplOptions.AggressiveInlining)] // added based on profiling
-      internal bool CheckExpired(in DateTimeOffset now)
-          => _state.IsExpired
-              || CheckForExpiredTime(now)
-              || (_tokens != null && _tokens.CheckForExpiredTokens(this));
-
-      internal void SetExpired(EvictionReason reason)
-      {
-         if (EvictionReason == EvictionReason.None)
-         {
-            EvictionReason = reason;
-         }
-         _state.IsExpired = true;
-         _tokens?.DetachTokens();
-      }
-
-      [MethodImpl(MethodImplOptions.AggressiveInlining)] // added based on profiling
-      private bool CheckForExpiredTime(in DateTimeOffset now)
-      {
-         if (!AbsoluteExpiration.HasValue && !_slidingExpiration.HasValue)
-         {
-            return false;
-         }
-
-         return FullCheck(now);
-
-         bool FullCheck(in DateTimeOffset offset)
-         {
-            if (AbsoluteExpiration.HasValue && AbsoluteExpiration.Value <= offset)
-            {
-               SetExpired(EvictionReason.Expired);
-               return true;
-            }
-
-            if (_slidingExpiration.HasValue
-                && (offset - LastAccessed) >= _slidingExpiration)
-            {
-               SetExpired(EvictionReason.Expired);
-               return true;
-            }
-
-            return false;
-         }
-      }
-
-      internal void AttachTokens() => _tokens?.AttachTokens(this);
-
-      private static void ExpirationTokensExpired(object obj)
-      {
-         // start a new thread to avoid issues with callbacks called from RegisterChangeCallback
-         Task.Factory.StartNew(state =>
-         {
-            var entry = (CacheEntry)state;
-            entry.SetExpired(EvictionReason.TokenExpired);
-            entry._cache.EntryExpired(entry);
-         }, obj, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
-      }
-
-      internal void InvokeEvictionCallbacks() => _tokens?.InvokeEvictionCallbacks(this);
-
-      // this simple check very often allows us to avoid expensive call to PropagateOptions(CacheEntryHelper.Current)
-      [MethodImpl(MethodImplOptions.AggressiveInlining)] // added based on profiling
-      internal bool CanPropagateOptions() => (_tokens != null && _tokens.CanPropagateTokens()) || AbsoluteExpiration.HasValue;
-
-      internal void PropagateOptions(CacheEntry parent)
-      {
-         if (parent == null)
-         {
-            return;
-         }
-
-         // Copy expiration tokens and AbsoluteExpiration to the cache entries hierarchy.
-         // We do this regardless of it gets cached because the tokens are associated with the value we'll return.
-         _tokens?.PropagateTokens(parent);
-
-         if (AbsoluteExpiration.HasValue)
-         {
-            if (!parent.AbsoluteExpiration.HasValue || AbsoluteExpiration < parent.AbsoluteExpiration)
-            {
-               parent.AbsoluteExpiration = AbsoluteExpiration;
-            }
-         }
-      }
-
-      private CacheEntryTokens GetOrCreateTokens()
-      {
-         if (_tokens != null)
-         {
-            return _tokens;
-         }
-
-         CacheEntryTokens result = new CacheEntryTokens();
-         return Interlocked.CompareExchange(ref _tokens, result, null) ?? result;
-      }
-   }
-}

+ 0 - 32
frameworks/CSharp/appmpower/src/Memory/CacheEntryHelper.cs

@@ -1,32 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics;
-using System.Threading;
-
-namespace appMpower.Memory
-{
-   internal static class CacheEntryHelper
-   {
-      private static readonly AsyncLocal<CacheEntry> _current = new AsyncLocal<CacheEntry>();
-
-      internal static CacheEntry Current
-      {
-         get => _current.Value;
-         private set => _current.Value = value;
-      }
-
-      internal static CacheEntry EnterScope(CacheEntry current)
-      {
-         CacheEntry previous = Current;
-         Current = current;
-         return previous;
-      }
-
-      internal static void ExitScope(CacheEntry current, CacheEntry previous)
-      {
-         Debug.Assert(Current == current, "Entries disposed in invalid order");
-         Current = previous;
-      }
-   }
-}

+ 0 - 62
frameworks/CSharp/appmpower/src/Memory/CacheEntryState.cs

@@ -1,62 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using Microsoft.Extensions.Caching.Memory;
-
-namespace appMpower.Memory
-{
-   internal sealed partial class CacheEntry
-   {
-      // this type exists just to reduce CacheEntry size by replacing many enum & boolean fields with one of a size of Int32
-      private struct CacheEntryState
-      {
-         private byte _flags;
-         private byte _evictionReason;
-         private byte _priority;
-
-         internal CacheEntryState(CacheItemPriority priority) : this() => _priority = (byte)priority;
-
-         internal bool IsDisposed
-         {
-            get => ((Flags)_flags & Flags.IsDisposed) != 0;
-            set => SetFlag(Flags.IsDisposed, value);
-         }
-
-         internal bool IsExpired
-         {
-            get => ((Flags)_flags & Flags.IsExpired) != 0;
-            set => SetFlag(Flags.IsExpired, value);
-         }
-
-         internal bool IsValueSet
-         {
-            get => ((Flags)_flags & Flags.IsValueSet) != 0;
-            set => SetFlag(Flags.IsValueSet, value);
-         }
-
-         internal EvictionReason EvictionReason
-         {
-            get => (EvictionReason)_evictionReason;
-            set => _evictionReason = (byte)value;
-         }
-
-         internal CacheItemPriority Priority
-         {
-            get => (CacheItemPriority)_priority;
-            set => _priority = (byte)value;
-         }
-
-         private void SetFlag(Flags option, bool value) => _flags = (byte)(value ? (_flags | (byte)option) : (_flags & ~(byte)option));
-
-         [Flags]
-         private enum Flags : byte
-         {
-            Default = 0,
-            IsValueSet = 1 << 0,
-            IsExpired = 1 << 1,
-            IsDisposed = 1 << 2,
-         }
-      }
-   }
-}

+ 0 - 140
frameworks/CSharp/appmpower/src/Memory/CacheEntryTokens.cs

@@ -1,140 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Primitives;
-using Microsoft.Extensions.Caching.Memory;
-
-namespace appMpower.Memory
-{
-   internal sealed partial class CacheEntry
-   {
-      // this type exists just to reduce average CacheEntry size
-      // which typically is not using expiration tokens or callbacks
-      private sealed class CacheEntryTokens
-      {
-         private List<IChangeToken> _expirationTokens;
-         private List<IDisposable> _expirationTokenRegistrations;
-         private List<PostEvictionCallbackRegistration> _postEvictionCallbacks; // this is not really related to tokens, but was moved here to shrink typical CacheEntry size
-
-         internal List<IChangeToken> ExpirationTokens => _expirationTokens ??= new List<IChangeToken>();
-         internal List<PostEvictionCallbackRegistration> PostEvictionCallbacks => _postEvictionCallbacks ??= new List<PostEvictionCallbackRegistration>();
-
-         internal void AttachTokens(CacheEntry cacheEntry)
-         {
-            if (_expirationTokens != null)
-            {
-               lock (this)
-               {
-                  for (int i = 0; i < _expirationTokens.Count; i++)
-                  {
-                     IChangeToken expirationToken = _expirationTokens[i];
-                     if (expirationToken.ActiveChangeCallbacks)
-                     {
-                        _expirationTokenRegistrations ??= new List<IDisposable>(1);
-                        IDisposable registration = expirationToken.RegisterChangeCallback(ExpirationCallback, cacheEntry);
-                        _expirationTokenRegistrations.Add(registration);
-                     }
-                  }
-               }
-            }
-         }
-
-         internal bool CheckForExpiredTokens(CacheEntry cacheEntry)
-         {
-            if (_expirationTokens != null)
-            {
-               for (int i = 0; i < _expirationTokens.Count; i++)
-               {
-                  IChangeToken expiredToken = _expirationTokens[i];
-                  if (expiredToken.HasChanged)
-                  {
-                     cacheEntry.SetExpired(EvictionReason.TokenExpired);
-                     return true;
-                  }
-               }
-            }
-            return false;
-         }
-
-         internal bool CanPropagateTokens() => _expirationTokens != null;
-
-         internal void PropagateTokens(CacheEntry parentEntry)
-         {
-            if (_expirationTokens != null)
-            {
-               lock (this)
-               {
-                  lock (parentEntry.GetOrCreateTokens())
-                  {
-                     foreach (IChangeToken expirationToken in _expirationTokens)
-                     {
-                        parentEntry.AddExpirationToken(expirationToken);
-                     }
-                  }
-               }
-            }
-         }
-
-         internal void DetachTokens()
-         {
-            // _expirationTokenRegistrations is not checked for null, because AttachTokens might initialize it under lock
-            // instead we are checking for _expirationTokens, because if they are not null, then _expirationTokenRegistrations might also be not null
-            if (_expirationTokens != null)
-            {
-               lock (this)
-               {
-                  List<IDisposable> registrations = _expirationTokenRegistrations;
-                  if (registrations != null)
-                  {
-                     _expirationTokenRegistrations = null;
-                     for (int i = 0; i < registrations.Count; i++)
-                     {
-                        IDisposable registration = registrations[i];
-                        registration.Dispose();
-                     }
-                  }
-               }
-            }
-         }
-
-         internal void InvokeEvictionCallbacks(CacheEntry cacheEntry)
-         {
-            if (_postEvictionCallbacks != null)
-            {
-               Task.Factory.StartNew(state => InvokeCallbacks((CacheEntry)state), cacheEntry,
-                   CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
-            }
-         }
-
-         private static void InvokeCallbacks(CacheEntry entry)
-         {
-            List<PostEvictionCallbackRegistration> callbackRegistrations = Interlocked.Exchange(ref entry._tokens._postEvictionCallbacks, null);
-
-            if (callbackRegistrations == null)
-            {
-               return;
-            }
-
-            for (int i = 0; i < callbackRegistrations.Count; i++)
-            {
-               PostEvictionCallbackRegistration registration = callbackRegistrations[i];
-
-               try
-               {
-                  registration.EvictionCallback?.Invoke(entry.Key, entry.Value, entry.EvictionReason, registration.State);
-               }
-               catch (Exception e)
-               {
-                  // This will be invoked on a background thread, don't let it throw.
-                  entry._cache._logger.LogError(e, "EvictionCallback invoked failed");
-               }
-            }
-         }
-      }
-   }
-}

+ 0 - 520
frameworks/CSharp/appmpower/src/Memory/MemoryCache.cs

@@ -1,520 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Internal;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
-using Microsoft.Extensions.Options;
-using Microsoft.Extensions.Caching.Memory;
-
-namespace appMpower.Memory
-{
-   /// <summary>
-   /// An implementation of <see cref="IMemoryCache"/> using a dictionary to
-   /// store its entries.
-   /// </summary>
-   public class MemoryCache : IMemoryCache
-   {
-      internal readonly ILogger _logger;
-
-      private readonly MemoryCacheOptions _options;
-      private readonly ConcurrentDictionary<object, CacheEntry> _entries;
-
-      private long _cacheSize;
-      private bool _disposed;
-      private DateTimeOffset _lastExpirationScan;
-
-      /// <summary>
-      /// Creates a new <see cref="MemoryCache"/> instance.
-      /// </summary>
-      /// <param name="optionsAccessor">The options of the cache.</param>
-      public MemoryCache(IOptions<MemoryCacheOptions> optionsAccessor)
-          : this(optionsAccessor, NullLoggerFactory.Instance) { }
-
-      /// <summary>
-      /// Creates a new <see cref="MemoryCache"/> instance.
-      /// </summary>
-      /// <param name="optionsAccessor">The options of the cache.</param>
-      /// <param name="loggerFactory">The factory used to create loggers.</param>
-      public MemoryCache(IOptions<MemoryCacheOptions> optionsAccessor, ILoggerFactory loggerFactory)
-      {
-         if (optionsAccessor == null)
-         {
-            throw new ArgumentNullException(nameof(optionsAccessor));
-         }
-
-         if (loggerFactory == null)
-         {
-            throw new ArgumentNullException(nameof(loggerFactory));
-         }
-
-         _options = optionsAccessor.Value;
-         //_logger = loggerFactory.CreateLogger<MemoryCache>();
-         _logger = loggerFactory.CreateLogger("MemoryCache");
-
-         _entries = new ConcurrentDictionary<object, CacheEntry>();
-
-         if (_options.Clock == null)
-         {
-            _options.Clock = new SystemClock();
-         }
-
-         _lastExpirationScan = _options.Clock.UtcNow;
-         TrackLinkedCacheEntries = _options.TrackLinkedCacheEntries; // we store the setting now so it's consistent for entire MemoryCache lifetime
-      }
-
-      /// <summary>
-      /// Cleans up the background collection events.
-      /// </summary>
-      ~MemoryCache() => Dispose(false);
-
-      /// <summary>
-      /// Gets the count of the current entries for diagnostic purposes.
-      /// </summary>
-      public int Count => _entries.Count;
-
-      // internal for testing
-      internal long Size { get => Interlocked.Read(ref _cacheSize); }
-
-      internal bool TrackLinkedCacheEntries { get; }
-
-      private ICollection<KeyValuePair<object, CacheEntry>> EntriesCollection => _entries;
-
-      /// <inheritdoc />
-      public ICacheEntry CreateEntry(object key)
-      {
-         CheckDisposed();
-         ValidateCacheKey(key);
-
-         return new CacheEntry(key, this);
-      }
-
-      internal void SetEntry(CacheEntry entry)
-      {
-         if (_disposed)
-         {
-            // No-op instead of throwing since this is called during CacheEntry.Dispose
-            return;
-         }
-
-         if (_options.SizeLimit.HasValue && !entry.Size.HasValue)
-         {
-            //throw new InvalidOperationException(SR.Format(SR.CacheEntryHasEmptySize, nameof(entry.Size), nameof(_options.SizeLimit)));
-            throw new InvalidOperationException();
-         }
-
-         DateTimeOffset utcNow = _options.Clock.UtcNow;
-
-         DateTimeOffset? absoluteExpiration = null;
-         if (entry.AbsoluteExpirationRelativeToNow.HasValue)
-         {
-            absoluteExpiration = utcNow + entry.AbsoluteExpirationRelativeToNow;
-         }
-         else if (entry.AbsoluteExpiration.HasValue)
-         {
-            absoluteExpiration = entry.AbsoluteExpiration;
-         }
-
-         // Applying the option's absolute expiration only if it's not already smaller.
-         // This can be the case if a dependent cache entry has a smaller value, and
-         // it was set by cascading it to its parent.
-         if (absoluteExpiration.HasValue)
-         {
-            if (!entry.AbsoluteExpiration.HasValue || absoluteExpiration.Value < entry.AbsoluteExpiration.Value)
-            {
-               entry.AbsoluteExpiration = absoluteExpiration;
-            }
-         }
-
-         // Initialize the last access timestamp at the time the entry is added
-         entry.LastAccessed = utcNow;
-
-         if (_entries.TryGetValue(entry.Key, out CacheEntry priorEntry))
-         {
-            priorEntry.SetExpired(EvictionReason.Replaced);
-         }
-
-         bool exceedsCapacity = UpdateCacheSizeExceedsCapacity(entry);
-
-         if (!entry.CheckExpired(utcNow) && !exceedsCapacity)
-         {
-            bool entryAdded = false;
-
-            if (priorEntry == null)
-            {
-               // Try to add the new entry if no previous entries exist.
-               entryAdded = _entries.TryAdd(entry.Key, entry);
-            }
-            else
-            {
-               // Try to update with the new entry if a previous entries exist.
-               entryAdded = _entries.TryUpdate(entry.Key, entry, priorEntry);
-
-               if (entryAdded)
-               {
-                  if (_options.SizeLimit.HasValue)
-                  {
-                     // The prior entry was removed, decrease the by the prior entry's size
-                     Interlocked.Add(ref _cacheSize, -priorEntry.Size.Value);
-                  }
-               }
-               else
-               {
-                  // The update will fail if the previous entry was removed after retrival.
-                  // Adding the new entry will succeed only if no entry has been added since.
-                  // This guarantees removing an old entry does not prevent adding a new entry.
-                  entryAdded = _entries.TryAdd(entry.Key, entry);
-               }
-            }
-
-            if (entryAdded)
-            {
-               entry.AttachTokens();
-            }
-            else
-            {
-               if (_options.SizeLimit.HasValue)
-               {
-                  // Entry could not be added, reset cache size
-                  Interlocked.Add(ref _cacheSize, -entry.Size.Value);
-               }
-               entry.SetExpired(EvictionReason.Replaced);
-               entry.InvokeEvictionCallbacks();
-            }
-
-            if (priorEntry != null)
-            {
-               priorEntry.InvokeEvictionCallbacks();
-            }
-         }
-         else
-         {
-            if (exceedsCapacity)
-            {
-               // The entry was not added due to overcapacity
-               entry.SetExpired(EvictionReason.Capacity);
-
-               TriggerOvercapacityCompaction();
-            }
-            else
-            {
-               if (_options.SizeLimit.HasValue)
-               {
-                  // Entry could not be added due to being expired, reset cache size
-                  Interlocked.Add(ref _cacheSize, -entry.Size.Value);
-               }
-            }
-
-            entry.InvokeEvictionCallbacks();
-            if (priorEntry != null)
-            {
-               RemoveEntry(priorEntry);
-            }
-         }
-
-         StartScanForExpiredItemsIfNeeded(utcNow);
-      }
-
-      /// <inheritdoc />
-      public bool TryGetValue(object key, out object result)
-      {
-         ValidateCacheKey(key);
-         CheckDisposed();
-
-         DateTimeOffset utcNow = _options.Clock.UtcNow;
-
-         if (_entries.TryGetValue(key, out CacheEntry entry))
-         {
-            // Check if expired due to expiration tokens, timers, etc. and if so, remove it.
-            // Allow a stale Replaced value to be returned due to concurrent calls to SetExpired during SetEntry.
-            if (!entry.CheckExpired(utcNow) || entry.EvictionReason == EvictionReason.Replaced)
-            {
-               entry.LastAccessed = utcNow;
-               result = entry.Value;
-
-               if (TrackLinkedCacheEntries && entry.CanPropagateOptions())
-               {
-                  // When this entry is retrieved in the scope of creating another entry,
-                  // that entry needs a copy of these expiration tokens.
-                  entry.PropagateOptions(CacheEntryHelper.Current);
-               }
-
-               StartScanForExpiredItemsIfNeeded(utcNow);
-
-               return true;
-            }
-            else
-            {
-               // TODO: For efficiency queue this up for batch removal
-               RemoveEntry(entry);
-            }
-         }
-
-         StartScanForExpiredItemsIfNeeded(utcNow);
-
-         result = null;
-         return false;
-      }
-
-      /// <inheritdoc />
-      public void Remove(object key)
-      {
-         ValidateCacheKey(key);
-
-         CheckDisposed();
-         if (_entries.TryRemove(key, out CacheEntry entry))
-         {
-            if (_options.SizeLimit.HasValue)
-            {
-               Interlocked.Add(ref _cacheSize, -entry.Size.Value);
-            }
-
-            entry.SetExpired(EvictionReason.Removed);
-            entry.InvokeEvictionCallbacks();
-         }
-
-         StartScanForExpiredItemsIfNeeded(_options.Clock.UtcNow);
-      }
-
-      private void RemoveEntry(CacheEntry entry)
-      {
-         if (EntriesCollection.Remove(new KeyValuePair<object, CacheEntry>(entry.Key, entry)))
-         {
-            if (_options.SizeLimit.HasValue)
-            {
-               Interlocked.Add(ref _cacheSize, -entry.Size.Value);
-            }
-            entry.InvokeEvictionCallbacks();
-         }
-      }
-
-      internal void EntryExpired(CacheEntry entry)
-      {
-         // TODO: For efficiency consider processing these expirations in batches.
-         RemoveEntry(entry);
-         StartScanForExpiredItemsIfNeeded(_options.Clock.UtcNow);
-      }
-
-      // Called by multiple actions to see how long it's been since we last checked for expired items.
-      // If sufficient time has elapsed then a scan is initiated on a background task.
-      [MethodImpl(MethodImplOptions.AggressiveInlining)]
-      private void StartScanForExpiredItemsIfNeeded(DateTimeOffset utcNow)
-      {
-         if (_options.ExpirationScanFrequency < utcNow - _lastExpirationScan)
-         {
-            ScheduleTask(utcNow);
-         }
-
-         void ScheduleTask(DateTimeOffset utcNow)
-         {
-            _lastExpirationScan = utcNow;
-            Task.Factory.StartNew(state => ScanForExpiredItems((MemoryCache)state), this,
-                CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
-         }
-      }
-
-      private static void ScanForExpiredItems(MemoryCache cache)
-      {
-         DateTimeOffset now = cache._lastExpirationScan = cache._options.Clock.UtcNow;
-
-         foreach (KeyValuePair<object, CacheEntry> item in cache._entries)
-         {
-            CacheEntry entry = item.Value;
-
-            if (entry.CheckExpired(now))
-            {
-               cache.RemoveEntry(entry);
-            }
-         }
-      }
-
-      private bool UpdateCacheSizeExceedsCapacity(CacheEntry entry)
-      {
-         if (!_options.SizeLimit.HasValue)
-         {
-            return false;
-         }
-
-         long newSize = 0L;
-         for (int i = 0; i < 100; i++)
-         {
-            long sizeRead = Interlocked.Read(ref _cacheSize);
-            newSize = sizeRead + entry.Size.Value;
-
-            if (newSize < 0 || newSize > _options.SizeLimit)
-            {
-               // Overflow occurred, return true without updating the cache size
-               return true;
-            }
-
-            if (sizeRead == Interlocked.CompareExchange(ref _cacheSize, newSize, sizeRead))
-            {
-               return false;
-            }
-         }
-
-         return true;
-      }
-
-      private void TriggerOvercapacityCompaction()
-      {
-         _logger.LogDebug("Overcapacity compaction triggered");
-
-         // Spawn background thread for compaction
-         ThreadPool.QueueUserWorkItem(s => OvercapacityCompaction((MemoryCache)s), this);
-      }
-
-      private static void OvercapacityCompaction(MemoryCache cache)
-      {
-         long currentSize = Interlocked.Read(ref cache._cacheSize);
-
-         cache._logger.LogDebug($"Overcapacity compaction executing. Current size {currentSize}");
-
-         double? lowWatermark = cache._options.SizeLimit * (1 - cache._options.CompactionPercentage);
-         if (currentSize > lowWatermark)
-         {
-            cache.Compact(currentSize - (long)lowWatermark, entry => entry.Size.Value);
-         }
-
-         cache._logger.LogDebug($"Overcapacity compaction executed. New size {Interlocked.Read(ref cache._cacheSize)}");
-      }
-
-      /// Remove at least the given percentage (0.10 for 10%) of the total entries (or estimated memory?), according to the following policy:
-      /// 1. Remove all expired items.
-      /// 2. Bucket by CacheItemPriority.
-      /// 3. Least recently used objects.
-      /// ?. Items with the soonest absolute expiration.
-      /// ?. Items with the soonest sliding expiration.
-      /// ?. Larger objects - estimated by object graph size, inaccurate.
-      public void Compact(double percentage)
-      {
-         int removalCountTarget = (int)(_entries.Count * percentage);
-         Compact(removalCountTarget, _ => 1);
-      }
-
-      private void Compact(long removalSizeTarget, Func<CacheEntry, long> computeEntrySize)
-      {
-         var entriesToRemove = new List<CacheEntry>();
-         var lowPriEntries = new List<CacheEntry>();
-         var normalPriEntries = new List<CacheEntry>();
-         var highPriEntries = new List<CacheEntry>();
-         long removedSize = 0;
-
-         // Sort items by expired & priority status
-         DateTimeOffset now = _options.Clock.UtcNow;
-         foreach (KeyValuePair<object, CacheEntry> item in _entries)
-         {
-            CacheEntry entry = item.Value;
-            if (entry.CheckExpired(now))
-            {
-               entriesToRemove.Add(entry);
-               removedSize += computeEntrySize(entry);
-            }
-            else
-            {
-               switch (entry.Priority)
-               {
-                  case CacheItemPriority.Low:
-                     lowPriEntries.Add(entry);
-                     break;
-                  case CacheItemPriority.Normal:
-                     normalPriEntries.Add(entry);
-                     break;
-                  case CacheItemPriority.High:
-                     highPriEntries.Add(entry);
-                     break;
-                  case CacheItemPriority.NeverRemove:
-                     break;
-                  default:
-                     throw new NotSupportedException("Not implemented: " + entry.Priority);
-               }
-            }
-         }
-
-         ExpirePriorityBucket(ref removedSize, removalSizeTarget, computeEntrySize, entriesToRemove, lowPriEntries);
-         ExpirePriorityBucket(ref removedSize, removalSizeTarget, computeEntrySize, entriesToRemove, normalPriEntries);
-         ExpirePriorityBucket(ref removedSize, removalSizeTarget, computeEntrySize, entriesToRemove, highPriEntries);
-
-         foreach (CacheEntry entry in entriesToRemove)
-         {
-            RemoveEntry(entry);
-         }
-
-         // Policy:
-         // 1. Least recently used objects.
-         // ?. Items with the soonest absolute expiration.
-         // ?. Items with the soonest sliding expiration.
-         // ?. Larger objects - estimated by object graph size, inaccurate.
-         static void ExpirePriorityBucket(ref long removedSize, long removalSizeTarget, Func<CacheEntry, long> computeEntrySize, List<CacheEntry> entriesToRemove, List<CacheEntry> priorityEntries)
-         {
-            // Do we meet our quota by just removing expired entries?
-            if (removalSizeTarget <= removedSize)
-            {
-               // No-op, we've met quota
-               return;
-            }
-
-            // Expire enough entries to reach our goal
-            // TODO: Refine policy
-
-            // LRU
-            priorityEntries.Sort((e1, e2) => e1.LastAccessed.CompareTo(e2.LastAccessed));
-            foreach (CacheEntry entry in priorityEntries)
-            {
-               entry.SetExpired(EvictionReason.Capacity);
-               entriesToRemove.Add(entry);
-               removedSize += computeEntrySize(entry);
-
-               if (removalSizeTarget <= removedSize)
-               {
-                  break;
-               }
-            }
-         }
-      }
-
-      public void Dispose()
-      {
-         Dispose(true);
-      }
-
-      protected virtual void Dispose(bool disposing)
-      {
-         if (!_disposed)
-         {
-            if (disposing)
-            {
-               GC.SuppressFinalize(this);
-            }
-
-            _disposed = true;
-         }
-      }
-
-      private void CheckDisposed()
-      {
-         if (_disposed)
-         {
-            Throw();
-         }
-
-         static void Throw() => throw new ObjectDisposedException(typeof(MemoryCache).FullName);
-      }
-
-      private static void ValidateCacheKey(object key)
-      {
-         if (key == null)
-         {
-            Throw();
-         }
-
-         static void Throw() => throw new ArgumentNullException(nameof(key));
-      }
-   }
-}

+ 0 - 67
frameworks/CSharp/appmpower/src/Memory/MemoryCacheOptions.cs

@@ -1,67 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using Microsoft.Extensions.Internal;
-using Microsoft.Extensions.Options;
-
-namespace appMpower.Memory
-{
-   public class MemoryCacheOptions : IOptions<MemoryCacheOptions>
-   {
-      private long? _sizeLimit;
-      private double _compactionPercentage = 0.05;
-
-      public ISystemClock Clock { get; set; }
-
-      /// <summary>
-      /// Gets or sets the minimum length of time between successive scans for expired items.
-      /// </summary>
-      public TimeSpan ExpirationScanFrequency { get; set; } = TimeSpan.FromMinutes(1);
-
-      /// <summary>
-      /// Gets or sets the maximum size of the cache.
-      /// </summary>
-      public long? SizeLimit
-      {
-         get => _sizeLimit;
-         set
-         {
-            if (value < 0)
-            {
-               throw new ArgumentOutOfRangeException(nameof(value), value, $"{nameof(value)} must be non-negative.");
-            }
-
-            _sizeLimit = value;
-         }
-      }
-
-      /// <summary>
-      /// Gets or sets the amount to compact the cache by when the maximum size is exceeded.
-      /// </summary>
-      public double CompactionPercentage
-      {
-         get => _compactionPercentage;
-         set
-         {
-            if (value < 0 || value > 1)
-            {
-               throw new ArgumentOutOfRangeException(nameof(value), value, $"{nameof(value)} must be between 0 and 1 inclusive.");
-            }
-
-            _compactionPercentage = value;
-         }
-      }
-
-      /// <summary>
-      /// Gets or sets whether to track linked entries. Disabled by default.
-      /// </summary>
-      /// <remarks>Prior to .NET 7 this feature was always enabled.</remarks>
-      public bool TrackLinkedCacheEntries { get; set; }
-
-      MemoryCacheOptions IOptions<MemoryCacheOptions>.Value
-      {
-         get { return this; }
-      }
-   }
-}

+ 0 - 24
frameworks/CSharp/appmpower/src/Microsoft/CachKey.cs

@@ -1,24 +0,0 @@
-using System;
-
-namespace PlatformBenchmarks
-{
-   public sealed class CacheKey : IEquatable<CacheKey>
-   {
-      private readonly int _value;
-
-      public CacheKey(int value)
-          => _value = value;
-
-      public bool Equals(CacheKey key)
-          => key._value == _value;
-
-      public override bool Equals(object obj)
-          => ReferenceEquals(obj, this);
-
-      public override int GetHashCode()
-          => _value;
-
-      public override string ToString()
-          => _value.ToString();
-   }
-}

+ 0 - 59
frameworks/CSharp/appmpower/src/Microsoft/StringBuilderCache.cs

@@ -1,59 +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.Text;
-
-namespace PlatformBenchmarks
-{
-   internal static class StringBuilderCache
-   {
-      private const int DefaultCapacity = 1386;
-      private const int MaxBuilderSize = DefaultCapacity * 3;
-
-      [ThreadStatic]
-      private static StringBuilder t_cachedInstance;
-
-      /// <summary>Get a StringBuilder for the specified capacity.</summary>
-      /// <remarks>If a StringBuilder of an appropriate size is cached, it will be returned and the cache emptied.</remarks>
-      public static StringBuilder Acquire(int capacity = DefaultCapacity)
-      {
-         if (capacity <= MaxBuilderSize)
-         {
-            StringBuilder sb = t_cachedInstance;
-            if (capacity < DefaultCapacity)
-            {
-               capacity = DefaultCapacity;
-            }
-
-            if (sb != null)
-            {
-               // Avoid stringbuilder block fragmentation by getting a new StringBuilder
-               // when the requested size is larger than the current capacity
-               if (capacity <= sb.Capacity)
-               {
-                  t_cachedInstance = null;
-                  sb.Clear();
-                  return sb;
-               }
-            }
-         }
-         return new StringBuilder(capacity);
-      }
-
-      public static void Release(StringBuilder sb)
-      {
-         if (sb.Capacity <= MaxBuilderSize)
-         {
-            t_cachedInstance = sb;
-         }
-      }
-
-      public static string GetStringAndRelease(StringBuilder sb)
-      {
-         string result = sb.ToString();
-         Release(sb);
-         return result;
-      }
-   }
-}

+ 0 - 42
frameworks/CSharp/appmpower/src/Program.cs

@@ -1,42 +0,0 @@
-using System;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Hosting.Server.Features;
-using Microsoft.AspNetCore.Server.Kestrel.Core;
-using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets;
-using Microsoft.Extensions.Logging.Abstractions;
-using Microsoft.Extensions.Options;
-
-namespace appMpower
-{
-   class Program
-   {
-      static async Task Main(string[] args)
-      {
-         var socketTransportOptions = new SocketTransportOptions();
-         var socketTransportFactory = new SocketTransportFactory(Options.Create(socketTransportOptions), NullLoggerFactory.Instance);
-         var kestrelServerOptions = new KestrelServerOptions();
-
-         kestrelServerOptions.Listen(IPAddress.Any, 8080);
-         kestrelServerOptions.AllowSynchronousIO = true; 
-         kestrelServerOptions.AddServerHeader = false;
-
-         using var kestrelServer = new KestrelServer(Options.Create(kestrelServerOptions), socketTransportFactory, NullLoggerFactory.Instance);
-
-         await kestrelServer.StartAsync(new HttpApplication(), CancellationToken.None);
-
-         Console.WriteLine("Listening on:");
-
-         foreach (var address in kestrelServer.Features.Get<IServerAddressesFeature>().Addresses)
-         {
-            Console.WriteLine(" - " + address);
-         }
-
-         Console.WriteLine("Process CTRL+C to quit");
-         var wh = new ManualResetEventSlim();
-         Console.CancelKeyPress += (sender, e) => wh.Set();
-         wh.Wait();
-      }
-   }
-}

+ 10 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Constants.cs

@@ -0,0 +1,10 @@
+using appMpower.Orm.Data; 
+
+namespace appMpower.Orm
+{
+  public static class Constants
+  {
+    public static Dbms Dbms = Dbms.PostgreSQL; 
+    public static DbProvider DbProvider = DbProvider.ODBC; 
+  }
+}

+ 40 - 63
frameworks/CSharp/appmpower/src/Data/DbCommand.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbCommand.cs

@@ -1,56 +1,40 @@
 using System.Data;
-using System.Threading.Tasks;
+using System.Data.Odbc; 
 
-namespace appMpower.Data
+namespace appMpower.Orm.Data
 {
    public class DbCommand : IDbCommand
    {
-      private IDbCommand _dbCommand;
+      private OdbcCommand _odbcCommand;
       private DbConnection _dbConnection;
 
       public DbCommand(DbConnection dbConnection)
       {
-         _dbCommand = dbConnection.CreateCommand();
+         _odbcCommand = (OdbcCommand)dbConnection.CreateCommand();
          _dbConnection = dbConnection;
       }
 
       public DbCommand(string commandText, DbConnection dbConnection)
       {
-         dbConnection.GetCommand(commandText, CommandType.Text, this);
+         _odbcCommand = dbConnection.GetCommand(commandText, CommandType.Text);
+         _dbConnection = dbConnection;
       }
 
       public DbCommand(string commandText, CommandType commandType, DbConnection dbConnection)
       {
-         dbConnection.GetCommand(commandText, commandType, this);
-      }
-
-      internal DbCommand(IDbCommand dbCommand, DbConnection dbConnection)
-      {
-         _dbCommand = dbCommand;
-         _dbConnection = dbConnection;
+         _odbcCommand = dbConnection.GetCommand(commandText, commandType);
+         _dbConnection = dbConnection; 
       }
 
       internal IDbCommand Command
       {
          get
          {
-            return _dbCommand;
+            return _odbcCommand;
          }
          set
          {
-            _dbCommand = value;
-         }
-      }
-
-      internal DbConnection DbConnection
-      {
-         get
-         {
-            return _dbConnection;
-         }
-         set
-         {
-            _dbConnection = value;
+            _odbcCommand = (OdbcCommand)value;
          }
       }
 
@@ -58,11 +42,11 @@ namespace appMpower.Data
       {
          get
          {
-            return _dbCommand.CommandText;
+            return _odbcCommand.CommandText;
          }
          set
          {
-            _dbCommand.CommandText = value;
+            _odbcCommand.CommandText = value;
          }
       }
 
@@ -70,22 +54,22 @@ namespace appMpower.Data
       {
          get
          {
-            return _dbCommand.CommandTimeout;
+            return _odbcCommand.CommandTimeout;
          }
          set
          {
-            _dbCommand.CommandTimeout = value;
+            _odbcCommand.CommandTimeout = value;
          }
       }
       public CommandType CommandType
       {
          get
          {
-            return _dbCommand.CommandType;
+            return _odbcCommand.CommandType;
          }
          set
          {
-            _dbCommand.CommandType = value;
+            _odbcCommand.CommandType = value;
          }
       }
 
@@ -94,11 +78,11 @@ namespace appMpower.Data
       {
          get
          {
-            return _dbCommand.Connection;
+            return _odbcCommand.Connection;
          }
          set
          {
-            _dbCommand.Connection = (IDbConnection?)value;
+            _odbcCommand.Connection = (OdbcConnection?)value;
          }
       }
 #nullable disable
@@ -107,7 +91,7 @@ namespace appMpower.Data
       {
          get
          {
-            return _dbCommand.Parameters;
+            return _odbcCommand.Parameters;
          }
       }
 
@@ -116,11 +100,11 @@ namespace appMpower.Data
       {
          get
          {
-            return _dbCommand.Transaction;
+            return _odbcCommand.Transaction;
          }
          set
          {
-            _dbCommand.Transaction = (IDbTransaction?)value;
+            _odbcCommand.Transaction = (OdbcTransaction?)value;
          }
       }
 #nullable disable
@@ -129,21 +113,21 @@ namespace appMpower.Data
       {
          get
          {
-            return _dbCommand.UpdatedRowSource;
+            return _odbcCommand.UpdatedRowSource;
          }
          set
          {
-            _dbCommand.UpdatedRowSource = value;
+            _odbcCommand.UpdatedRowSource = value;
          }
       }
       public void Cancel()
       {
-         _dbCommand.Cancel();
+         _odbcCommand.Cancel();
       }
 
       public IDbDataParameter CreateParameter()
       {
-         return _dbCommand.CreateParameter();
+         return _odbcCommand.CreateParameter();
       }
 
       public IDbDataParameter CreateParameter(string name, object value)
@@ -153,21 +137,21 @@ namespace appMpower.Data
 
       public IDbDataParameter CreateParameter(string name, DbType dbType, object value)
       {
-         IDbDataParameter dbDataParameter = null;
+         IDbDataParameter dbDataParameter;
 
-         if (this.Parameters.Contains(name))
+         if (_odbcCommand.Parameters.Contains(name))
          {
-            dbDataParameter = this.Parameters[name] as IDbDataParameter;
+            dbDataParameter = _odbcCommand.Parameters[name];
             dbDataParameter.Value = value;
          }
          else
          {
-            dbDataParameter = _dbCommand.CreateParameter();
+            dbDataParameter = _odbcCommand.CreateParameter();
 
             dbDataParameter.ParameterName = name;
             dbDataParameter.DbType = dbType;
             dbDataParameter.Value = value;
-            this.Parameters.Add(dbDataParameter);
+            _odbcCommand.Parameters.Add(dbDataParameter);
          }
 
          return dbDataParameter;
@@ -175,51 +159,44 @@ namespace appMpower.Data
 
       public int ExecuteNonQuery()
       {
-         return _dbCommand.ExecuteNonQuery();
+         return _odbcCommand.ExecuteNonQuery();
       }
 
       public IDataReader ExecuteReader()
       {
-         return _dbCommand.ExecuteReader();
+         return _odbcCommand.ExecuteReader();
       }
 
       public async Task<int> ExecuteNonQueryAsync()
       {
-         return await (_dbCommand as System.Data.Common.DbCommand).ExecuteNonQueryAsync();
-      }
-
-      public async Task<System.Data.Common.DbDataReader> ExecuteReaderAsync(CommandBehavior behavior)
-      {
-         return await (_dbCommand as System.Data.Common.DbCommand).ExecuteReaderAsync(behavior);
+         return await _odbcCommand.ExecuteNonQueryAsync();
       }
 
       public IDataReader ExecuteReader(CommandBehavior behavior)
       {
-         return _dbCommand.ExecuteReader(behavior);
+         return _odbcCommand.ExecuteReader(behavior);
       }
 
-#nullable enable
-      public object? ExecuteScalar()
+      public async Task<System.Data.Common.DbDataReader> ExecuteReaderAsync(CommandBehavior behavior)
       {
-         return _dbCommand.ExecuteScalar();
+         return await _odbcCommand.ExecuteReaderAsync(behavior);
       }
-#nullable disable
 
 #nullable enable
-      public async Task<object?> ExecuteScalarAsync()
+      public object? ExecuteScalar()
       {
-         return await ((System.Data.Common.DbCommand)_dbCommand).ExecuteScalarAsync();
+         return _odbcCommand.ExecuteScalar();
       }
 #nullable disable
 
       public void Prepare()
       {
-         _dbCommand.Prepare();
+         _odbcCommand.Prepare();
       }
 
       public void Dispose()
       {
-         _dbConnection.ReleaseCommand(this);
+         _dbConnection.Release(_odbcCommand);
       }
    }
 }

+ 174 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnection.cs

@@ -0,0 +1,174 @@
+using System.Collections.Concurrent;
+using System.Data;
+using System.Data.Odbc;
+
+namespace appMpower.Orm.Data
+{
+   public class DbConnection : IDbConnection
+   {
+      private string _connectionString;
+      private bool _keyed = false;
+      private int _number;
+      private OdbcConnection _odbcConnection;
+      private ConcurrentStack<OdbcCommand> _odbcCommands = new();
+      private Dictionary<string, OdbcCommand> _keyedOdbcCommands;
+
+      public DbConnection()
+      {
+      }
+
+      public DbConnection(string connectionString, bool keyed = false)
+      {
+         _keyed = keyed;
+         _connectionString = connectionString; 
+         GetConnection();
+      }
+
+      public IDbConnection Connection
+      {
+         get
+         {
+            return _odbcConnection;
+         }
+         set
+         {
+            _odbcConnection = (OdbcConnection)value;
+         }
+      }
+
+      public string ConnectionString
+      {
+         get
+         {
+            return _odbcConnection.ConnectionString;
+         }
+         set
+         {
+            _connectionString = value; 
+            GetConnection();
+         }
+      }
+
+      private void GetConnection()
+      {
+         if (_keyed)
+         {
+            (_number, _odbcConnection, _keyedOdbcCommands) = 
+               DbConnectionsKeyed.GetConnectionBase(_connectionString).GetAwaiter().GetResult();
+         }
+         else
+         {
+            (_number, _odbcConnection, _odbcCommands) = 
+               DbConnections.GetConnectionBase(_connectionString).GetAwaiter().GetResult();
+         }
+      }
+
+      public int ConnectionTimeout
+      {
+         get
+         {
+            return _odbcConnection.ConnectionTimeout;
+         }
+      }
+
+      public string Database
+      {
+         get
+         {
+            return _odbcConnection.Database;
+         }
+      }
+
+      public ConnectionState State
+      {
+         get
+         {
+            if (_odbcConnection is null) return ConnectionState.Closed;
+            return _odbcConnection.State;
+         }
+      }
+
+      public IDbTransaction BeginTransaction()
+      {
+         return _odbcConnection.BeginTransaction();
+      }
+
+      public IDbTransaction BeginTransaction(IsolationLevel il)
+      {
+         return _odbcConnection.BeginTransaction(il);
+      }
+
+      public void ChangeDatabase(string databaseName)
+      {
+         _odbcConnection.ChangeDatabase(databaseName);
+      }
+
+      public void Close()
+      {
+         _odbcConnection.Close();
+      }
+
+      public IDbCommand CreateCommand()
+      {
+         return _odbcConnection.CreateCommand();
+      }
+
+      public void Open()
+      {
+         if (_odbcConnection.State == ConnectionState.Closed)
+         {
+            _odbcConnection.Open();
+         }
+      }
+
+      public async Task OpenAsync()
+      {
+         if (_odbcConnection.State == ConnectionState.Closed)
+         {
+            await _odbcConnection.OpenAsync();
+         }
+      }
+
+      public void Dispose()
+      {
+         if (_keyed)
+         {
+            DbConnectionsKeyed.Release((Number: _number, OdbcConnection: _odbcConnection, KeyedOdbcCommands: _keyedOdbcCommands));
+         }
+         else
+         {
+            DbConnections.Release((Number: _number, OdbcConnection: _odbcConnection, OdbcCommands: _odbcCommands));
+         }
+      }
+
+      internal OdbcCommand GetCommand(string commandText, CommandType commandType)
+      {
+         OdbcCommand odbcCommand;
+
+         if (_odbcCommands.TryPop(out odbcCommand))
+         {
+            if (commandText != odbcCommand.CommandText)
+            {
+               odbcCommand.CommandText = commandText; 
+               odbcCommand.Parameters.Clear();
+            }
+
+            return odbcCommand; 
+         }
+         else if (_keyed && _keyedOdbcCommands.TryGetValue(commandText, out odbcCommand)) return odbcCommand; 
+
+         odbcCommand = _odbcConnection.CreateCommand();
+         odbcCommand.CommandText = commandText;
+         odbcCommand.CommandType = commandType;
+         odbcCommand.Prepare();
+
+         return odbcCommand;
+      }
+
+      internal void Release(OdbcCommand odbcCommand)
+      {
+         if (_keyed) _keyedOdbcCommands.TryAdd(odbcCommand.CommandText, odbcCommand);
+         else _odbcCommands.Push(odbcCommand);
+      }
+   }
+}

+ 61 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnections.cs

@@ -0,0 +1,61 @@
+using System.Collections.Concurrent;
+using System.Data.Odbc;
+
+namespace appMpower.Orm.Data
+{
+   internal static class DbConnections
+   {
+      private static bool _maxConnectionsCreated = false;
+      private static short _createdConnections = 0;
+      private static short _maxConnections = 500;
+
+      private static ConcurrentStack<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> _connectionsStack = new();
+      private static ConcurrentQueue<TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)>> _waitingQueue = new();
+      
+      internal static async Task<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> GetConnectionBase(string connectionString)
+      {
+         (int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands) dbConnectionBase;
+
+         if (!_connectionsStack.TryPop(out dbConnectionBase))
+         {
+            if (_maxConnectionsCreated)
+            {
+               dbConnectionBase = await GetDbConnectionBaseAsync();
+            }
+            else
+            {
+               _createdConnections++;
+               dbConnectionBase = (Number: _maxConnections, OdbcConnection: new OdbcConnection(connectionString), OdbcCommands: new ConcurrentStack<OdbcCommand>());
+
+               if (_createdConnections == _maxConnections) _maxConnectionsCreated = true;
+
+               //Console.WriteLine("opened connection number: " + dbConnectionBase._number);
+            }
+         }
+
+         return dbConnectionBase;
+      }
+
+      internal static void Release((int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands) dbConnectionBase)
+      {
+         TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> taskCompletionSource;
+
+         if (_waitingQueue.TryDequeue(out taskCompletionSource))
+         {
+            taskCompletionSource.SetResult(dbConnectionBase);
+         }
+         else
+         {
+            _connectionsStack.Push(dbConnectionBase);
+         }
+      }
+
+      private static Task<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> GetDbConnectionBaseAsync()
+      {
+         var taskCompletionSource = new TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)>(TaskCreationOptions.RunContinuationsAsynchronously);
+
+         _waitingQueue.Enqueue(taskCompletionSource);
+         return taskCompletionSource.Task;
+      }
+   }
+}

+ 61 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnectionsKeyed.cs

@@ -0,0 +1,61 @@
+using System.Collections.Concurrent;
+using System.Data.Odbc;
+
+namespace appMpower.Orm.Data
+{
+   internal static class DbConnectionsKeyed
+   {
+      private static bool _maxConnectionsCreated = false;
+      private static short _createdConnections = 0;
+      private static short _maxConnections = 500;
+
+      private static ConcurrentStack<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)> _connectionsStack = new();
+      private static ConcurrentQueue<TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)>> _waitingQueue = new();
+
+      internal static async Task<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand> KeyedOdbcCommands)> GetConnectionBase(string connectionString)
+      {
+         (int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand> KeyedOdbcCommands) dbConnectionBase;
+
+         if (!_connectionsStack.TryPop(out dbConnectionBase))
+         {
+            if (_maxConnectionsCreated)
+            {
+               dbConnectionBase = await GetDbConnectionBaseAsync();
+            }
+            else
+            {
+               _createdConnections++;
+               dbConnectionBase = (Number: _maxConnections, OdbcConnection: new OdbcConnection(connectionString), KeyedOdbcCommands: new Dictionary<string, OdbcCommand>());
+
+               if (_createdConnections == _maxConnections) _maxConnectionsCreated = true;
+
+               //Console.WriteLine("opened connection number: " + dbConnectionBase._number);
+            }
+         }
+
+         return dbConnectionBase;
+      }
+
+      internal static void Release((int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand> KeyedOdbcCommands) dbConnectionBase)
+      {
+         TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)> taskCompletionSource;
+
+         if (_waitingQueue.TryDequeue(out taskCompletionSource))
+         {
+            taskCompletionSource.SetResult(dbConnectionBase);
+         }
+         else
+         {
+            _connectionsStack.Push(dbConnectionBase);
+         }
+      }
+
+      private static Task<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)> GetDbConnectionBaseAsync()
+      {
+         var taskCompletionSource = new TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)>(TaskCreationOptions.RunContinuationsAsynchronously);
+
+         _waitingQueue.Enqueue(taskCompletionSource);
+         return taskCompletionSource.Task;
+      }
+   }
+}

+ 8 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProvider.cs

@@ -0,0 +1,8 @@
+namespace appMpower.Orm.Data
+{
+   public enum DbProvider
+   {
+      ADO = 0,
+      ODBC = 1,
+   }
+}

+ 21 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProviderFactory.cs

@@ -0,0 +1,21 @@
+using System.Data;
+
+namespace appMpower.Orm.Data
+{
+   public static class DbProviderFactory
+   {
+      public static string ConnectionString; 
+
+      public static void SetConnectionString()
+      {
+         if (Constants.Dbms == Dbms.MySQL)
+         {
+            ConnectionString = "Driver={MariaDB};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;Pooling=false;OPTIONS=67108864;FLAG_FORWARD_CURSOR=1;sslmode=DISABLED;CharSet=utf8;"; 
+         }
+         else
+         {
+            ConnectionString = "Driver={PostgreSQL};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;UseServerSidePrepare=1;Pooling=false;sslmode=disable";
+         }
+      }
+   }
+}

+ 9 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/Dbms.cs

@@ -0,0 +1,9 @@
+namespace appMpower.Orm.Data
+{
+   public enum Dbms
+   {
+      MySQL = 0,
+      PostgreSQL = 1,
+      SQLServer = 2,
+   }
+}

+ 66 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/DotnetMethods.cs

@@ -0,0 +1,66 @@
+using System.Runtime.InteropServices;
+using System.Text; 
+using System.Text.Json; 
+using appMpower.Orm.Data; 
+using appMpower.Orm.Objects; 
+using appMpower.Orm.Serializers; 
+
+namespace appMpower.Orm;
+
+//These methods are for test purposes only; not used in actual execution
+public static class DotnetMethods
+{
+    private static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions
+    {
+        Indented = false, 
+        SkipValidation = true
+    };
+
+    private readonly static WorldSerializer _worldSerializer = new WorldSerializer();
+    private readonly static WorldsSerializer _worldsSerializer = new WorldsSerializer();
+
+    public static byte[] Db()
+    {
+        var world = RawDb.LoadSingleQueryRow().GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldSerializer.Serialize(utf8JsonWriter, world);
+
+        return memoryStream.ToArray();
+    }
+
+    public static byte[] Query(int queries)
+    {
+        World[] worlds = RawDb.ReadMultipleRows(queries).GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldsSerializer.Serialize(utf8JsonWriter, worlds);
+
+        return memoryStream.ToArray();
+    }
+
+    public static byte[] Updates(int count)
+    {
+        World[] worlds = RawDb.LoadMultipleUpdatesRows(count).GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldsSerializer.Serialize(utf8JsonWriter, worlds);
+
+        return memoryStream.ToArray();
+    }
+
+    public static byte[] Fortunes()
+    {
+        List<Fortune> fortunes = RawDb.LoadFortunesRows().GetAwaiter().GetResult(); 
+        string fortunesView = FortunesView.Render(fortunes);
+        byte[] byteArray = Encoding.UTF8.GetBytes(fortunesView);
+
+        return byteArray.ToArray();
+    }
+}

+ 4 - 17
frameworks/CSharp/appmpower/src/FortunesView.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/FortunesView.cs

@@ -1,33 +1,23 @@
 using System.Collections.Generic;
-using System.IO.Pipelines;
 using System.Globalization;
 using System.Text;
 using System.Threading.Tasks;
 using System.Web;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Primitives;
 using PlatformBenchmarks;
+using appMpower.Orm.Objects;
 
-namespace appMpower
+namespace appMpower.Orm
 {
    public static class FortunesView
    {
-      private readonly static KeyValuePair<string, StringValues> _headerServer =
-         new KeyValuePair<string, StringValues>("Server", "k");
-      private readonly static KeyValuePair<string, StringValues> _headerContentType =
-         new KeyValuePair<string, StringValues>("Content-Type", "text/html; charset=UTF-8");
-
       public static char[] _fortunesTableStart = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>".ToCharArray();
       public static char[] _fortunesRowStart = "<tr><td>".ToCharArray();
       public static char[] _fortunesColumn = "</td><td>".ToCharArray();
       public static char[] _fortunesRowEnd = "</td></tr>".ToCharArray();
       public static char[] _fortunesTableEnd = "</table></body></html>".ToCharArray();
 
-      public static async Task Render(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, List<Fortune> fortunes)
+      public static string Render(List<Fortune> fortunes)
       {
-         headerDictionary.Add(_headerServer);
-         headerDictionary.Add(_headerContentType);
-
          var writer = StringBuilderCache.Acquire();
 
          writer.Append(_fortunesTableStart);
@@ -39,10 +29,7 @@ namespace appMpower
 
          writer.Append(_fortunesTableEnd);
 
-         headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", (writer.Length + 32).ToString()));
-
-         await pipeWriter.WriteAsync(Encoding.UTF8.GetBytes(StringBuilderCache.GetStringAndRelease(writer)));
-         pipeWriter.Complete();
+         return StringBuilderCache.GetStringAndRelease(writer);
       }
    }
 }

+ 19 - 37
frameworks/CSharp/appmpower/src/Microsoft/BatchUpdateString.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/BatchUpdateString.cs

@@ -1,7 +1,8 @@
 // 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.Linq;
+using appMpower.Orm; 
+using appMpower.Orm.Data; 
 
 namespace PlatformBenchmarks
 {
@@ -33,51 +34,32 @@ namespace PlatformBenchmarks
          //sb.Append("(?::int,?::int)) AS temp(id, randomNumber) WHERE temp.id = world.id");
          */
 
-#if MYSQL
-         for (int i = 0; i < batchSize; i++)
+         if (Constants.Dbms == Dbms.MySQL)
          {
-            sb.Append("UPDATE world SET randomNumber=? WHERE id=?;");
+            for (int i = 0; i < batchSize; i++)
+            {
+               sb.Append("UPDATE world SET randomNumber=? WHERE id=?;");
+            }
          }
-#elif ADO
-         /*
-         sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ");
-         Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append($"(@i{i}, @r{i}), "));
-         sb.Append($"(@i{lastIndex}, @r{lastIndex}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id");
-         */
-
-         sb.Append("UPDATE world SET randomNumber=CASE id ");
-
-         for (int i = 0; i < batchSize; i++)
-         {
-            sb.Append("WHEN @i" + i + " THEN @r" + i + " ");
-         }
-
-         sb.Append("ELSE randomnumber END WHERE id IN(");
-
-         for (int i = 0; i < lastIndex; i++)
+         else
          {
-            sb.Append("@j" + i + ",");
-         }
+            sb.Append("UPDATE world SET randomNumber=CASE id ");
 
-         sb.Append("@j" + lastIndex + ")");
-#else
-         sb.Append("UPDATE world SET randomNumber=CASE id ");
+            for (int i = 0; i < batchSize; i++)
+            {
+               sb.Append("WHEN ? THEN ? ");
+            }
 
-         for (int i = 0; i < batchSize; i++)
-         {
-            sb.Append("WHEN ? THEN ? ");
-         }
+            sb.Append("ELSE randomnumber END WHERE id IN(");
 
-         sb.Append("ELSE randomnumber END WHERE id IN(");
+            for (int i = 0; i < lastIndex; i++)
+            {
+               sb.Append("?,");
+            }
 
-         for (int i = 0; i < lastIndex; i++)
-         {
-            sb.Append("?,");
+            sb.Append("?)");
          }
 
-         sb.Append("?)");
-#endif
-
          return _queries[batchSize] = StringBuilderCache.GetStringAndRelease(sb);
       }
    }

+ 0 - 2
frameworks/CSharp/appmpower/src/Microsoft/ConcurrentRandom.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/ConcurrentRandom.cs

@@ -1,9 +1,7 @@
 // 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
 {

+ 54 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/StringBuilderCache.cs

@@ -0,0 +1,54 @@
+// 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.Text;
+
+namespace PlatformBenchmarks; 
+
+internal static class StringBuilderCache
+{
+    private const int DefaultCapacity = 1386;
+    private const int MaxBuilderSize = DefaultCapacity * 3;
+    [ThreadStatic]
+    private static StringBuilder t_cachedInstance;
+
+    public static StringBuilder Acquire(int capacity = DefaultCapacity)
+    {
+        if (capacity <= MaxBuilderSize)
+        {
+            StringBuilder sb = t_cachedInstance;
+
+            if (capacity < DefaultCapacity)
+            {
+                capacity = DefaultCapacity;
+            }
+
+            if (sb != null)
+            {
+                if (capacity <= sb.Capacity)
+                {
+                    t_cachedInstance = null;
+                    sb.Clear();
+                    return sb;
+                }
+            }
+        }
+
+        return new StringBuilder(capacity);
+    }
+
+    public static void Release(StringBuilder sb)
+    {
+        if (sb.Capacity <= MaxBuilderSize)
+        {
+            t_cachedInstance = sb;
+        }
+    }
+
+    public static string GetStringAndRelease(StringBuilder sb)
+    {
+        string result = sb.ToString();
+        Release(sb);
+        return result;
+    }
+}

+ 144 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs

@@ -0,0 +1,144 @@
+using System.Runtime.InteropServices;
+using System.Text; 
+using System.Text.Json; 
+using appMpower.Orm.Data; 
+using appMpower.Orm.Objects; 
+using appMpower.Orm.Serializers; 
+
+namespace appMpower.Orm;
+
+public static class NativeMethods
+{
+    private static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions
+    {
+        Indented = false, 
+        SkipValidation = true
+    };
+
+    private readonly static WorldSerializer _worldSerializer = new WorldSerializer();
+    private readonly static WorldsSerializer _worldsSerializer = new WorldsSerializer();
+
+    [UnmanagedCallersOnly(EntryPoint = "Dbms")]
+    public static void Dbms(int dbms)
+    {
+        Constants.Dbms = (Dbms)dbms; 
+        DbProviderFactory.SetConnectionString();
+    }
+
+    [UnmanagedCallersOnly(EntryPoint = "DbProvider")]
+    public static void DbProvider(int dbProvider)
+    {
+        Constants.DbProvider = (DbProvider)dbProvider; 
+        DbProviderFactory.SetConnectionString();
+    }
+    
+    [UnmanagedCallersOnly(EntryPoint = "FreeHandlePointer")]
+    public static void FreeHandlePointer(IntPtr handlePointer)
+    {
+        GCHandle handle = GCHandle.FromIntPtr(handlePointer);
+        handle.Free();
+    }
+
+    [UnmanagedCallersOnly(EntryPoint = "Db")]
+    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);
+
+        _worldSerializer.Serialize(utf8JsonWriter, world);
+
+        *length = (int)utf8JsonWriter.BytesCommitted; 
+        byte[] byteArray = memoryStream.ToArray();
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        // return the managed and byteArrayPointer pointer
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+        /*
+        fixed(byte* b = memoryStream.ToArray())
+        {
+            return b; 
+        }
+        */
+    }
+
+    [UnmanagedCallersOnly(EntryPoint = "Fortunes")]
+    public static unsafe IntPtr Fortunes(int* length, IntPtr* handlePointer)
+    {
+        List<Fortune> fortunes = RawDb.LoadFortunesRows().GetAwaiter().GetResult(); 
+        string fortunesView = FortunesView.Render(fortunes);
+        byte[] byteArray = Encoding.UTF8.GetBytes(fortunesView);
+
+        *length = byteArray.Length; 
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+    }
+
+    [UnmanagedCallersOnly(EntryPoint = "Query")]
+    public static unsafe IntPtr Query(int queries, int* length, IntPtr* handlePointer)
+    {
+        World[] worlds = RawDb.ReadMultipleRows(queries).GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldsSerializer.Serialize(utf8JsonWriter, worlds);
+
+        *length = (int)utf8JsonWriter.BytesCommitted; 
+        byte[] byteArray = memoryStream.ToArray();
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+    }
+
+    [UnmanagedCallersOnly(EntryPoint = "Updates")]
+    public static unsafe IntPtr Updates(int count, int* length, IntPtr* handlePointer)
+    {
+        World[] worlds = RawDb.LoadMultipleUpdatesRows(count).GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldsSerializer.Serialize(utf8JsonWriter, worlds);
+
+        *length = (int)utf8JsonWriter.BytesCommitted; 
+        byte[] byteArray = memoryStream.ToArray();
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+    }
+
+    [UnmanagedCallersOnly(EntryPoint = "DbById")]
+    public static unsafe IntPtr DbById(int id, int* length, IntPtr* handlePointer)
+    {
+        var world = RawDb.LoadSingleQueryRowById(id).GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldSerializer.Serialize(utf8JsonWriter, world);
+
+        *length = (int)utf8JsonWriter.BytesCommitted; 
+        byte[] byteArray = memoryStream.ToArray();
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+    }
+}

+ 1 - 1
frameworks/CSharp/appmpower/src/CachedWorld.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/CachedWorld.cs

@@ -1,4 +1,4 @@
-namespace appMpower
+namespace appMpower.Orm.Objects
 {
    public struct CachedWorld
    {

+ 1 - 3
frameworks/CSharp/appmpower/src/Fortune.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/Fortune.cs

@@ -1,6 +1,4 @@
-using System;
-
-namespace appMpower
+namespace appMpower.Orm.Objects
 {
    public readonly struct Fortune : IComparable<Fortune>, IComparable
    {

+ 1 - 1
frameworks/CSharp/appmpower/src/World.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/World.cs

@@ -1,4 +1,4 @@
-namespace appMpower
+namespace appMpower.Orm.Objects
 {
    public struct World
    {

+ 50 - 131
frameworks/CSharp/appmpower/src/RawDb.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/RawDb.cs

@@ -1,34 +1,18 @@
-using System;
-using System.Collections.Generic;
 using System.Data;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Caching.Memory;
-using appMpower.Data; 
+using appMpower.Orm.Data; 
+using appMpower.Orm.Objects;
 using PlatformBenchmarks;
 
-namespace appMpower
+namespace appMpower.Orm
 {
    public static class RawDb
    {
       private const int MaxBatch = 500;
 
-#if ADO      
-      private static ConcurrentRandom _random = new ConcurrentRandom();
-#else
       private static Random _random = new Random();
-#endif
 
       private static string[] _queriesMultipleRows = new string[MaxBatch + 1];
 
-      private static readonly object[] _cacheKeys = Enumerable.Range(0, 10001).Select((i) => new CacheKey(i)).ToArray();
-
-      private static readonly appMpower.Memory.MemoryCache _cache = new appMpower.Memory.MemoryCache(
-            new appMpower.Memory.MemoryCacheOptions()
-            {
-               ExpirationScanFrequency = TimeSpan.FromMinutes(60)
-            });
-
       public static async Task<World> LoadSingleQueryRow()
       {
          using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
@@ -38,7 +22,22 @@ namespace appMpower
 
          using (dbCommand)
          {
-            var world = await ReadSingleRow(dbCommand);
+            World world = await ReadSingleRow(dbCommand);
+
+            return world;
+         }
+      }
+
+      public static async Task<World> LoadSingleQueryRowById(int id)
+      {
+         using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
+         await pooledConnection.OpenAsync();
+
+         var (dbCommand, _) = CreateReadCommandById(pooledConnection, id);
+
+         using (dbCommand)
+         {
+            World world = await ReadSingleRow(dbCommand);
 
             return world;
          }
@@ -76,21 +75,17 @@ namespace appMpower
 
          using (dbCommand)
          {
-            var dataReader = await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleResult & CommandBehavior.SequentialAccess);
+            IDataReader dataReader = await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleResult & CommandBehavior.SequentialAccess);
 
             while (dataReader.Read())
             {
                fortunes.Add(new Fortune
                (
-                   id: dataReader.GetInt32(0),
-#if MYSQL
-               //MariaDB ODBC connector does not correctly support Japanese characters in combination with default ADO.NET;
-               //as a solution we custom read this string
-                message: ReadColumn(dataReader, 1)
-#else
-                message: dataReader.GetString(1)
-#endif
-            ));
+                  id: dataReader.GetInt32(0),
+                  //MariaDB ODBC connector does not correctly support Japanese characters in combination with default ADO.NET;
+                  //as a solution we custom read this string
+                  message: (Constants.Dbms == Dbms.MySQL ? ReadColumn(dataReader, 1) : dataReader.GetString(1))
+               ));
             }
 
             dataReader.Close();
@@ -106,7 +101,7 @@ namespace appMpower
       {
          var worlds = new World[count];
 
-         using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
+         using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString, true);
          await pooledConnection.OpenAsync();
 
          var (queryCommand, dbDataParameter) = CreateReadCommand(pooledConnection);
@@ -120,14 +115,10 @@ namespace appMpower
             }
          }
 
-         using var updateCommand = new DbCommand(PlatformBenchmarks.BatchUpdateString.Query(count), pooledConnection);
+         using var updateCommand = new DbCommand(BatchUpdateString.Query(count), pooledConnection);
 
-         var ids = PlatformBenchmarks.BatchUpdateString.Ids;
-         var randoms = PlatformBenchmarks.BatchUpdateString.Randoms;
-
-#if !MYSQL
-         var jds = PlatformBenchmarks.BatchUpdateString.Jds;
-#endif      
+         var ids = BatchUpdateString.Ids;
+         var randoms = BatchUpdateString.Randoms;
 
          for (int i = 0; i < count; i++)
          {
@@ -139,30 +130,36 @@ namespace appMpower
             worlds[i].RandomNumber = randomNumber;
          }
 
-#if !MYSQL
-         for (int i = 0; i < count; i++)
+         if (Constants.Dbms != Dbms.MySQL)
          {
-            updateCommand.CreateParameter(jds[i], DbType.Int32, worlds[i].Id);
+            var jds = BatchUpdateString.Jds;
+
+            for (int i = 0; i < count; i++)
+            {
+               updateCommand.CreateParameter(jds[i], DbType.Int32, worlds[i].Id);
+            }
          }
-#endif
 
-         await updateCommand.ExecuteNonQueryAsync();
+         updateCommand.ExecuteNonQuery();
 
          return worlds;
       }
 
-      private static (DbCommand dbCommand, IDbDataParameter dbDataParameter) CreateReadCommand(DbConnection pooledConnection)
+      internal static (DbCommand dbCommand, IDbDataParameter dbDataParameter) CreateReadCommand(DbConnection pooledConnection)
       {
-#if ADO         
-         var dbCommand = new DbCommand("SELECT * FROM world WHERE id=@Id", pooledConnection);
-#else         
-         var dbCommand = new DbCommand("SELECT * FROM world WHERE id=?", pooledConnection);
-#endif         
+         DbCommand dbCommand = new DbCommand("SELECT * FROM world WHERE id=?", pooledConnection);
 
          return (dbCommand, dbCommand.CreateParameter("Id", DbType.Int32, _random.Next(1, 10001)));
       }
 
-      private static async Task<World> ReadSingleRow(DbCommand dbCommand)
+      internal static (DbCommand dbCommand, IDbDataParameter dbDataParameter) CreateReadCommandById(DbConnection pooledConnection, int id)
+      {
+         DbCommand dbCommand = new DbCommand("SELECT * FROM world WHERE id=?", pooledConnection);
+
+         return (dbCommand, dbCommand.CreateParameter("Id", DbType.Int32, id));
+      }
+
+      internal static async Task<World> ReadSingleRow(DbCommand dbCommand)
       {
          var dataReader = await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleRow & CommandBehavior.SequentialAccess);
 
@@ -182,7 +179,7 @@ namespace appMpower
       public static async Task<World[]> ReadMultipleRows(int count)
       {
          int j = 0;
-         var ids = PlatformBenchmarks.BatchUpdateString.Ids;
+         var ids = BatchUpdateString.Ids;
          var worlds = new World[count];
          string queryString;
 
@@ -192,14 +189,14 @@ namespace appMpower
          }
          else
          {
-            var stringBuilder = PlatformBenchmarks.StringBuilderCache.Acquire();
+            var stringBuilder = StringBuilderCache.Acquire();
 
             for (int i = 0; i < count; i++)
             {
                stringBuilder.Append("SELECT * FROM world WHERE id=?;");
             }
 
-            queryString = _queriesMultipleRows[count] = PlatformBenchmarks.StringBuilderCache.GetStringAndRelease(stringBuilder);
+            queryString = _queriesMultipleRows[count] = StringBuilderCache.GetStringAndRelease(stringBuilder);
          }
 
          using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
@@ -249,83 +246,5 @@ namespace appMpower
 
          return System.Text.Encoding.Default.GetString(values);
       }
-
-      public static async Task PopulateCache()
-      {
-         using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
-         await pooledConnection.OpenAsync();
-
-         var (dbCommand, dbDataParameter) = CreateReadCommand(pooledConnection);
-
-         using (dbCommand)
-         {
-            var cacheKeys = _cacheKeys;
-            var cache = _cache;
-
-            for (var i = 1; i < 10001; i++)
-            {
-               dbDataParameter.Value = i;
-               cache.Set<CachedWorld>(cacheKeys[i], await ReadSingleRow(dbCommand));
-            }
-         }
-      }
-
-      public static Task<CachedWorld[]> 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 key = cacheKeys[id];
-
-            if (cache.TryGetValue(key, out object cached))
-            {
-               result[i] = (CachedWorld)cached;
-            }
-            else
-            {
-               //return LoadUncachedQueries(id, i, count, this, result);
-               return LoadUncachedQueries(id, i, count, result);
-            }
-         }
-
-         return Task.FromResult(result);
-      }
-
-      static async Task<CachedWorld[]> LoadUncachedQueries(int id, int i, int count, CachedWorld[] result)
-      {
-         using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
-         await pooledConnection.OpenAsync();
-
-         var (dbCommand, dbDataParameter) = CreateReadCommand(pooledConnection);
-
-         using (dbCommand)
-         {
-            Func<ICacheEntry, Task<CachedWorld>> create = async (entry) =>
-            {
-               return await ReadSingleRow(dbCommand);
-            };
-
-            var cacheKeys = _cacheKeys;
-            var key = cacheKeys[id];
-
-            dbDataParameter.Value = id;
-
-            for (; i < result.Length; i++)
-            {
-               result[i] = await _cache.GetOrCreateAsync<CachedWorld>(key, create);
-
-               id = _random.Next(1, 10001);
-               dbDataParameter.Value = id;
-               key = cacheKeys[id];
-            }
-         }
-
-         return result;
-      }
    }
 }

+ 9 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/IJsonSerializer.cs

@@ -0,0 +1,9 @@
+using System.Text.Json;
+
+namespace appMpower.Orm.Serializers
+{
+   public interface IJsonSerializer<T>
+   {
+      public void Serialize(Utf8JsonWriter utf8JsonWriter, T t);
+   }
+}

+ 4 - 2
frameworks/CSharp/appmpower/src/WorldSerializer.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/WorldSerializer.cs

@@ -1,8 +1,9 @@
 using System.Text.Json;
+using appMpower.Orm.Objects;
 
-namespace appMpower
+namespace appMpower.Orm.Serializers
 {
-   public class WorldSerializer : Kestrel.IJsonSerializer<World>
+   public class WorldSerializer : IJsonSerializer<World>
    {
       public void Serialize(Utf8JsonWriter utf8JsonWriter, World world)
       {
@@ -10,6 +11,7 @@ namespace appMpower
          utf8JsonWriter.WriteNumber("id", world.Id);
          utf8JsonWriter.WriteNumber("randomNumber", world.RandomNumber);
          utf8JsonWriter.WriteEndObject();
+         utf8JsonWriter.Flush();
       }
    }
 }

+ 24 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/WorldsSerizalizer.cs

@@ -0,0 +1,24 @@
+using System.Text.Json;
+using appMpower.Orm.Objects;
+
+namespace appMpower.Orm.Serializers
+{
+   public class WorldsSerializer : IJsonSerializer<World[]>
+   {
+      public void Serialize(Utf8JsonWriter utf8JsonWriter, World[] worlds)
+      {
+         utf8JsonWriter.WriteStartArray();
+
+         foreach (World world in worlds)
+         {
+            utf8JsonWriter.WriteStartObject();
+            utf8JsonWriter.WriteNumber("id", world.Id);
+            utf8JsonWriter.WriteNumber("randomNumber", world.RandomNumber);
+            utf8JsonWriter.WriteEndObject();
+         }
+
+         utf8JsonWriter.WriteEndArray();
+         utf8JsonWriter.Flush();
+      }
+   }
+}

+ 42 - 55
frameworks/CSharp/appmpower/src/appMpower.csproj → frameworks/CSharp/appmpower/src/appMpower.Orm/appMpower.Orm.csproj

@@ -1,55 +1,42 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
-
-  <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
-    <OutputType>Exe</OutputType>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-
-    <!--<RuntimeIdentifier>linux-x64</RuntimeIdentifier>-->
-
-    <!-- Normal .NET 8 -->
-    <PublishAot>true</PublishAot>
-    <SelfContained>true</SelfContained>
-    <InvariantGlobalization>true</InvariantGlobalization>
-    <IlcGenerateStackTraceData>false</IlcGenerateStackTraceData>
-    <IlcOptimizationPreference>Speed</IlcOptimizationPreference>
-    <DebugType>none</DebugType>
-    <GenerateRuntimeConfigurationFiles>false</GenerateRuntimeConfigurationFiles>
-
-    <!-- Only some may work - From the experimental AOT version -->
-    <IlcFoldIdenticalMethodBodies>true</IlcFoldIdenticalMethodBodies>
-    <IlcTrimMetadata>true</IlcTrimMetadata>
-    <IlcInvariantGlobalization>true</IlcInvariantGlobalization>
-    <IlcGenerateCompleteTypeMetadata>false</IlcGenerateCompleteTypeMetadata>
-
-    <!-- Still works from the experimental AOT version, but high risk -->
-    <IlcDisableReflection>true</IlcDisableReflection>
-
-    <SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
-
-    <!--
-    <TrimMode>link</TrimMode>
-    -->
-
-    <!-- Opt out of the "easy mode" of the CoreRT compiler (http://aka.ms/OptimizeCoreRT) -->
-    <IlcPgoOptimize>true</IlcPgoOptimize>
-
-    <!-- This benchmark is marked Stripped, so we might as well do this: -->
-    <UseSystemResourceKeys>true</UseSystemResourceKeys>
-    <EventSourceSupport>false</EventSourceSupport>
-    <DebuggerSupport>false</DebuggerSupport>
-
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="System.Data.Odbc" Version="8.0.0" />
-    <PackageReference Include="Npgsql" Version="8.0.2-*" />
-  </ItemGroup>
-
-  <PropertyGroup>
-      <DefineConstants>$(DefineConstants);POSTGRESQL</DefineConstants>
-      <DefineConstants Condition=" '$(Driver)' == 'odbc' ">$(DefineConstants);ODBC</DefineConstants>
-      <DefineConstants Condition=" '$(Driver)' == 'ado' ">$(DefineConstants);ADO</DefineConstants>
-  </PropertyGroup>
-
-</Project>
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+
+    <PublishAot>true</PublishAot>
+    <SelfContained>true</SelfContained>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    
+    <RuntimeIdentifier>linux-x64</RuntimeIdentifier> <!-- docker server -->
+    <!--TODOLOCAL-->
+    <!--<RuntimeIdentifier>linux-arm64</RuntimeIdentifier>--> <!-- docker local -->
+    <!--<RuntimeIdentifier>osx-arm64</RuntimeIdentifier>--> <!-- outside docker local -->
+
+    <InvariantGlobalization>true</InvariantGlobalization>
+    <IlcGenerateStackTraceData>false</IlcGenerateStackTraceData>
+    <IlcOptimizationPreference>Size</IlcOptimizationPreference>
+    <DebugType>none</DebugType>
+    <GenerateRuntimeConfigurationFiles>false</GenerateRuntimeConfigurationFiles>
+
+    <IlcFoldIdenticalMethodBodies>true</IlcFoldIdenticalMethodBodies>
+    <IlcTrimMetadata>true</IlcTrimMetadata>
+    <IlcInvariantGlobalization>true</IlcInvariantGlobalization>
+    <IlcGenerateCompleteTypeMetadata>false</IlcGenerateCompleteTypeMetadata>
+
+    <IlcDisableReflection>true</IlcDisableReflection>
+
+    <SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
+
+    <IlcPgoOptimize>true</IlcPgoOptimize>
+
+    <UseSystemResourceKeys>true</UseSystemResourceKeys>
+    <EventSourceSupport>false</EventSourceSupport>
+    <DebuggerSupport>false</DebuggerSupport>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="System.Data.Odbc" Version="8.0.0" />
+  </ItemGroup>
+
+</Project>

+ 7 - 0
frameworks/CSharp/appmpower/src/appMpower/JsonMessage.cs

@@ -0,0 +1,7 @@
+namespace appMpower
+{
+  public struct JsonMessage
+  {
+      public string Message { get; set; }
+  }
+}

+ 120 - 0
frameworks/CSharp/appmpower/src/appMpower/Middleware/CachingMiddelware.cs

@@ -0,0 +1,120 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+
+namespace appMpower;
+
+public class CachingMiddleware
+{
+   private static readonly Dictionary<int, byte[]> _cache = new();
+   private static readonly Random _random = new();
+
+   private static readonly byte[] _startBytes = Encoding.UTF8.GetBytes("[");
+   private static readonly byte[] _endBytes = Encoding.UTF8.GetBytes("]");
+   private static readonly byte[] _comma = Encoding.UTF8.GetBytes(",");
+
+
+   private readonly static KeyValuePair<string, StringValues> _headerServer =
+       new KeyValuePair<string, StringValues>("Server", new StringValues("k"));
+   private readonly static KeyValuePair<string, StringValues> _headerContentType =
+        new KeyValuePair<string, StringValues>("Content-Type", new StringValues("application/json"));
+
+   private readonly RequestDelegate _next;
+
+   public CachingMiddleware(RequestDelegate next)
+   {
+      _next = next;
+   }
+
+   public unsafe Task Invoke(HttpContext httpContext)
+   {
+      if (httpContext.Request.Path.StartsWithSegments("/cached-worlds", StringComparison.Ordinal))
+      {
+         int payloadLength;
+         IntPtr handlePointer;
+         IntPtr bytePointer;
+         byte[] json;
+
+         if (_cache.Count == 0)
+         {
+            for (int i = 1; i < 10001; i++)
+            {
+               bytePointer = NativeMethods.DbById(i, out payloadLength, out handlePointer);
+               json = new byte[payloadLength];
+               Marshal.Copy(bytePointer, json, 0, payloadLength);
+               NativeMethods.FreeHandlePointer(handlePointer);
+               _cache.Add(i, json);
+            }
+         }
+
+         var queryString = httpContext.Request.QueryString.ToString();
+         int queries;
+         Int32.TryParse(queryString.Substring(queryString.LastIndexOf("=") + 1), out queries);
+         queries = queries > 500 ? 500 : (queries > 0 ? queries : 1);
+
+         var response = httpContext.Response;
+         response.Headers.Add(_headerServer);
+         response.Headers.Add(_headerContentType);
+
+         int queriesLength = 0;
+         int[] keys = new int[queries];
+
+         for (int i = 0; i < queries; i++)
+         {
+            keys[i] = _random.Next(1, 10001);
+            
+            if (!_cache.TryGetValue(keys[i], out json))
+            {
+               bytePointer = NativeMethods.DbById(keys[i], out payloadLength, out handlePointer);
+               json = new byte[payloadLength];
+               Marshal.Copy(bytePointer, json, 0, payloadLength);
+               NativeMethods.FreeHandlePointer(handlePointer);
+               _cache.Add(keys[i], json);
+            }
+
+            queriesLength += json.Length;
+         }
+
+         byte[] result = new byte[_startBytes.Length + _endBytes.Length + (_comma.Length * queries - 1) + queriesLength];
+         int position = 0;
+
+         Buffer.BlockCopy(_startBytes, 0, result, position, _startBytes.Length);
+         position += _startBytes.Length;
+
+         for (int i = 0; i < queries; i++)
+         {
+            json = _cache[keys[i]]; 
+            Buffer.BlockCopy(json, 0, result, position, json.Length);
+            position += json.Length;
+
+            if (i < queries - 1)
+            {
+               Buffer.BlockCopy(_comma, 0, result, position, _comma.Length);
+               position += _comma.Length;
+            }
+         }
+
+         Buffer.BlockCopy(_endBytes, 0, result, position, _endBytes.Length);
+
+         response.Headers.Add(
+             new KeyValuePair<string, StringValues>("Content-Length", result.Length.ToString()));
+
+         return response.Body.WriteAsync(result, 0, result.Length);
+      }
+
+      return _next(httpContext);
+   }
+}
+
+public static class CachingMiddlewareExtensions
+{
+   public static IApplicationBuilder UseCaching(this IApplicationBuilder builder)
+   {
+      return builder.UseMiddleware<CachingMiddleware>();
+   }
+}

+ 58 - 0
frameworks/CSharp/appmpower/src/appMpower/Middleware/FortunesMiddleware.cs

@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+
+namespace appMpower; 
+
+public class FortunesMiddleware
+{
+    private readonly static KeyValuePair<string, StringValues> _headerServer =
+         new KeyValuePair<string, StringValues>("Server", new StringValues("k"));
+    private readonly static KeyValuePair<string, StringValues> _headerContentType =
+         new KeyValuePair<string, StringValues>("Content-Type", new StringValues("text/html; charset=UTF-8"));
+
+    private readonly RequestDelegate _next;
+
+    public FortunesMiddleware(RequestDelegate next)
+    {
+        _next = next;
+    }
+
+    public unsafe Task Invoke(HttpContext httpContext)
+    {
+        if (httpContext.Request.Path.StartsWithSegments("/fortunes", StringComparison.Ordinal))
+        {
+            var response = httpContext.Response; 
+            response.Headers.Add(_headerServer);
+            response.Headers.Add(_headerContentType);
+
+            int payloadLength;
+            IntPtr handlePointer; 
+
+            IntPtr bytePointer = NativeMethods.Fortunes(out payloadLength, out handlePointer);
+            byte[] json = new byte[payloadLength];
+            Marshal.Copy(bytePointer, json, 0, payloadLength);
+            NativeMethods.FreeHandlePointer(handlePointer);
+
+            response.Headers.Add(
+                new KeyValuePair<string, StringValues>("Content-Length", payloadLength.ToString()));
+
+            return response.Body.WriteAsync(json, 0, payloadLength);
+        }
+
+        return _next(httpContext);
+    }
+}
+
+public static class FortunesMiddlewareExtensions
+{
+    public static IApplicationBuilder UseFortunes(this IApplicationBuilder builder)
+    {
+        return builder.UseMiddleware<FortunesMiddleware>();
+    }
+}

+ 64 - 0
frameworks/CSharp/appmpower/src/appMpower/Middleware/JsonMiddleware.cs

@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Json; 
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+using appMpower.Serializers; 
+
+namespace appMpower; 
+
+public class JsonMiddleware
+{
+    private readonly static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions
+    {
+        Indented = false, 
+        SkipValidation = true
+    };
+
+    private readonly static JsonMessageSerializer _jsonMessageSerializer = new JsonMessageSerializer();
+
+    private readonly static KeyValuePair<string, StringValues> _headerServer =
+         new KeyValuePair<string, StringValues>("Server", new StringValues("k"));
+    private readonly static KeyValuePair<string, StringValues> _headerContentType =
+         new KeyValuePair<string, StringValues>("Content-Type", new StringValues("application/json"));
+         
+    private readonly RequestDelegate _nextStage;
+
+    public JsonMiddleware(RequestDelegate nextStage)
+    {
+        _nextStage = nextStage;
+    }
+
+    public unsafe Task Invoke(HttpContext httpContext)
+    {
+        if (httpContext.Request.Path.StartsWithSegments("/json", StringComparison.Ordinal))
+        {
+            var response = httpContext.Response; 
+            response.Headers.Add(_headerServer);
+            response.Headers.Add(_headerContentType);
+
+            using var utf8JsonWriter = new Utf8JsonWriter(httpContext.Response.Body, _jsonWriterOptions);
+
+            _jsonMessageSerializer.Serialize(utf8JsonWriter, new JsonMessage { Message = "Hello, World!" });
+
+            response.Headers.Add(
+                new KeyValuePair<string, StringValues>("Content-Length", utf8JsonWriter.BytesPending.ToString()));
+
+            utf8JsonWriter.Flush();
+
+            return Task.CompletedTask;
+        }
+
+        return _nextStage(httpContext);
+    }
+}
+
+public static class JsonMiddlewareExtensions
+{
+    public static IApplicationBuilder UseJson(this IApplicationBuilder builder)
+    {
+        return builder.UseMiddleware<JsonMiddleware>();
+    }
+}

+ 62 - 0
frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleQueriesMiddleware.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+
+namespace appMpower; 
+
+public class MultipleQueriesMiddleware
+{
+    private readonly static KeyValuePair<string, StringValues> _headerServer =
+         new KeyValuePair<string, StringValues>("Server", new StringValues("k"));
+    private readonly static KeyValuePair<string, StringValues> _headerContentType =
+         new KeyValuePair<string, StringValues>("Content-Type", new StringValues("application/json"));
+
+   private readonly RequestDelegate _next;
+
+   public MultipleQueriesMiddleware(RequestDelegate next)
+   {
+      _next = next;
+   }
+
+    public unsafe Task Invoke(HttpContext httpContext)
+   {
+      if (httpContext.Request.Path.StartsWithSegments("/queries", StringComparison.Ordinal))
+      {
+         var queryString = httpContext.Request.QueryString.ToString(); 
+         int queries; 
+         Int32.TryParse(queryString.Substring(queryString.LastIndexOf("=") + 1), out queries); 
+         queries = queries > 500 ? 500 : (queries > 0 ? queries : 1);
+
+         var response = httpContext.Response;
+         response.Headers.Add(_headerServer);
+         response.Headers.Add(_headerContentType);
+
+         int payloadLength;
+         IntPtr handlePointer;
+
+         IntPtr bytePointer = NativeMethods.Query(queries, out payloadLength, out handlePointer);
+         byte[] json = new byte[payloadLength];
+         Marshal.Copy(bytePointer, json, 0, payloadLength);
+         NativeMethods.FreeHandlePointer(handlePointer);
+
+         response.Headers.Add(
+             new KeyValuePair<string, StringValues>("Content-Length", payloadLength.ToString()));
+
+         return response.Body.WriteAsync(json, 0, payloadLength);
+      }
+
+      return _next(httpContext);
+   }
+}
+
+public static class MultipleQueriesMiddlewareExtensions
+{
+   public static IApplicationBuilder UseMultipleQueries(this IApplicationBuilder builder)
+   {
+      return builder.UseMiddleware<MultipleQueriesMiddleware>();
+   }
+}

+ 62 - 0
frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleUpdatesMiddleware.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+
+namespace appMpower; 
+
+public class MultipleUpdatesMiddelware
+{
+    private readonly static KeyValuePair<string, StringValues> _headerServer =
+         new KeyValuePair<string, StringValues>("Server", new StringValues("k"));
+    private readonly static KeyValuePair<string, StringValues> _headerContentType =
+         new KeyValuePair<string, StringValues>("Content-Type", new StringValues("application/json"));
+
+   private readonly RequestDelegate _next;
+
+   public MultipleUpdatesMiddelware(RequestDelegate next)
+   {
+      _next = next;
+   }
+
+    public unsafe Task Invoke(HttpContext httpContext)
+   {
+      if (httpContext.Request.Path.StartsWithSegments("/updates", StringComparison.Ordinal))
+      {
+         var queryString = httpContext.Request.QueryString.ToString(); 
+         int count; 
+         Int32.TryParse(queryString.Substring(queryString.LastIndexOf("=") + 1), out count); 
+         count = count > 500 ? 500 : (count > 0 ? count : 1);
+
+         var response = httpContext.Response;
+         response.Headers.Add(_headerServer);
+         response.Headers.Add(_headerContentType);
+
+         int payloadLength;
+         IntPtr handlePointer;
+
+         IntPtr bytePointer = NativeMethods.Updates(count, out payloadLength, out handlePointer);
+         byte[] json = new byte[payloadLength];
+         Marshal.Copy(bytePointer, json, 0, payloadLength);
+         NativeMethods.FreeHandlePointer(handlePointer);
+
+         response.Headers.Add(
+             new KeyValuePair<string, StringValues>("Content-Length", payloadLength.ToString()));
+
+         return response.Body.WriteAsync(json, 0, payloadLength);
+      }
+
+      return _next(httpContext);
+   }
+}
+
+public static class MultipleUpdatesMiddelwareExtensions
+{
+   public static IApplicationBuilder UseMultipleUpdates(this IApplicationBuilder builder)
+   {
+      return builder.UseMiddleware<MultipleUpdatesMiddelware>();
+   }
+}

+ 50 - 0
frameworks/CSharp/appmpower/src/appMpower/Middleware/PlaintextMiddleware.cs

@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+
+namespace appMpower; 
+
+public unsafe class PlaintextMiddleware
+{
+    private readonly static KeyValuePair<string, StringValues> _headerServer =
+         new KeyValuePair<string, StringValues>("Server", new StringValues("k"));
+    private readonly static KeyValuePair<string, StringValues> _headerContentType =
+         new KeyValuePair<string, StringValues>("Content-Type", new StringValues("text/plain"));
+    private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!");
+
+    private readonly RequestDelegate _nextStage;
+
+    public PlaintextMiddleware(RequestDelegate nextStage)
+    {
+        _nextStage = nextStage;
+    }
+
+    public Task Invoke(HttpContext httpContext)
+    {
+        if (httpContext.Request.Path.StartsWithSegments("/plaintext", StringComparison.Ordinal))
+        {
+            var payloadLength = _helloWorldPayload.Length;
+            var response = httpContext.Response; 
+            response.Headers.Add(_headerServer);
+            response.Headers.Add(_headerContentType);
+            response.Headers.Add(
+                new KeyValuePair<string, StringValues>("Content-Length", payloadLength.ToString()));
+
+            return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength);
+        }
+
+        return _nextStage(httpContext);
+    }
+}
+
+public static class PlaintextMiddlewareExtensions
+{
+    public static IApplicationBuilder UsePlainText(this IApplicationBuilder builder)
+    {
+        return builder.UseMiddleware<PlaintextMiddleware>();
+    }
+}

+ 57 - 0
frameworks/CSharp/appmpower/src/appMpower/Middleware/SingleQueryMiddleware.cs

@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+
+namespace appMpower; 
+
+public class SingleQueryMiddleware
+{
+    private readonly static KeyValuePair<string, StringValues> _headerServer =
+         new KeyValuePair<string, StringValues>("Server", new StringValues("k"));
+    private readonly static KeyValuePair<string, StringValues> _headerContentType =
+         new KeyValuePair<string, StringValues>("Content-Type", new StringValues("application/json"));
+
+    private readonly RequestDelegate _nextStage;
+
+    public SingleQueryMiddleware(RequestDelegate nextStage)
+    {
+        _nextStage = nextStage;
+    }
+
+    public unsafe Task Invoke(HttpContext httpContext)
+    {
+        if (httpContext.Request.Path.StartsWithSegments("/db", StringComparison.Ordinal))
+        {
+            var response = httpContext.Response; 
+            response.Headers.Add(_headerServer);
+            response.Headers.Add(_headerContentType);
+
+            int payloadLength;
+            IntPtr handlePointer; 
+
+            IntPtr bytePointer = NativeMethods.Db(out payloadLength, out handlePointer);
+            byte[] json = new byte[payloadLength];
+            Marshal.Copy(bytePointer, json, 0, payloadLength);
+            NativeMethods.FreeHandlePointer(handlePointer);
+
+            response.Headers.Add(
+                new KeyValuePair<string, StringValues>("Content-Length", payloadLength.ToString()));
+
+            return response.Body.WriteAsync(json, 0, payloadLength);
+        }
+
+        return _nextStage(httpContext);
+    }
+}
+
+public static class SingleQueryMiddlewareExtensions
+{
+    public static IApplicationBuilder UseSingleQuery(this IApplicationBuilder builder)
+    {
+        return builder.UseMiddleware<SingleQueryMiddleware>();
+    }
+}

+ 62 - 0
frameworks/CSharp/appmpower/src/appMpower/NativeMethods.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Runtime.InteropServices;
+
+public unsafe partial class NativeMethods
+{
+#if DEBUG
+    [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#else
+    [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#endif   
+    public static extern void Dbms(int dbms); 
+
+#if DEBUG
+    [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#else
+    [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#endif   
+    public static extern void DbProvider(int dbProvider); 
+
+#if DEBUG
+    [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl)]
+#else
+    [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl)]
+#endif
+    public static extern void FreeHandlePointer(IntPtr handlePointer);
+
+#if DEBUG
+    [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#else
+    [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#endif   
+    //public static extern byte* Db(out int length); 
+    public static extern IntPtr Db(out int length, out IntPtr handlePointer); 
+
+#if DEBUG
+    [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#else
+    [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#endif   
+    public static extern IntPtr Fortunes(out int length, out IntPtr handlePointer); 
+
+#if DEBUG
+    [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#else
+    [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#endif   
+    public static extern IntPtr Query(int queries, out int length, out IntPtr handlePointer); 
+
+#if DEBUG
+    [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#else
+    [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#endif   
+    public static extern IntPtr Updates(int queries, out int length, out IntPtr handlePointer); 
+
+#if DEBUG
+    [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#else
+    [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
+#endif   
+    public static extern IntPtr DbById(int id, out int length, out IntPtr handlePointer); 
+}

+ 44 - 0
frameworks/CSharp/appmpower/src/appMpower/Program.cs

@@ -0,0 +1,44 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+
+namespace appMpower; 
+
+class Program
+{
+    static void Main(string[] args)
+    {
+        BuildWebHost(args).Run();
+    }
+
+    static IHost BuildWebHost(string[] args)
+    {
+        var config = new ConfigurationBuilder()
+            .AddJsonFile("appsettings.json")
+            .AddEnvironmentVariables(prefix: "ASPNETCORE_")
+            .AddCommandLine(args)
+            .Build();
+
+        var appSettings = config.GetSection("AppSettings").Get<AppSettings>();
+
+        var host = Host.CreateDefaultBuilder(args)
+            .ConfigureWebHostDefaults(webBuilder =>
+            {
+                webBuilder.UseConfiguration(config)
+                          .UseKestrel(options =>
+                          {
+                            options.AddServerHeader = false; 
+                            options.AllowSynchronousIO = true;
+                          })
+                          .UseStartup<Startup>();
+            })
+            .Build();
+
+        return host;
+    }
+}
+
+public class AppSettings
+{
+    public string Database { get; set; }
+}

+ 1 - 1
frameworks/CSharp/appmpower/src/Kestrel/IJsonSerializer.cs → frameworks/CSharp/appmpower/src/appMpower/Serializers/IJsonSerializer.cs

@@ -1,6 +1,6 @@
 using System.Text.Json;
 
-namespace appMpower.Kestrel
+namespace appMpower.Serializers
 {
    public interface IJsonSerializer<T>
    {

+ 3 - 3
frameworks/CSharp/appmpower/src/JsonMessageSerializer.cs → frameworks/CSharp/appmpower/src/appMpower/Serializers/JsonMessageSerializer.cs

@@ -1,13 +1,13 @@
 using System.Text.Json;
 
-namespace appMpower
+namespace appMpower.Serializers
 {
-   public class JsonMessageSerializer : Kestrel.IJsonSerializer<JsonMessage>
+   public class JsonMessageSerializer : IJsonSerializer<JsonMessage>
    {
       public void Serialize(Utf8JsonWriter utf8JsonWriter, JsonMessage jsonMessage)
       {
          utf8JsonWriter.WriteStartObject();
-         utf8JsonWriter.WriteString("message", jsonMessage.message);
+         utf8JsonWriter.WriteString("message", jsonMessage.Message);
          utf8JsonWriter.WriteEndObject();
       }
    }

+ 56 - 0
frameworks/CSharp/appmpower/src/appMpower/Startup.cs

@@ -0,0 +1,56 @@
+using System.Text.Encodings.Web;
+using System.Text.Unicode;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace appMpower; 
+
+public class Startup
+{
+    private readonly IConfiguration _configuration;
+
+    public Startup(IConfiguration configuration)
+    {
+        _configuration = configuration;
+    }
+
+    public void ConfigureServices(IServiceCollection services)
+    {
+        var appSettings = _configuration.Get<AppSettings>();
+        services.AddSingleton(appSettings);
+
+#if !DEBUG
+    #if ODBC      
+        NativeMethods.DbProvider(1); //ODBC
+    #else
+        NativeMethods.DbProvider(0); //ADO
+    #endif        
+
+    #if POSTGRESQL      
+        NativeMethods.Dbms(1); //PostgreSQL
+    #else
+        NativeMethods.Dbms(0); //MySQL
+    #endif
+#endif
+
+        var settings = new TextEncoderSettings(UnicodeRanges.BasicLatin, UnicodeRanges.Katakana, UnicodeRanges.Hiragana);
+
+        settings.AllowCharacter('—');
+        services.AddWebEncoders(options =>
+        {
+            options.TextEncoderSettings = settings;
+        });
+    }
+
+    public void Configure(IApplicationBuilder app)
+    {
+        app.UsePlainText();
+        app.UseJson();
+        app.UseSingleQuery();
+        app.UseCaching();
+        app.UseFortunes();
+        app.UseMultipleQueries();
+        app.UseMultipleUpdates();
+    }
+}

+ 35 - 0
frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj

@@ -0,0 +1,35 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <OutputType>Exe</OutputType>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <None Include="appsettings.json" CopyToOutputDirectory="PreserveNewest" />
+
+    <!--
+    <Content Include="../appMpower.Orm/bin/Release/net8.0/appMpower.Orm.dll">
+        <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content> 
+    -->
+    <!--TODOLOCAL-->
+    <!--
+    <Content Include="../appMpower.Orm/bin/Release/net8.0/osx-arm64/native/appMpower.Orm.dylib">
+        <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content> 
+    -->
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include = "..\appMpower.Orm\appMpower.Orm.csproj" />
+  </ItemGroup>
+
+  <PropertyGroup>
+      <DefineConstants Condition=" '$(Driver)' == 'odbc' ">$(DefineConstants);ODBC</DefineConstants>
+      <DefineConstants Condition=" '$(Database)' == 'postgresql' ">$(DefineConstants);POSTGRESQL</DefineConstants>
+      <DefineConstants Condition=" '$(Database)' == 'mysql' ">$(DefineConstants);MYSQL</DefineConstants>
+  </PropertyGroup>
+
+</Project>

+ 9 - 0
frameworks/CSharp/appmpower/src/appMpower/appsettings.json

@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "None",
+      "Microsoft": "None",
+      "Microsoft.Hosting.Lifetime": "None"
+    }
+  }
+}

+ 0 - 0
frameworks/CSharp/appmpower/src/nuget.config → frameworks/CSharp/appmpower/src/appMpower/nuget.config


+ 28 - 0
frameworks/CSharp/appmpower/src/src.sln

@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "appMpower.Orm", "appMpower.Orm\appMpower.Orm.csproj", "{1EC05247-7299-4F69-887B-3B746DF5F878}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "appMpower", "appMpower\appMpower.csproj", "{EB5D3496-53B9-49A7-A3AD-754078142F81}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{1EC05247-7299-4F69-887B-3B746DF5F878}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{1EC05247-7299-4F69-887B-3B746DF5F878}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{1EC05247-7299-4F69-887B-3B746DF5F878}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{1EC05247-7299-4F69-887B-3B746DF5F878}.Release|Any CPU.Build.0 = Release|Any CPU
+		{EB5D3496-53B9-49A7-A3AD-754078142F81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{EB5D3496-53B9-49A7-A3AD-754078142F81}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{EB5D3496-53B9-49A7-A3AD-754078142F81}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{EB5D3496-53B9-49A7-A3AD-754078142F81}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal

+ 1 - 1
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=18;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000",
+  "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",
   "Database": "postgresql"
 }

+ 3 - 3
frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile

@@ -1,12 +1,12 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.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:8.0 AS runtime
-ENV URLS http://+:8080
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
+ENV URLS=http://+:8080
 
 WORKDIR /app
 COPY --from=build /app/out ./

+ 5 - 2
frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile

@@ -1,10 +1,13 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 WORKDIR /app
 COPY src/Minimal .
 RUN dotnet publish -c Release -o out
 
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
 ENV URLS http://+:8080
+ENV DOTNET_GCDynamicAdaptationMode=0
+ENV DOTNET_ReadyToRun=0
+ENV DOTNET_HillClimbing_Disable=1
 
 WORKDIR /app
 COPY --from=build /app/out ./

+ 5 - 2
frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile

@@ -1,10 +1,13 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 WORKDIR /app
 COPY src/Mvc .
 RUN dotnet publish -c Release -o out
 
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
 ENV URLS http://+:8080
+ENV DOTNET_GCDynamicAdaptationMode=0
+ENV DOTNET_ReadyToRun=0
+ENV DOTNET_HillClimbing_Disable=1
 
 WORKDIR /app
 COPY --from=build /app/out ./

+ 5 - 2
frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile

@@ -1,10 +1,13 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 WORKDIR /app
 COPY src/Platform .
 RUN dotnet publish -c Release -o out /p:DatabaseProvider=MySqlConnector
 
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
 ENV URLS http://+:8080
+ENV DOTNET_GCDynamicAdaptationMode=0
+ENV DOTNET_ReadyToRun=0
+ENV DOTNET_HillClimbing_Disable=1
 
 WORKDIR /app
 COPY --from=build /app/out ./

+ 6 - 3
frameworks/CSharp/aspnetcore/aspnetcore.dockerfile

@@ -1,10 +1,13 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 WORKDIR /app
 COPY src/Platform .
 RUN dotnet publish -c Release -o out /p:DatabaseProvider=Npgsql
 
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
-ENV URLS http://+:8080
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
+ENV URLS=http://+:8080
+ENV DOTNET_GCDynamicAdaptationMode=0
+ENV DOTNET_ReadyToRun=0
+ENV DOTNET_HillClimbing_Disable=1
 
 WORKDIR /app
 COPY --from=build /app/out ./

+ 4 - 4
frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
   <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <Nullable>enable</Nullable>
     <ImplicitUsings>enable</ImplicitUsings>
     <LangVersion>latest</LangVersion>
@@ -9,9 +9,9 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Npgsql" Version="8.0.3" />
-    <PackageReference Include="Dapper" Version="2.1.21" />
-    <PackageReference Include="RazorSlices" Version="0.7.0" />
+    <PackageReference Include="Npgsql" Version="8.0.5" />
+    <PackageReference Include="Dapper" Version="2.1.35" />
+    <PackageReference Include="RazorSlices" Version="0.8.1" />
   </ItemGroup>
 
 </Project>

+ 6 - 8
frameworks/CSharp/aspnetcore/src/Minimal/Program.cs

@@ -1,13 +1,11 @@
 // 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.Text.Encodings.Web;
-using System.Text.Unicode;
-using Microsoft.AspNetCore.Http.HttpResults;
-using RazorSlices;
 using Minimal;
 using Minimal.Database;
 using Minimal.Models;
+using System.Text.Encodings.Web;
+using System.Text.Unicode;
 
 var builder = WebApplication.CreateBuilder(args);
 
@@ -36,14 +34,14 @@ app.MapGet("/json", () => new { message = "Hello, World!" });
 
 app.MapGet("/db", async (Db db) => await db.LoadSingleQueryRow());
 
-var createFortunesTemplate = RazorSlice.ResolveSliceFactory<List<Fortune>>("/Templates/Fortunes.cshtml");
 var htmlEncoder = CreateHtmlEncoder();
 
 app.MapGet("/fortunes", async (HttpContext context, Db db) => {
     var fortunes = await db.LoadFortunesRows();
-    var template = (RazorSliceHttpResult<List<Fortune>>)createFortunesTemplate(fortunes);
-    template.HtmlEncoder = htmlEncoder;
-    return template;
+    var result = Results.Extensions.RazorSlice<Minimal.Slices.Fortunes, List<Fortune>>(fortunes);
+    result.HtmlEncoder = htmlEncoder;
+
+    return result;
 });
 
 app.MapGet("/queries/{count?}", async (Db db, string? count) => await db.LoadMultipleQueriesRows(count));

+ 0 - 0
frameworks/CSharp/aspnetcore/src/Minimal/Templates/Fortunes.cshtml → frameworks/CSharp/aspnetcore/src/Minimal/Slices/Fortunes.cshtml


+ 0 - 0
frameworks/CSharp/aspnetcore/src/Minimal/Templates/_ViewImports.cshtml → frameworks/CSharp/aspnetcore/src/Minimal/Slices/_ViewImports.cshtml


+ 3 - 3
frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
   <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <Nullable>enable</Nullable>
     <ImplicitUsings>enable</ImplicitUsings>
     <LangVersion>latest</LangVersion>
@@ -9,8 +9,8 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Npgsql" Version="8.0.3" />
-    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0-rc.2" />
+    <PackageReference Include="Npgsql" Version="8.0.5" />
+    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.0-rc.2" />
   </ItemGroup>
 
 </Project>

+ 4 - 4
frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
   <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <IsTestAssetProject>true</IsTestAssetProject>
     <LangVersion>preview</LangVersion>
@@ -19,9 +19,9 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="Npgsql" Version="8.0.3" />
-    <PackageReference Include="MySqlConnector" Version="2.3.1" />
-    <PackageReference Include="Dapper" Version="2.1.21" />
+    <PackageReference Include="Npgsql" Version="8.0.5" />
+    <PackageReference Include="MySqlConnector" Version="2.3.7" />
+    <PackageReference Include="Dapper" Version="2.1.35" />
     <PackageReference Include="RazorSlices" Version="0.7.0" Condition="$(PublishAot) != 'true'" />
   </ItemGroup>
 

+ 0 - 1
frameworks/CSharp/aspnetcore/src/Platform/Program.cs

@@ -52,7 +52,6 @@ public class Program
 #if DEBUG
             .AddUserSecrets<Program>()
 #endif
-            .AddEnvironmentVariables()
             .AddEnvironmentVariables()
             .AddCommandLine(args)
             .Build();

+ 177 - 248
frameworks/CSharp/beetlex/PlatformBenchmarks/DBRaw.cs

@@ -10,110 +10,44 @@ using System.Threading.Tasks;
 
 using Microsoft.Extensions.Caching.Memory;
 using Npgsql;
+using System.Runtime.CompilerServices;
 
 
 namespace PlatformBenchmarks
 {
-    public class RawDb
+    public sealed class RawDb
     {
-
         private readonly ConcurrentRandom _random;
+        private readonly MemoryCache _cache
+            = new(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(60) });
 
-        private readonly DbProviderFactory _dbProviderFactory;
-
-        private readonly static MemoryCache _cache = new MemoryCache(
-          new MemoryCacheOptions()
-          {
-              ExpirationScanFrequency = TimeSpan.FromMinutes(60)
-          });
-
-        private static readonly object[] _cacheKeys = Enumerable.Range(0, 10001).Select((i) => new CacheKey(i)).ToArray();
+        private static DbProviderFactory _dbProviderFactory => Npgsql.NpgsqlFactory.Instance;
+        private readonly string _connectionString;
 
-        public static string _connectionString = null;
-
-        public RawDb(ConcurrentRandom random, DbProviderFactory dbProviderFactory)
+        public RawDb(ConcurrentRandom random, string connectionString)
         {
             _random = random;
-            _dbProviderFactory = dbProviderFactory;
-            OnCreateCommand();
-        }
-        private void OnCreateCommand()
-        {
-            SingleCommand = new Npgsql.NpgsqlCommand();
-            SingleCommand.CommandText = "SELECT id, randomnumber FROM world WHERE id = @Id";
-            mID = new Npgsql.NpgsqlParameter<int>("@Id", _random.Next(1, 10001));
-            SingleCommand.Parameters.Add(mID);
-            FortuneCommand = new Npgsql.NpgsqlCommand();
-            FortuneCommand.CommandText = "SELECT id, message FROM fortune";
-        }
-
-        private DbCommand SingleCommand;
-
-        private DbCommand FortuneCommand;
-
-        private Npgsql.NpgsqlParameter<int> mID;
-
-        private static int ListDefaultSize = 8;
-
-        private World[] mWorldBuffer = null;
-
-        private World[] GetWorldBuffer()
-        {
-            if (mWorldBuffer == null)
-                mWorldBuffer = new World[512];
-            return mWorldBuffer;
-        }
-
-        private Fortune[] mFortunesBuffer = null;
-
-        private Fortune[] GetFortuneBuffer()
-        {
-            if (mFortunesBuffer == null)
-                mFortunesBuffer = new Fortune[512];
-            return mFortunesBuffer;
+            _connectionString = connectionString;
         }
 
         public async Task<World> LoadSingleQueryRow()
         {
-            using (var db = _dbProviderFactory.CreateConnection())
-            {
-                db.ConnectionString = _connectionString;
-                await db.OpenAsync();
-                SingleCommand.Connection = db;
-                mID.TypedValue = _random.Next(1, 10001);
-                return await ReadSingleRow(db, SingleCommand);
-
-            }
-        }
-
-        async Task<World> ReadSingleRow(DbConnection connection, DbCommand cmd)
-        {
-            using (var rdr = await cmd.ExecuteReaderAsync(CommandBehavior.SingleRow))
-
+            using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection())
             {
-                await rdr.ReadAsync();
-                return new World
+                connection.ConnectionString = _connectionString;
+                await connection.OpenAsync();
+                var (cmd, _) = CreateReadCommand(connection);
+                using (var command = cmd)
                 {
-                    Id = rdr.GetInt32(0),
-                    RandomNumber = rdr.GetInt32(1)
-                };
-            }
-        }
 
-        public async Task<ArraySegment<World>> LoadMultipleQueriesRows(int count)
-        {
-            using (var db = _dbProviderFactory.CreateConnection())
-            {
-                db.ConnectionString = _connectionString;
-                await db.OpenAsync();
-                return await LoadMultipleRows(count, db);
+                    return await ReadSingleRow(cmd);
+                }
             }
         }
 
-
-        public Task<World[]> LoadCachedQueries(int count)
+        public Task<CachedWorld[]> LoadCachedQueries(int count)
         {
-            var result = new World[count];
+            var result = new CachedWorld[count];
             var cacheKeys = _cacheKeys;
             var cache = _cache;
             var random = _random;
@@ -121,42 +55,40 @@ namespace PlatformBenchmarks
             {
                 var id = random.Next(1, 10001);
                 var key = cacheKeys[id];
-                var data = cache.Get<CachedWorld>(key);
-
-                if (data != null)
+                if (cache.TryGetValue(key, out var cached))
                 {
-                    result[i] = data;
+                    result[i] = (CachedWorld)cached;
                 }
                 else
                 {
-                    return LoadUncachedQueries(id, i, count, this, result);
+                    return LoadUncachedQueries(_connectionString, id, i, count, this, result);
                 }
             }
 
             return Task.FromResult(result);
 
-            static async Task<World[]> LoadUncachedQueries(int id, int i, int count, RawDb rawdb, World[] result)
+            static async Task<CachedWorld[]> LoadUncachedQueries(string conn, int id, int i, int count, RawDb rawdb, CachedWorld[] result)
             {
-                using (var db = new NpgsqlConnection(_connectionString))
+                using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection())
                 {
-                    await db.OpenAsync();
-                    Func<ICacheEntry, Task<CachedWorld>> create = async (entry) =>
-                    {
-                        return await rawdb.ReadSingleRow(db, rawdb.SingleCommand);
-                    };
+                    connection.ConnectionString = conn;
+                    await connection.OpenAsync();
+                    var (cmd, idParameter) = rawdb.CreateReadCommand(connection);
+                    using var command = cmd;
+                    async Task<CachedWorld> create(ICacheEntry _) => await ReadSingleRow(cmd);
+
 
                     var cacheKeys = _cacheKeys;
                     var key = cacheKeys[id];
 
-                    rawdb.SingleCommand.Connection = db;
-                    rawdb.mID.TypedValue = id;
+                    idParameter.TypedValue = id;
+
                     for (; i < result.Length; i++)
                     {
-                        var data = await _cache.GetOrCreateAsync<CachedWorld>(key, create);
-                        result[i] = data;
+                        result[i] = await rawdb._cache.GetOrCreateAsync(key, create);
+
                         id = rawdb._random.Next(1, 10001);
-                        rawdb.SingleCommand.Connection = db;
-                        rawdb.mID.TypedValue = id;
+                        idParameter.TypedValue = id;
                         key = cacheKeys[id];
                     }
                 }
@@ -164,215 +96,212 @@ namespace PlatformBenchmarks
             }
         }
 
-
-        private async Task<ArraySegment<World>> LoadMultipleRows(int count, DbConnection db)
+        public async Task PopulateCache()
         {
-            SingleCommand.Connection = db;
-            SingleCommand.Parameters[0].Value = _random.Next(1, 10001);
-            var result = GetWorldBuffer();
-            for (int i = 0; i < count; i++)
+            using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection())
             {
-                result[i] = await ReadSingleRow(db, SingleCommand);
-                SingleCommand.Parameters[0].Value = _random.Next(1, 10001);
+                connection.ConnectionString = _connectionString;
+                await connection.OpenAsync();
+                var (cmd, idParameter) = CreateReadCommand(connection);
+                using var command = cmd;
+
+                var cacheKeys = _cacheKeys;
+                var cache = _cache;
+                for (var i = 1; i < 10001; i++)
+                {
+                    idParameter.TypedValue = i;
+                    cache.Set<CachedWorld>(cacheKeys[i], await ReadSingleRow(cmd));
+                }
             }
-            return new ArraySegment<World>(result, 0, count);
 
+            Console.WriteLine("Caching Populated");
         }
 
-        public async Task<ArraySegment<Fortune>> LoadFortunesRows()
+        public async Task<World[]> LoadMultipleQueriesRows(int count)
         {
-            int count = 0;
-            var result = GetFortuneBuffer();
-            using (var db = new NpgsqlConnection(_connectionString))
+            var results = new World[count];
+
+            using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection())
             {
-                await db.OpenAsync();
-                FortuneCommand.Connection = db;
-                using (var rdr = await FortuneCommand.ExecuteReaderAsync())
+                connection.ConnectionString = _connectionString;
+                await connection.OpenAsync();
+
+                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++)
                 {
-                    while (await rdr.ReadAsync())
+                    batch.BatchCommands.Add(new()
                     {
-                        result[count] = (new Fortune
-                        {
-                            Id = rdr.GetInt32(0),
-                            Message = rdr.GetString(1)
-                        });
-                        count++;
-                    }
+                        CommandText = "SELECT id, randomnumber FROM world WHERE id = $1",
+                        Parameters = { new NpgsqlParameter<int> { 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();
                 }
             }
-            result[count] = (new Fortune { Message = "Additional fortune added at request time." });
-            count++;
-            Array.Sort<Fortune>(result, 0, count);
-            return new ArraySegment<Fortune>(result, 0, count);
+            return results;
         }
+
         public async Task<World[]> LoadMultipleUpdatesRows(int count)
         {
-            using (var db = new NpgsqlConnection(_connectionString))
+            var results = new World[count];
+
+            using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection())
             {
-                await db.OpenAsync();
-                var updateCmd = UpdateCommandsCached.PopCommand(count);
-                try
+                connection.ConnectionString = _connectionString;
+                await connection.OpenAsync();
+                var (queryCmd, queryParameter) = CreateReadCommand(connection);
+                using (queryCmd)
                 {
-                    var command = updateCmd.Command;
-                    command.Connection = db;
-                    SingleCommand.Connection = db;
-                    mID.TypedValue = _random.Next(1, int.MaxValue) % 10000 + 1;
-                    var results = new World[count];
-                    for (int i = 0; i < count; i++)
+                    for (var i = 0; i < results.Length; i++)
                     {
-                        results[i] = await ReadSingleRow(db, SingleCommand);
-                        mID.TypedValue = _random.Next(1, int.MaxValue) % 10000 + 1;
+                        results[i] = await ReadSingleRow(queryCmd);
+                        queryParameter.TypedValue = _random.Next(1, 10001);
                     }
+                }
 
-                    for (int i = 0; i < count; i++)
+                using (var updateCmd = new NpgsqlCommand(BatchUpdateString.Query(count), connection))
+                {
+                    for (var i = 0; i < results.Length; i++)
                     {
-                        var randomNumber = _random.Next(1, int.MaxValue) % 10000 + 1;
-                        updateCmd.Parameters[i * 2].TypedValue = results[i].Id;
-                        updateCmd.Parameters[i * 2 + 1].TypedValue = randomNumber;
-                        //updateCmd.Parameters[i * 2].Value = results[i].Id;
-                        //updateCmd.Parameters[i * 2 + 1].Value = randomNumber;
+                        var randomNumber = _random.Next(1, 10001);
+
+                        updateCmd.Parameters.Add(new NpgsqlParameter<int> { TypedValue = results[i].Id });
+                        updateCmd.Parameters.Add(new NpgsqlParameter<int> { TypedValue = randomNumber });
+
                         results[i].RandomNumber = randomNumber;
                     }
 
-                    await command.ExecuteNonQueryAsync();
-                    return results;
-                }
-                catch (Exception e_)
-                {
-                    throw e_;
-                }
-                finally
-                {
-                    UpdateCommandsCached.PushCommand(count, updateCmd);
+                    await updateCmd.ExecuteNonQueryAsync();
                 }
             }
-        }
-    }
 
+            return results;
+        }
 
-    public sealed class CacheKey : IEquatable<CacheKey>
-    {
-        private readonly int _value;
+        public async Task<List<Fortune>> LoadFortunesRows()
+        {
+            // Benchmark requirements explicitly prohibit pre-initializing the list size
+            var result = new List<Fortune>();
 
-        public CacheKey(int value)
-            => _value = value;
+            using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection())
+            {
+                connection.ConnectionString = _connectionString;
+                await connection.OpenAsync();
 
-        public bool Equals(CacheKey key)
-            => key._value == _value;
+                using (var cmd = new NpgsqlCommand("SELECT id, message FROM fortune", connection))
+                {
 
-        public override bool Equals(object obj)
-            => ReferenceEquals(obj, this);
+                    using (var rdr = await cmd.ExecuteReaderAsync())
+                    {
 
-        public override int GetHashCode()
-            => _value;
+                        while (await rdr.ReadAsync())
+                        {
+                            result.Add(new Fortune
+                            {
+                                Id = rdr.GetInt32(0),
+                                Message = rdr.GetString(1)
+                            });
+                        }
+                    }
+                }
+            }
+            result.Add(new Fortune { Message = "Additional fortune added at request time." });
+            result.Sort();
 
-        public override string ToString()
-            => _value.ToString();
-    }
+            return result;
+        }
 
-    internal class UpdateCommandsCached
-    {
-        private static System.Collections.Concurrent.ConcurrentStack<CommandCacheItem>[] mCacheTable
-            = new System.Collections.Concurrent.ConcurrentStack<CommandCacheItem>[1024];
 
-        public static string[] IDParamereNames = new string[1024];
+        private (NpgsqlCommand readCmd, NpgsqlParameter<int> idParameter) CreateReadCommand(NpgsqlConnection connection)
+        {
+            var cmd = new NpgsqlCommand("SELECT id, randomnumber FROM world WHERE id = $1", connection);
+            var parameter = new NpgsqlParameter<int> { TypedValue = _random.Next(1, 10001) };
 
-        public static string[] RandomParamereNames = new string[1024];
+            cmd.Parameters.Add(parameter);
 
-        static UpdateCommandsCached()
-        {
-            for (int i = 0; i < 1024; i++)
-            {
-                IDParamereNames[i] = $"@Id_{i}";
-                RandomParamereNames[i] = $"@Random_{i}";
-                mCacheTable[i] = new System.Collections.Concurrent.ConcurrentStack<CommandCacheItem>();
-            }
+            return (cmd, parameter);
         }
 
-        private static CommandCacheItem CreatCommand(int count)
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static async Task<World> ReadSingleRow(NpgsqlCommand cmd)
         {
-            CommandCacheItem item = new CommandCacheItem();
-            NpgsqlCommand cmd = new Npgsql.NpgsqlCommand();
-            cmd.CommandText = BatchUpdateString.Query(count);
-            for (int i = 0; i < count; i++)
-            {
-                var id = new NpgsqlParameter<int>();
-                id.ParameterName = IDParamereNames[i];
-                cmd.Parameters.Add(id);
-                item.Parameters.Add(id);
-
-                var random = new NpgsqlParameter<int>();
-                random.ParameterName = RandomParamereNames[i];
-                cmd.Parameters.Add(random);
-                item.Parameters.Add(random);
-            }
-            item.Command = cmd;
-            return item;
+            using var rdr = await cmd.ExecuteReaderAsync(System.Data.CommandBehavior.SingleRow);
+            await rdr.ReadAsync();
 
+            return new World
+            {
+                Id = rdr.GetInt32(0),
+                RandomNumber = rdr.GetInt32(1)
+            };
         }
 
-        public static void PushCommand(int count, CommandCacheItem cmd)
-        {
-            mCacheTable[count].Push(cmd);
-        }
+        private static readonly object[] _cacheKeys = Enumerable.Range(0, 10001).Select((i) => new CacheKey(i)).ToArray();
 
-        public static CommandCacheItem PopCommand(int count)
+        public sealed class CacheKey : IEquatable<CacheKey>
         {
-            if (mCacheTable[count].TryPop(out CommandCacheItem cmd))
-                return cmd;
-            return CreatCommand(count);
-        }
+            private readonly int _value;
 
-        private static bool mInited = false;
+            public CacheKey(int value)
+                => _value = value;
 
-        public static void Init()
-        {
-            if (mInited)
-                return;
-            lock (typeof(UpdateCommandsCached))
-            {
-                if (mInited)
-                    return;
-                for (int i = 1; i <= 500; i++)
-                {
-                    for (int k = 0; k < 10; k++)
-                    {
-                        var cmd = CreatCommand(i);
-                        mCacheTable[i].Push(cmd);
-                    }
-                }
-                mInited = true;
-                return;
-            }
-        }
-    }
+            public bool Equals(CacheKey key)
+                => key._value == _value;
 
-    class CommandCacheItem
-    {
-        public Npgsql.NpgsqlCommand Command { get; set; }
+            public override bool Equals(object obj)
+                => ReferenceEquals(obj, this);
 
-        public List<Npgsql.NpgsqlParameter<int>> Parameters { get; private set; } = new List<Npgsql.NpgsqlParameter<int>>(1024);
+            public override int GetHashCode()
+                => _value;
+
+            public override string ToString()
+                => _value.ToString();
+        }
     }
 
 
-    internal class BatchUpdateString
+    internal sealed class BatchUpdateString
     {
         private const int MaxBatch = 500;
 
+        internal static readonly string[] ParamNames = Enumerable.Range(0, MaxBatch * 2).Select(i => $"@p{i}").ToArray();
+
         private static string[] _queries = new string[MaxBatch + 1];
 
         public static string Query(int batchSize)
+            => _queries[batchSize] is null
+                ? CreateBatch(batchSize)
+                : _queries[batchSize];
+
+        private static string CreateBatch(int batchSize)
         {
-            if (_queries[batchSize] != null)
+            var sb = StringBuilderCache.Acquire();
+
+
+            sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ");
+            var c = 1;
+            for (var i = 0; i < batchSize; i++)
             {
-                return _queries[batchSize];
+                if (i > 0)
+                    sb.Append(", ");
+                sb.Append($"(${c++}, ${c++})");
             }
+            sb.Append(" ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id");
+
 
-            var lastIndex = batchSize - 1;
-            var sb = StringBuilderCache.Acquire();
-            sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ");
-            Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append($"(@Id_{i}, @Random_{i}), "));
-            sb.Append($"(@Id_{lastIndex}, @Random_{lastIndex}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id");
             return _queries[batchSize] = StringBuilderCache.GetStringAndRelease(sb);
         }
     }

+ 8 - 6
frameworks/CSharp/beetlex/PlatformBenchmarks/GMTDate.cs

@@ -49,7 +49,7 @@ namespace PlatformBenchmarks
             }
         }
 
-        public ArraySegment<byte> DATE
+        public Memory<byte> DATE
         {
             get;
             set;
@@ -95,18 +95,20 @@ namespace PlatformBenchmarks
             }, null, 1000, 1000);
         }
 
-        private ArraySegment<byte> GetData()
+        private Memory<byte> GetData()
         {
             return GetData(DateTime.Now);
         }
 
+
+
         public void Write(IStreamWriter stream)
         {
-            var data = DATE;
-            stream.Write(data.Array, 0, data.Count);
+
+            stream.Write(DATE.Span);
         }
 
-        private ArraySegment<byte> GetData(DateTime date)
+        private Memory<byte> GetData(DateTime date)
         {
             date = date.ToUniversalTime();
             int offset13 = 0;
@@ -190,7 +192,7 @@ namespace PlatformBenchmarks
             buffer[offset13] = _n;
             offset13++;
 
-            return new ArraySegment<byte>(GTM_BUFFER, 0, offset13);
+            return new Memory<byte>(GTM_BUFFER, 0, offset13);
         }
     }
 

+ 1 - 1
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.Caching.cs

@@ -33,7 +33,7 @@ namespace PlatformBenchmarks
             ContentLengthMemory content = new ContentLengthMemory();
             try
             {
-                var data = await _db.LoadCachedQueries(count);
+                var data = await DB.LoadCachedQueries(count);
                 stream.Write(_jsonResultPreamble.Data, 0, _jsonResultPreamble.Length);
                 content.Data = GetContentLengthMemory(stream);
                 GMTDate.Default.Write(stream);

+ 4 - 18
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.cs

@@ -47,7 +47,6 @@ namespace PlatformBenchmarks
 
         private static readonly AsciiString _path_Fortunes = "/fortunes";
 
-        private static readonly AsciiString _result_plaintext = "Hello, World!";
 
         private static readonly AsciiString _cached_worlds = "/cached-worlds";
 
@@ -55,19 +54,6 @@ namespace PlatformBenchmarks
 
 
 
-        private readonly static AsciiString _jsonPreamble =
-            _httpsuccess
-            + _headerContentTypeJson
-            + _headerServer
-            + _headerContentLength + _jsonPayloadSize.ToString() + _line;
-
-        private readonly static AsciiString _plaintextPreamble =
-              _httpsuccess
-              + _headerContentTypeText
-              + _headerServer
-              + _headerContentLength + _result_plaintext.Length.ToString() + _line;
-
-
         private readonly static AsciiString _jsonResultPreamble =
         _httpsuccess
         + _headerContentTypeJson
@@ -122,14 +108,14 @@ namespace PlatformBenchmarks
 
         private Queue<RequestData> _Requests = new Queue<RequestData>();
 
-        private RawDb _db;
+        public static RawDb DB;
 
         private RequestData _ReadRequest = null;
         public override void Connected(NetContext context)
         {
             base.Connected(context);
             this.Context = context;
-            _db = new RawDb(new ConcurrentRandom(), Npgsql.NpgsqlFactory.Instance); ;
+
         }
 
         private int AnalysisUrl(ReadOnlySpan<byte> url)
@@ -255,11 +241,11 @@ namespace PlatformBenchmarks
             Span<byte> baseUrl = stackalloc byte[baseurlLen];
             url.Slice(0, baseurlLen).CopyTo(baseUrl);
 
-            if (baseUrl.Length == _path_Plaintext.Length && baseUrl.StartsWith(_path_Plaintext))
+            if (baseUrl.Length == _path_Plaintext.Length && baseUrl[1] == 'p')
             {
                 type = ActionType.Plaintext;
             }
-            else if (baseUrl.Length == _path_Json.Length && baseUrl.StartsWith(_path_Json))
+            else if (baseUrl.Length == _path_Json.Length && baseUrl[1] == 'j')
             {
                 type = ActionType.Json;
             }

+ 2 - 2
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.db.cs

@@ -17,8 +17,8 @@ namespace PlatformBenchmarks
 
             try
             {
-                var data = await _db.LoadSingleQueryRow();
-                stream.Write(_jsonResultPreamble.Data, 0, _jsonResultPreamble.Length);
+                var data = await DB.LoadSingleQueryRow();
+                stream.Write(_jsonResultPreamble.AsSpan());
                 content.Data = GetContentLengthMemory(stream);
                 GMTDate.Default.Write(stream);
                 stream.WriteSequenceNetStream.StartWriteLength();

+ 12 - 12
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.fortunes.cs

@@ -21,11 +21,11 @@ namespace PlatformBenchmarks
             return HtmlEncoder.Create(settings);
         }
 
-        private readonly static AsciiString _fortunesTableStart = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>";
-        private readonly static AsciiString _fortunesRowStart = "<tr><td>";
-        private readonly static AsciiString _fortunesColumn = "</td><td>";
-        private readonly static AsciiString _fortunesRowEnd = "</td></tr>";
-        private readonly static AsciiString _fortunesTableEnd = "</table></body></html>";
+        private static ReadOnlySpan<byte> _fortunesTableStart => "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>"u8;
+        private static ReadOnlySpan<byte> _fortunesRowStart => "<tr><td>"u8;
+        private static ReadOnlySpan<byte> _fortunesColumn => "</td><td>"u8;
+        private static ReadOnlySpan<byte> _fortunesRowEnd => "</td></tr>"u8;
+        private static ReadOnlySpan<byte> _fortunesTableEnd => "</table></body></html>"u8;
 
 
         public async Task fortunes(IStreamWriter stream)
@@ -34,23 +34,23 @@ namespace PlatformBenchmarks
             try
             {
 
-                var data = await this._db.LoadFortunesRows();
+                var data = await DB.LoadFortunesRows();
 
-                stream.Write(_HtmlResultPreamble.Data, 0, _HtmlResultPreamble.Length);
+                stream.Write(_HtmlResultPreamble);
                 content.Data = GetContentLengthMemory(stream);
                 GMTDate.Default.Write(stream);
 
                 stream.WriteSequenceNetStream.StartWriteLength();
-                stream.Write(_fortunesTableStart.Data, 0, _fortunesTableStart.Length);
+                stream.Write(_fortunesTableStart);
                 foreach (var item in data)
                 {
-                    stream.Write(_fortunesRowStart.Data, 0, _fortunesRowStart.Length);
+                    stream.Write(_fortunesRowStart);
                     stream.WriteString(item.Id.ToString(CultureInfo.InvariantCulture));
-                    stream.Write(_fortunesColumn.Data, 0, _fortunesColumn.Length);
+                    stream.Write(_fortunesColumn);
                     stream.WriteString(htmlEncoder.Encode(item.Message));
-                    stream.Write(_fortunesRowEnd.Data, 0, _fortunesRowEnd.Length);
+                    stream.Write(_fortunesRowEnd);
                 }
-                stream.Write(_fortunesTableEnd.Data, 0, _fortunesTableEnd.Length);
+                stream.Write(_fortunesTableEnd);
             }
             catch (Exception e_)
             {

+ 7 - 3
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.json.cs

@@ -14,10 +14,14 @@ namespace PlatformBenchmarks
     public partial class HttpHandler
     {
 
-
+        private static ReadOnlySpan<byte> _jsonPreamble =>
+     "HTTP/1.1 200 OK\r\n"u8 +
+     "Server: B\r\n"u8 +
+     "Content-Type: application/json\r\n"u8 +
+     "Content-Length: 27\r\n"u8;
         public void Json(IStreamWriter stream)
         {
-            stream.Write(_jsonPreamble.Data, 0, _jsonPreamble.Length);
+            stream.Write(_jsonPreamble);
             GMTDate.Default.Write(stream);
             var jsonWriter = GetJsonWriter(stream);
             using (var unflush = stream.UnFlush())
@@ -27,7 +31,7 @@ namespace PlatformBenchmarks
                 jsonWriter.WriteEndObject();
                 jsonWriter.Flush();
             }
-            
+
         }
     }
 }

+ 19 - 4
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.plaintext.cs

@@ -2,6 +2,7 @@
 using BeetleX.Light.Memory;
 using System;
 using System.Collections.Generic;
+using System.Data;
 using System.Text;
 using System.Threading.Tasks;
 
@@ -9,13 +10,27 @@ namespace PlatformBenchmarks
 {
     public partial class HttpHandler
     {
-      
 
+        private static ReadOnlySpan<byte> _plaintextPreamble =>
+       "HTTP/1.1 200 OK\r\n"u8 +
+       "Server: B\r\n"u8 +
+       "Content-Type: text/plain\r\n"u8 +
+       "Content-Length: 13\r\n"u8;
+
+        private static ReadOnlySpan<byte> _plainTextBody => "Hello, World!"u8;
         public void Plaintext(IStreamWriter stream)
         {
-            stream.Write(_plaintextPreamble.Data, 0, _plaintextPreamble.Length);
-            GMTDate.Default.Write(stream);
-            stream.Write(_result_plaintext.Data, 0, _result_plaintext.Length);
+            Span<byte> data = stream.WriteSequenceNetStream.GetWriteSpan(256);
+            var timedata = GMTDate.Default.DATE;
+            _plaintextPreamble.CopyTo(data);
+            data = data.Slice(_plaintextPreamble.Length);
+            timedata.Span.CopyTo(data);
+            data = data.Slice(timedata.Length);
+            _plainTextBody.CopyTo(data);
+            //stream.Write(_plaintextPreamble.AsSpan());
+            //GMTDate.Default.Write(stream);
+            //stream.Write(_result_plaintext.Data.AsSpan());
+            stream.WriteSequenceNetStream.WriteAdvance(_plaintextPreamble.Length + timedata.Length + _plainTextBody.Length);
         }
     }
 }

+ 1 - 1
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.queries.cs

@@ -31,7 +31,7 @@ namespace PlatformBenchmarks
             ContentLengthMemory content = new ContentLengthMemory();
             try
             {
-                var data = await _db.LoadMultipleQueriesRows(count);
+                var data = await DB.LoadMultipleQueriesRows(count);
                 stream.Write(_jsonResultPreamble.Data, 0, _jsonResultPreamble.Length);
                 content.Data = GetContentLengthMemory(stream);
                 GMTDate.Default.Write(stream);

+ 1 - 1
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.updates.cs

@@ -32,7 +32,7 @@ namespace PlatformBenchmarks
             ContentLengthMemory content = new ContentLengthMemory();
             try
             {
-                var data = await _db.LoadMultipleUpdatesRows(count);
+                var data = await DB.LoadMultipleUpdatesRows(count);
 
                 stream.Write(_jsonResultPreamble.Data, 0, _jsonResultPreamble.Length);
                 content.Data = GetContentLengthMemory(stream);

+ 10 - 18
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpServer.cs

@@ -13,13 +13,19 @@ namespace PlatformBenchmarks
     {
         private static NetServer<HttpNetApplication, HttpHandler> _apiServer;
 
-        public virtual Task StartAsync(CancellationToken cancellationToken)
+        public static string _connectionString;
+
+        public virtual async Task StartAsync(CancellationToken cancellationToken)
         {
+            _connectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=16;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000";
+            //_connectionString = "Server=localhost;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=16;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000";
             ThreadPool.SetMinThreads(Environment.ProcessorCount * 2, Environment.ProcessorCount * 2);
-            Constants.MemorySegmentMinSize = 1024 * 8;
-            Constants.MemorySegmentMaxSize = 1024 * 8;
+            Constants.MemorySegmentMinSize = 1024 * 16;
+            Constants.MemorySegmentMaxSize = 1024 * 16;
             Constants.InitMemoryBlock();
-            ArraySegment<byte> date = GMTDate.Default.DATE;
+            var date = GMTDate.Default.DATE;
+            HttpHandler.DB = new RawDb(new ConcurrentRandom(), HttpServer._connectionString);
+            await HttpHandler.DB.PopulateCache();
             _apiServer = new NetServer<HttpNetApplication, HttpHandler>();
             _apiServer.Options.LogLevel = BeetleX.Light.Logs.LogLevel.Error;
             _apiServer.Options.AddLogOutputHandler<LogOutputToConsole>();
@@ -30,20 +36,6 @@ namespace PlatformBenchmarks
             _apiServer.Start();
 
 
-            if (!Program.UpDB)
-            {
-                RawDb._connectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=64;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000";
-                //RawDb._connectionString = "Server=127.0.0.1;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=256;NoResetOnClose=true;Enlist=false;Max Auto Prepare=3";
-            }
-            else
-            {
-
-                 RawDb._connectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=64;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000";
-                //RawDb._connectionString = "Server=127.0.0.1;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=64;NoResetOnClose=true;Enlist=false;Max Auto Prepare=3";
-            }
-            // ApiServer.Log(LogType.Info, null, $"Debug mode [{Program.Debug}]");
-            return Task.CompletedTask;
-
         }
 
         public virtual Task StopAsync(CancellationToken cancellationToken)

Some files were not shown because too many files changed in this diff