Browse Source

add beetlex core cases (#4879)

* 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

* beetlex framework add fortunes cases

* change Content-Type

* add beetlex core cases

* fix queries cases

* update config
Henry 6 years ago
parent
commit
688e4dfbea

+ 6 - 0
frameworks/CSharp/beetlex/Benchmarks.sln

@@ -5,6 +5,8 @@ VisualStudioVersion = 15.0.28010.2036
 MinimumVisualStudioVersion = 10.0.40219.1
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{12CA0190-5EA2-460F-ABC4-FAD454148EBF}"
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{12CA0190-5EA2-460F-ABC4-FAD454148EBF}"
 EndProject
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlatformBenchmarks", "PlatformBenchmarks\PlatformBenchmarks.csproj", "{8ACF83AD-E861-4642-BEF3-A6211F99389D}"
+EndProject
 Global
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
 		Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
 		{12CA0190-5EA2-460F-ABC4-FAD454148EBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{12CA0190-5EA2-460F-ABC4-FAD454148EBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{12CA0190-5EA2-460F-ABC4-FAD454148EBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{12CA0190-5EA2-460F-ABC4-FAD454148EBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{12CA0190-5EA2-460F-ABC4-FAD454148EBF}.Release|Any CPU.Build.0 = Release|Any CPU
 		{12CA0190-5EA2-460F-ABC4-FAD454148EBF}.Release|Any CPU.Build.0 = Release|Any CPU
+		{8ACF83AD-E861-4642-BEF3-A6211F99389D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{8ACF83AD-E861-4642-BEF3-A6211F99389D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{8ACF83AD-E861-4642-BEF3-A6211F99389D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{8ACF83AD-E861-4642-BEF3-A6211F99389D}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 		HideSolutionNode = FALSE

+ 96 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/AsciiString.cs

@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PlatformBenchmarks
+{
+    public readonly struct AsciiString : IEquatable<AsciiString>
+    {
+        private readonly byte[] _data;
+
+        public byte[] Data => _data;
+
+        public int Length => _data.Length;
+
+        public AsciiString(string s)
+        {
+            _data = Encoding.ASCII.GetBytes(s);
+        }
+
+        public ReadOnlySpan<byte> AsSpan()
+        {
+            return _data;
+        }
+
+        public static implicit operator ReadOnlySpan<byte>(AsciiString str)
+        {
+            return str._data;
+        }
+
+        public static implicit operator byte[] (AsciiString str)
+        {
+            return str._data;
+        }
+
+        public static implicit operator AsciiString(string str)
+        {
+            return new AsciiString(str);
+        }
+
+        public override string ToString()
+        {
+            return Encoding.ASCII.GetString(_data);
+        }
+
+        public static explicit operator string(AsciiString str)
+        {
+            return str.ToString();
+        }
+
+        public bool Equals(AsciiString other)
+        {
+            if (_data != other._data)
+            {
+                return SequenceEqual(_data, other._data);
+            }
+            return true;
+        }
+
+        private bool SequenceEqual(byte[] data1, byte[] data2)
+        {
+            return new Span<byte>(data1).SequenceEqual(data2);
+        }
+
+        public static bool operator ==(AsciiString a, AsciiString b)
+        {
+            return a.Equals(b);
+        }
+
+        public static bool operator !=(AsciiString a, AsciiString b)
+        {
+            return !a.Equals(b);
+        }
+
+        public override bool Equals(object other)
+        {
+            if (other is AsciiString)
+            {
+                return Equals((AsciiString)other);
+            }
+            return false;
+        }
+
+        public override int GetHashCode()
+        {
+            byte[] data = _data;
+            int hash3 = 5381;
+            int hash2 = hash3;
+            byte[] array = data;
+            foreach (int b in array)
+            {
+                hash3 = (((hash3 << 5) + hash3) ^ b);
+            }
+            return hash3 + hash2 * 1566083941;
+        }
+    }
+}

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

@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading;
+
+namespace PlatformBenchmarks
+{
+    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);
+        }
+    }
+}

+ 124 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/DBRaw.cs

@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Common;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PlatformBenchmarks
+{
+    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";
+            //_connectionString = "Server=192.168.2.19;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;
+            }
+        }
+
+        public async Task<List<Fortune>> LoadFortunesRows()
+        {
+            var result = new List<Fortune>();
+
+            using (var db = _dbProviderFactory.CreateConnection())
+            using (var cmd = db.CreateCommand())
+            {
+                cmd.CommandText = "SELECT id, message FROM fortune";
+
+                db.ConnectionString = _connectionString;
+                await db.OpenAsync();
+                using (var rdr = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection))
+                {
+                    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();
+            return result;
+        }
+    }
+}

+ 24 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/Fortune.cs

@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PlatformBenchmarks
+{
+    public class Fortune : IComparable<Fortune>, IComparable
+    {
+        public int Id { get; set; }
+
+        public string Message { get; set; }
+
+        public int CompareTo(object obj)
+        {
+            return CompareTo((Fortune)obj);
+        }
+
+        public int CompareTo(Fortune other)
+        {
+            // Performance critical, using culture insensitive comparison
+            return String.CompareOrdinal(Message, other.Message);
+        }
+    }
+}

+ 186 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/GMTDate.cs

@@ -0,0 +1,186 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+
+namespace PlatformBenchmarks
+{
+    internal class GMTDate
+    {
+        private List<byte[]> mWeekBuffers = new List<byte[]>();
+
+        public List<byte[]> mYears = new List<byte[]>();
+
+        public List<byte[]> mMoth = new List<byte[]>();
+
+        public List<byte[]> mNumber = new List<byte[]>();
+
+        private byte _1 = 58;
+
+        private byte _s = 32;
+
+        private byte _r = 13;
+
+        private byte _n = 10;
+
+        private byte[] GMT = new byte[3]
+        {
+        71,
+        77,
+        84
+        };
+
+        private static GMTDate mDefault;
+
+        private Timer mUpdateTime;
+
+        public static GMTDate Default
+        {
+            get
+            {
+                if (mDefault == null)
+                {
+                    mDefault = new GMTDate();
+                    mDefault.Init();
+                }
+                return mDefault;
+            }
+        }
+
+        public ArraySegment<byte> DATE
+        {
+            get;
+            set;
+        }
+
+        public GMTDate()
+        {
+            mWeekBuffers.Add(Encoding.ASCII.GetBytes("Sun"));
+            mWeekBuffers.Add(Encoding.ASCII.GetBytes("Mon"));
+            mWeekBuffers.Add(Encoding.ASCII.GetBytes("Tue"));
+            mWeekBuffers.Add(Encoding.ASCII.GetBytes("Wed"));
+            mWeekBuffers.Add(Encoding.ASCII.GetBytes("Thu"));
+            mWeekBuffers.Add(Encoding.ASCII.GetBytes("Fri"));
+            mWeekBuffers.Add(Encoding.ASCII.GetBytes("Sat"));
+            for (int j = 1970; j < 2470; j++)
+            {
+                mYears.Add(Encoding.ASCII.GetBytes(j.ToString()));
+            }
+            for (int i = 0; i <= 100; i++)
+            {
+                mNumber.Add(Encoding.ASCII.GetBytes(i.ToString("00")));
+            }
+            mMoth.Add(Encoding.ASCII.GetBytes("Jan"));
+            mMoth.Add(Encoding.ASCII.GetBytes("Feb"));
+            mMoth.Add(Encoding.ASCII.GetBytes("Mar"));
+            mMoth.Add(Encoding.ASCII.GetBytes("Apr"));
+            mMoth.Add(Encoding.ASCII.GetBytes("May"));
+            mMoth.Add(Encoding.ASCII.GetBytes("Jun"));
+            mMoth.Add(Encoding.ASCII.GetBytes("Jul"));
+            mMoth.Add(Encoding.ASCII.GetBytes("Aug"));
+            mMoth.Add(Encoding.ASCII.GetBytes("Sep"));
+            mMoth.Add(Encoding.ASCII.GetBytes("Oct"));
+            mMoth.Add(Encoding.ASCII.GetBytes("Nov"));
+            mMoth.Add(Encoding.ASCII.GetBytes("Dec"));
+        }
+
+        private void Init()
+        {
+            DATE = GetData(inLine: true);
+            mUpdateTime = new Timer(delegate
+            {
+                DATE = GetData(inLine: true);
+            }, null, 1000, 1000);
+        }
+
+        private ArraySegment<byte> GetData(bool inLine = false)
+        {
+            return GetData(DateTime.Now, inLine);
+        }
+
+        private ArraySegment<byte> GetData(DateTime date, bool inLine = false)
+        {
+            date = date.ToUniversalTime();
+            int offset13 = 0;
+            byte[] GTM_BUFFER = new byte[50];
+            Encoding.ASCII.GetBytes("Date: ", 0, 6, GTM_BUFFER, 0);
+            offset13 = 6;
+            byte[] buffer = GTM_BUFFER;
+            byte[] sub8 = mWeekBuffers[(int)date.DayOfWeek];
+            buffer[offset13] = sub8[0];
+            offset13++;
+            buffer[offset13] = sub8[1];
+            offset13++;
+            buffer[offset13] = sub8[2];
+            offset13++;
+            buffer[offset13] = 44;
+            offset13++;
+            buffer[offset13] = _s;
+            offset13++;
+            sub8 = mNumber[date.Day];
+            buffer[offset13] = sub8[0];
+            offset13++;
+            buffer[offset13] = sub8[1];
+            offset13++;
+            buffer[offset13] = _s;
+            offset13++;
+            sub8 = mMoth[date.Month - 1];
+            buffer[offset13] = sub8[0];
+            offset13++;
+            buffer[offset13] = sub8[1];
+            offset13++;
+            buffer[offset13] = sub8[2];
+            offset13++;
+            buffer[offset13] = _s;
+            offset13++;
+            sub8 = mYears[date.Year - 1970];
+            buffer[offset13] = sub8[0];
+            offset13++;
+            buffer[offset13] = sub8[1];
+            offset13++;
+            buffer[offset13] = sub8[2];
+            offset13++;
+            buffer[offset13] = sub8[3];
+            offset13++;
+            buffer[offset13] = _s;
+            offset13++;
+            sub8 = mNumber[date.Hour];
+            buffer[offset13] = sub8[0];
+            offset13++;
+            buffer[offset13] = sub8[1];
+            offset13++;
+            buffer[offset13] = _1;
+            offset13++;
+            sub8 = mNumber[date.Minute];
+            buffer[offset13] = sub8[0];
+            offset13++;
+            buffer[offset13] = sub8[1];
+            offset13++;
+            buffer[offset13] = _1;
+            offset13++;
+            sub8 = mNumber[date.Second];
+            buffer[offset13] = sub8[0];
+            offset13++;
+            buffer[offset13] = sub8[1];
+            offset13++;
+            buffer[offset13] = _s;
+            offset13++;
+            sub8 = GMT;
+            buffer[offset13] = sub8[0];
+            offset13++;
+            buffer[offset13] = sub8[1];
+            offset13++;
+            buffer[offset13] = sub8[2];
+            offset13++;
+            if (inLine)
+            {
+                buffer[offset13] = _r;
+                offset13++;
+                buffer[offset13] = _n;
+                offset13++;
+            }
+            return new ArraySegment<byte>(GTM_BUFFER, 0, offset13);
+        }
+    }
+
+}

+ 196 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.cs

@@ -0,0 +1,196 @@
+using BeetleX;
+using BeetleX.Buffers;
+using BeetleX.EventArgs;
+using SpanJson;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PlatformBenchmarks
+{
+    public partial class HttpHandler : ServerHandlerBase
+    {
+        private static AsciiString _line = new AsciiString("\r\n");
+
+        private static AsciiString _2line = new AsciiString("\r\n\r\n");
+
+        private static AsciiString _httpsuccess = new AsciiString("HTTP/1.1 200 OK\r\n");
+
+        private static readonly AsciiString _headerServer = "Server: Beetlex\r\n";
+
+        private static readonly AsciiString _headerContentLength = "Content-Length: ";
+
+        private static readonly AsciiString _headerContentLengthZero = "Content-Length: 0\r\n";
+
+        private static readonly AsciiString _headerContentTypeText = "Content-Type: text/plain\r\n";
+
+        private static readonly AsciiString _headerContentTypeHtml = "Content-Type: text/html; charset=UTF-8\r\n";
+
+        private static readonly AsciiString _headerContentTypeJson = "Content-Type: application/json\r\n";
+
+        private static readonly AsciiString _path_Json = "/json";
+
+        private static readonly AsciiString _path_Db = "/db";
+
+        private static readonly AsciiString _path_Queries = "/queries";
+
+        private static readonly AsciiString _path_Plaintext = "/plaintext";
+
+        private static readonly AsciiString _path_Fortunes = "/fortunes";
+
+        private static readonly AsciiString _result_plaintext = "Hello, World!";
+
+        private static byte _Space = 32;
+
+        private static byte _question = 63;
+
+        private RawDb mPgsql;
+
+        public HttpHandler()
+        {
+
+            mPgsql = new RawDb(new ConcurrentRandom(), Npgsql.NpgsqlFactory.Instance);
+        }
+
+        public void Default(ReadOnlySpan<byte> url, PipeStream stream, HttpToken token, ISession session)
+        {
+            stream.Write("<b> beetlex server</b><hr/>");
+            stream.Write($"{Encoding.ASCII.GetString(url)} not found!");
+            OnCompleted(stream, session, token);
+        }
+
+        public override void Connected(IServer server, ConnectedEventArgs e)
+        {
+            base.Connected(server, e);
+            e.Session.Tag = new HttpToken();
+        }
+
+        private int AnalysisUrl(ReadOnlySpan<byte> url)
+        {
+            for (int i = 0; i < url.Length; i++)
+            {
+                if (url[i] == _question)
+                    return i;
+            }
+            return -1;
+
+        }
+
+        public override void SessionReceive(IServer server, SessionReceiveEventArgs e)
+        {
+            base.SessionReceive(server, e);
+            PipeStream pipeStream = e.Session.Stream.ToPipeStream();
+            HttpToken token = (HttpToken)e.Session.Tag;
+            int len = pipeStream.IndexOf(_line.Data, token.Buffer);
+            if (len <= 0)
+            {
+                return;
+            }
+            ReadOnlySpan<byte> line = new Span<byte>(token.Buffer, 0, len);
+            ReadOnlySpan<byte> http = line;
+            ReadOnlySpan<byte> method = line;
+            ReadOnlySpan<byte> url = line;
+            int offset2 = 0;
+            int count = 0;
+            for (int i = 0; i < line.Length; i++)
+            {
+                if (line[i] == _Space)
+                {
+                    if (count != 0)
+                    {
+                        url = line.Slice(offset2, i - offset2);
+                        offset2 = i + 1;
+                        http = line.Slice(offset2, line.Length - offset2 - 2);
+                        break;
+                    }
+                    method = line.Slice(offset2, i - offset2);
+                    offset2 = i + 1;
+                    count++;
+                }
+            }
+            OnStartLine(http, method, url, e.Session, token, pipeStream);
+        }
+
+
+
+        protected virtual void OnStartLine(ReadOnlySpan<byte> http, ReadOnlySpan<byte> method, ReadOnlySpan<byte> url, ISession session, HttpToken token, PipeStream stream)
+        {
+            int queryIndex = AnalysisUrl(url);
+            ReadOnlySpan<byte> baseUrl=default;
+            ReadOnlySpan<byte> queryString = default;
+            if (queryIndex>0)
+            {
+                baseUrl = url.Slice(0, queryIndex);
+                queryString = url.Slice(queryIndex+1, url.Length - queryIndex - 1);
+            }
+            else
+            {
+                baseUrl = url;
+            }
+            OnWriteHeader(stream, token);         
+            if (baseUrl.Length== _path_Plaintext.Length && baseUrl.StartsWith(_path_Plaintext))
+            {
+                stream.Write(_headerContentTypeText.Data, 0, _headerContentTypeText.Length);
+                OnWriteContentLength(stream, token);
+                Plaintext(url, stream, token, session);
+            }
+            else if (baseUrl.Length==_path_Json.Length && baseUrl.StartsWith(_path_Json))
+            {
+                stream.Write(_headerContentTypeJson.Data, 0, _headerContentTypeJson.Length);
+                OnWriteContentLength(stream, token);
+                Json(url, stream, token, session);
+            }
+            else if(baseUrl.Length == _path_Db.Length && baseUrl.StartsWith(_path_Db))
+            {
+                stream.Write(_headerContentTypeJson.Data, 0, _headerContentTypeJson.Length);
+                OnWriteContentLength(stream, token);
+                db(stream, token, session);
+            }
+            else if(baseUrl.Length == _path_Queries.Length && baseUrl.StartsWith(_path_Queries))
+            {
+                stream.Write(_headerContentTypeJson.Data, 0, _headerContentTypeJson.Length);
+                OnWriteContentLength(stream, token);
+                queries(Encoding.ASCII.GetString(queryString), stream, token, session);
+            }
+            else if(baseUrl.Length == _path_Fortunes.Length && baseUrl.StartsWith(_path_Fortunes))
+            {
+                stream.Write(_headerContentTypeHtml.Data, 0, _headerContentTypeHtml.Length);
+                OnWriteContentLength(stream, token);
+                fortunes(stream, token, session);
+            }
+            else
+            {
+                stream.Write(_headerContentTypeHtml.Data, 0, _headerContentTypeHtml.Length);
+                OnWriteContentLength(stream, token);
+                Default(url, stream, token, session);
+            }
+        }
+
+        private void OnWriteHeader(PipeStream stream, HttpToken token)
+        {
+            stream.Write(_httpsuccess.Data, 0, _httpsuccess.Length);
+            stream.Write(_headerServer.Data, 0, _headerServer.Length);
+            ArraySegment<byte> date = GMTDate.Default.DATE;
+            stream.Write(date.Array, date.Offset, date.Count);
+        }
+
+        private void OnWriteContentLength(PipeStream stream, HttpToken token)
+        {
+            stream.Write(_headerContentLength.Data, 0, _headerContentLength.Length);
+            token.ContentLength = stream.Allocate(10);
+            stream.Write(_2line, 0, 4);
+            token.ContentPostion = stream.CacheLength;
+        }
+
+        private void OnCompleted(PipeStream stream, ISession session, HttpToken token)
+        {
+            stream.ReadFree((int)stream.Length);
+            token.FullLength((stream.CacheLength - token.ContentPostion).ToString());
+            session.Stream.Flush();
+        }
+
+
+
+
+    }
+}

+ 39 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpServer.cs

@@ -0,0 +1,39 @@
+using BeetleX;
+using BeetleX.EventArgs;
+using Microsoft.Extensions.Hosting;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace PlatformBenchmarks
+{
+    public class HttpServer : IHostedService
+    {
+        private IServer mApiServer;
+
+        public virtual Task StartAsync(CancellationToken cancellationToken)
+        {
+            ArraySegment<byte> date = GMTDate.Default.DATE;
+            ServerOptions serverOptions = new ServerOptions();
+            serverOptions.LogLevel = LogType.Error;
+            serverOptions.DefaultListen.Port = 8080;
+            serverOptions.Statistical = false;
+            serverOptions.PrivateBufferPool = true;
+            serverOptions.BufferSize = 1024 * 4;
+            serverOptions.PrivateBufferPool = true;
+            serverOptions.MaxConnections = 100000;
+            serverOptions.BufferPoolMaxMemory = 500;
+            mApiServer = SocketFactory.CreateTcpServer<HttpHandler>(serverOptions);
+            mApiServer.Open();
+            return Task.CompletedTask;
+        }
+
+        public virtual Task StopAsync(CancellationToken cancellationToken)
+        {
+            mApiServer.Dispose();
+            return Task.CompletedTask;
+        }
+    }
+}

+ 44 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/HttpToken.cs

@@ -0,0 +1,44 @@
+using BeetleX.Buffers;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PlatformBenchmarks
+{
+    public class HttpToken
+    {
+        private byte[] mLengthBuffer = new byte[10];
+
+        public byte[] Buffer
+        {
+            get;
+            private set;
+        }       
+
+        public HttpToken()
+        {
+            Buffer = new byte[2048];
+        }
+
+        public byte[] GetLengthBuffer(string length)
+        {
+            Encoding.ASCII.GetBytes(length, 0, length.Length, mLengthBuffer, 0);
+            for (int i = length.Length; i < 10; i++)
+            {
+                mLengthBuffer[i] = 32;
+            }
+            return mLengthBuffer;
+        }
+
+        public int ContentPostion { get; set; }
+
+        public  MemoryBlockCollection ContentLength { get; set; }
+
+        public void FullLength(string length)
+        {
+            var item = GetLengthBuffer(length);
+            ContentLength.Full(item);
+        }
+        
+    }
+}

+ 15 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/JsonMessage.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PlatformBenchmarks
+{
+    public struct JsonMessage
+    {
+        public string message
+        {
+            get;
+            set;
+        }
+    }
+}

+ 17 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/PlatformBenchmarks.csproj

@@ -0,0 +1,17 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.2</TargetFramework>
+    <ServerGarbageCollection>true</ServerGarbageCollection>
+    <LangVersion>7.2</LangVersion>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="BeetleX" Version="1.3.2" />
+    <PackageReference Include="Microsoft.Extensions.Hosting" Version="2.2.0" />
+    <PackageReference Include="Npgsql" Version="4.0.7" />
+    <PackageReference Include="SpanJson" Version="2.0.14" />
+  </ItemGroup>
+
+</Project>

+ 17 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/Program.cs

@@ -0,0 +1,17 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using System;
+
+namespace PlatformBenchmarks
+{
+    class Program
+    {
+        public static void Main(string[] args)
+        {
+            new HostBuilder().ConfigureServices(delegate (HostBuilderContext hostContext, IServiceCollection services)
+            {
+                services.AddHostedService<HttpServer>();
+            }).Build().Run();
+        }
+    }
+}

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

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

+ 27 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/db.cs

@@ -0,0 +1,27 @@
+using BeetleX;
+using BeetleX.Buffers;
+using SpanJson;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PlatformBenchmarks
+{
+    public partial class HttpHandler
+    {
+
+        public async void db(PipeStream stream, HttpToken token, ISession session)
+        {
+            try
+            {
+                var data = await mPgsql.LoadSingleQueryRow();
+                await JsonSerializer.NonGeneric.Utf8.SerializeAsync(data, stream);
+            }
+            catch(Exception e_)
+            {
+                stream.Write(e_.Message);
+            }
+            OnCompleted(stream, session, token);
+        }
+    }
+}

+ 42 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/fortunes.cs

@@ -0,0 +1,42 @@
+using BeetleX;
+using BeetleX.Buffers;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+
+namespace PlatformBenchmarks
+{
+    public partial class HttpHandler
+    {
+
+        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>";
+
+        public async void fortunes(PipeStream stream, HttpToken token, ISession session)
+        {
+            try
+            {
+                var data = await mPgsql.LoadFortunesRows();
+                stream.Write(_fortunesTableStart.Data, 0, _fortunesTableStart.Length);
+                foreach (var item in data)
+                {
+                    stream.Write(_fortunesRowStart.Data, 0, _fortunesRowStart.Length);
+                    stream.Write(item.Id.ToString(CultureInfo.InvariantCulture));
+                    stream.Write(_fortunesColumn.Data, 0, _fortunesColumn.Length);
+                    stream.Write(System.Web.HttpUtility.HtmlEncode(item.Message));
+                    stream.Write(_fortunesRowEnd.Data, 0, _fortunesRowEnd.Length);
+                }
+                stream.Write(_fortunesTableEnd.Data, 0, _fortunesTableEnd.Length);
+            }
+            catch (Exception e_)
+            {
+                stream.Write(e_.Message);
+            }
+            OnCompleted(stream, session, token);
+        }
+    }
+}

+ 20 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/json.cs

@@ -0,0 +1,20 @@
+using BeetleX;
+using BeetleX.Buffers;
+using SpanJson;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PlatformBenchmarks
+{
+    public partial class HttpHandler
+    {
+        public void Json(ReadOnlySpan<byte> url, PipeStream stream, HttpToken token, ISession session)
+        {
+            JsonMessage jsonMessage = default(JsonMessage);
+            jsonMessage.message = "Hello, World!";
+            JsonSerializer.NonGeneric.Utf8.SerializeAsync(jsonMessage, stream);
+            OnCompleted(stream, session, token);
+        }
+    }
+}

+ 17 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/plaintext.cs

@@ -0,0 +1,17 @@
+using BeetleX;
+using BeetleX.Buffers;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PlatformBenchmarks
+{
+    public partial class HttpHandler
+    {
+        public void Plaintext(ReadOnlySpan<byte> url, PipeStream stream, HttpToken token, ISession session)
+        {
+            stream.Write(_result_plaintext.Data, 0, _result_plaintext.Length);
+            OnCompleted(stream, session, token);
+        }
+    }
+}

+ 42 - 0
frameworks/CSharp/beetlex/PlatformBenchmarks/queries.cs

@@ -0,0 +1,42 @@
+using BeetleX;
+using BeetleX.Buffers;
+using SpanJson;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PlatformBenchmarks
+{
+    public partial class  HttpHandler
+    {
+        public async void queries(string queryString, PipeStream stream, HttpToken token, ISession session)
+        {
+            int count = 1;
+            if(!string.IsNullOrEmpty(queryString))
+            {
+                var values = queryString.Split('=');
+                if(values.Length>1)
+                {
+                    if(int.TryParse(values[1],out int size))
+                    {
+                        count = size;
+                    }
+                }
+            }
+            if (count > 500)
+                count = 500;
+            if (count < 1)
+                count = 1;
+            try
+            {
+                var data = await mPgsql.LoadMultipleQueriesRows(count);
+                await JsonSerializer.NonGeneric.Utf8.SerializeAsync(data, stream);
+            }
+            catch (Exception e_)
+            {
+                stream.Write(e_.Message);
+            }
+            OnCompleted(stream, session, token);
+        }
+    }
+}

+ 10 - 0
frameworks/CSharp/beetlex/beetlex-core.dockerfile

@@ -0,0 +1,10 @@
+FROM microsoft/dotnet:2.2-sdk AS build
+WORKDIR /app
+COPY PlatformBenchmarks .
+RUN dotnet publish -c Release -o out
+
+FROM microsoft/dotnet:2.2-aspnetcore-runtime AS runtime
+ENV COMPlus_ReadyToRun 0
+WORKDIR /app
+COPY --from=build /app/out ./
+ENTRYPOINT ["dotnet", "PlatformBenchmarks.dll"]

+ 23 - 1
frameworks/CSharp/beetlex/benchmark_config.json

@@ -20,7 +20,29 @@
         "webserver": "beetlex",
         "webserver": "beetlex",
         "os": "Linux",
         "os": "Linux",
         "database_os": "Linux",
         "database_os": "Linux",
-        "display_name": "beetlex",
+        "display_name": "beetlex webapi",
+        "notes": "",
+        "versus": "beetlex"
+      },
+      "core": {
+        "fortune_url": "/fortunes",
+        "plaintext_url": "/plaintext",
+        "json_url": "/json",
+        "db_url": "/db",
+        "query_url": "/queries?queries=",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Micro",
+        "database": "Postgres",
+        "framework": "beetlex",
+        "language": "C#",
+        "orm": "Raw",
+        "platform": ".NET",
+        "flavor": "CoreCLR",
+        "webserver": "beetlex",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "beetlex core",
         "notes": "",
         "notes": "",
         "versus": "beetlex"
         "versus": "beetlex"
       }
       }