Browse Source

beetlex framework add db and queries cases (#4866)

* docker add COMPlus_ReadyToRun variable
update beetlex

* update beetlex, enabled thread queue

* beetlex framework add db and queries cases

* add db code

* change result json data

* update query url
Henry 6 years ago
parent
commit
4b5fcb6f22

+ 1 - 0
frameworks/CSharp/beetlex/Benchmarks/Benchmarks.csproj

@@ -9,6 +9,7 @@
   <ItemGroup>
   <ItemGroup>
     <PackageReference Include="BeetleX.FastHttpApi" Version="1.5.2.6" />
     <PackageReference Include="BeetleX.FastHttpApi" Version="1.5.2.6" />
     <PackageReference Include="Microsoft.Extensions.Hosting" Version="2.1.1" />
     <PackageReference Include="Microsoft.Extensions.Hosting" Version="2.1.1" />
+    <PackageReference Include="Npgsql" Version="4.0.7" />
     <PackageReference Include="SpanJson" Version="2.0.10" />
     <PackageReference Include="SpanJson" Version="2.0.10" />
   </ItemGroup>
   </ItemGroup>
 
 

+ 31 - 0
frameworks/CSharp/beetlex/Benchmarks/ConcurrentRandom.cs

@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading;
+
+namespace Benchmarks
+{
+    public class ConcurrentRandom
+    {
+        private static int nextSeed = 0;
+
+        // Random isn't thread safe
+        [ThreadStatic]
+        private static Random _random;
+
+        private static Random Random => _random ?? CreateRandom();
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static Random CreateRandom()
+        {
+            _random = new Random(Interlocked.Increment(ref nextSeed));
+            return _random;
+        }
+
+        public int Next(int minValue, int maxValue)
+        {
+            return Random.Next(minValue, maxValue);
+        }
+    }
+}

+ 94 - 0
frameworks/CSharp/beetlex/Benchmarks/DBRaw.cs

@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Common;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Benchmarks
+{
+    public class RawDb
+    {
+    
+        private readonly ConcurrentRandom _random;
+
+        private readonly DbProviderFactory _dbProviderFactory;
+
+        private readonly string _connectionString;
+
+        public RawDb(ConcurrentRandom random, DbProviderFactory dbProviderFactory)
+        {
+            _random = random;
+            _dbProviderFactory = dbProviderFactory;
+            _connectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=256;NoResetOnClose=true;Enlist=false;Max Auto Prepare=3";
+        }
+
+        public async Task<World> LoadSingleQueryRow()
+        {
+            using (var db = _dbProviderFactory.CreateConnection())
+            {
+                db.ConnectionString = _connectionString;
+                await db.OpenAsync();
+
+                using (var cmd = CreateReadCommand(db))
+                {
+                    return await ReadSingleRow(db, cmd);
+                }
+            }
+        }
+
+        async Task<World> ReadSingleRow(DbConnection connection, DbCommand cmd)
+        {
+            using (var rdr = await cmd.ExecuteReaderAsync(CommandBehavior.SingleRow))
+            {
+                await rdr.ReadAsync();
+
+                return new World
+                {
+                    Id = rdr.GetInt32(0),
+                    RandomNumber = rdr.GetInt32(1)
+                };
+            }
+        }
+
+        DbCommand CreateReadCommand(DbConnection connection)
+        {
+            var cmd = connection.CreateCommand();
+            cmd.CommandText = "SELECT id, randomnumber FROM world WHERE id = @Id";
+            var id = cmd.CreateParameter();
+            id.ParameterName = "@Id";
+            id.DbType = DbType.Int32;
+            id.Value = _random.Next(1, 10001);
+            cmd.Parameters.Add(id);
+            return cmd;
+        }
+
+
+        public async Task<World[]> LoadMultipleQueriesRows(int count)
+        {
+            using (var db = _dbProviderFactory.CreateConnection())
+            {
+                db.ConnectionString = _connectionString;
+                await db.OpenAsync();
+                return await LoadMultipleRows(count, db);
+            }
+
+        }
+
+        private async Task<World[]> LoadMultipleRows(int count, DbConnection db)
+        {
+            using (var cmd = CreateReadCommand(db))
+            {
+                cmd.Parameters["@Id"].Value = _random.Next(1, 10001);
+
+                var result = new World[count];
+                for (int i = 0; i < result.Length; i++)
+                {
+                    result[i] = await ReadSingleRow(db, cmd);
+                    cmd.Parameters["@Id"].Value = _random.Next(1, 10001);
+                }
+                return result;
+            }
+        }
+    }
+}

+ 34 - 22
frameworks/CSharp/beetlex/Benchmarks/Program.cs

@@ -7,11 +7,12 @@ using System.Threading;
 using System.Text;
 using System.Text;
 using BeetleX.Buffers;
 using BeetleX.Buffers;
 using SpanJson;
 using SpanJson;
+using System.Collections.Generic;
 
 
 namespace Benchmarks
 namespace Benchmarks
 {
 {
     [Controller]
     [Controller]
-    class Program
+    class Program:IController
     {
     {
         public static void Main(string[] args)
         public static void Main(string[] args)
         {
         {
@@ -22,8 +23,38 @@ namespace Benchmarks
                 });
                 });
             builder.Build().Run();
             builder.Build().Run();
         }
         }
-    }
 
 
+        public object plaintext()
+        {
+            return BeetleXHttpServer.plaintextResult;
+        }
+
+        public object json()
+        {
+            return new SpanJsonResult(new JsonMessage { message = "Hello, World!" });
+        }
+
+        public async Task<object> queries(int queries)
+        {
+            queries = queries < 1 ? 1 : queries > 500 ? 500 : queries;
+            var result = await mPgsql.LoadMultipleQueriesRows(queries);
+            return new SpanJsonResult(result);
+        }
+
+        public async Task<object> db()
+        {
+            var result = await mPgsql.LoadSingleQueryRow();
+            return new SpanJsonResult(result);
+        }
+
+        private RawDb mPgsql;
+
+        [NotAction]
+        public void Init(HttpApiServer server, string path)
+        {
+            mPgsql = new RawDb(new ConcurrentRandom(), Npgsql.NpgsqlFactory.Instance);
+        }
+    }
 
 
     public class BeetleXHttpServer : IHostedService
     public class BeetleXHttpServer : IHostedService
     {
     {
@@ -34,24 +65,6 @@ namespace Benchmarks
 
 
         private HttpApiServer mApiServer;
         private HttpApiServer mApiServer;
 
 
-        public void OnRequesting(object sender, EventHttpRequestArgs e)
-        {
-            if (e.Request.BaseUrl == "/plaintext")
-            {
-                e.Response.Result(plaintextResult);
-            }
-            else if (e.Request.BaseUrl == "/json")
-            {
-                var json = new SpanJsonResult(new JsonMessage { message = "Hello, World!" });
-                e.Response.Result(json);
-            }
-            else
-            {
-                e.Response.Result(new NotFoundResult("url not found!"));
-            }
-            e.Cancel = true;
-        }
-
         public virtual Task StartAsync(CancellationToken cancellationToken)
         public virtual Task StartAsync(CancellationToken cancellationToken)
         {
         {
             plaintextResult = new StringBytes(_helloWorldPayload);
             plaintextResult = new StringBytes(_helloWorldPayload);
@@ -61,12 +74,11 @@ namespace Benchmarks
             mApiServer.Options.MaxConnections = 100000;
             mApiServer.Options.MaxConnections = 100000;
             mApiServer.Options.Statistical = false;
             mApiServer.Options.Statistical = false;
             mApiServer.Options.UrlIgnoreCase = false;
             mApiServer.Options.UrlIgnoreCase = false;
-            mApiServer.Options.LogLevel = BeetleX.EventArgs.LogType.Off;
+            mApiServer.Options.LogLevel = BeetleX.EventArgs.LogType.Error;
             mApiServer.Options.LogToConsole = true;
             mApiServer.Options.LogToConsole = true;
             mApiServer.Options.PrivateBufferPool = true;
             mApiServer.Options.PrivateBufferPool = true;
             mApiServer.Options.IOQueueEnabled = true;
             mApiServer.Options.IOQueueEnabled = true;
             mApiServer.Register(typeof(Program).Assembly);
             mApiServer.Register(typeof(Program).Assembly);
-            mApiServer.HttpRequesting += OnRequesting;
             mApiServer.Open();
             mApiServer.Open();
             return Task.CompletedTask;
             return Task.CompletedTask;
         }
         }

+ 15 - 0
frameworks/CSharp/beetlex/Benchmarks/World.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Benchmarks
+{
+    [StructLayout(LayoutKind.Sequential, Size = 8)]
+    public struct World
+    {
+        public int Id { get; set; }
+
+        public int RandomNumber { get; set; }
+    }
+}

+ 4 - 2
frameworks/CSharp/beetlex/benchmark_config.json

@@ -5,16 +5,18 @@
       "default": {
       "default": {
         "plaintext_url": "/plaintext",
         "plaintext_url": "/plaintext",
         "json_url": "/json",
         "json_url": "/json",
+        "db_url": "/db",
+        "query_url": "/queries?queries=",
         "port": 8080,
         "port": 8080,
         "approach": "Realistic",
         "approach": "Realistic",
         "classification": "Micro",
         "classification": "Micro",
-        "database": "None",
+        "database": "Postgres",
         "framework": "beetlex",
         "framework": "beetlex",
         "language": "C#",
         "language": "C#",
         "orm": "Raw",
         "orm": "Raw",
         "platform": ".NET",
         "platform": ".NET",
         "flavor": "CoreCLR",
         "flavor": "CoreCLR",
-        "webserver": "BeetleX",
+        "webserver": "beetlex",
         "os": "Linux",
         "os": "Linux",
         "database_os": "Linux",
         "database_os": "Linux",
         "display_name": "beetlex",
         "display_name": "beetlex",