Browse Source

beetlex framework add fortunes cases (#4871)

* 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
Henry 6 years ago
parent
commit
eb0334b9a2

+ 49 - 0
frameworks/CSharp/beetlex/Benchmarks/AsciiString.cs

@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Benchmarks
+{
+
+    public readonly struct AsciiString : IEquatable<AsciiString>
+    {
+        private readonly byte[] _data;
+
+        public AsciiString(string s) => _data = Encoding.ASCII.GetBytes(s);
+
+        public int Length => _data.Length;
+
+        public byte[] Data => _data;
+
+        public ReadOnlySpan<byte> AsSpan() => _data;
+
+        public static implicit operator ReadOnlySpan<byte>(AsciiString str) => str._data;
+        public static implicit operator byte[] (AsciiString str) => str._data;
+
+        public static implicit operator AsciiString(string str) => new AsciiString(str);
+
+        public static explicit operator string(AsciiString str) => str.ToString();
+
+        public bool Equals(AsciiString other) => ReferenceEquals(_data, other._data) || SequenceEqual(_data, other._data);
+        private bool SequenceEqual(byte[] data1, byte[] data2) => new Span<byte>(data1).SequenceEqual(data2);
+
+        public static bool operator ==(AsciiString a, AsciiString b) => a.Equals(b);
+        public static bool operator !=(AsciiString a, AsciiString b) => !a.Equals(b);
+        public override bool Equals(object other) => (other is AsciiString) && Equals((AsciiString)other);
+
+        public override int GetHashCode()
+        {
+            // Copied from x64 version of string.GetLegacyNonRandomizedHashCode()
+            // https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/String.Comparison.cs
+            var data = _data;
+            int hash1 = 5381;
+            int hash2 = hash1;
+            foreach (int b in data)
+            {
+                hash1 = ((hash1 << 5) + hash1) ^ b;
+            }
+            return hash1 + (hash2 * 1566083941);
+        }
+
+    }
+}

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

@@ -4,6 +4,7 @@
     <OutputType>Exe</OutputType>
     <TargetFramework>netcoreapp2.2</TargetFramework>
     <ServerGarbageCollection>true</ServerGarbageCollection>
+    <LangVersion>7.2</LangVersion>
   </PropertyGroup>
 
   <ItemGroup>

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

@@ -90,5 +90,34 @@ namespace Benchmarks
                 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/Benchmarks/Fortune.cs

@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Benchmarks
+{
+    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);
+        }
+    }
+}

+ 46 - 0
frameworks/CSharp/beetlex/Benchmarks/FortuneView.cs

@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using BeetleX.Buffers;
+using BeetleX.FastHttpApi;
+
+namespace Benchmarks
+{
+    public class FortuneView:BeetleX.FastHttpApi.ResultBase
+    {
+        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 HeaderItem HTML_UTF8 = new HeaderItem("Content-Type: text/html; charset=UTF-8\r\n");
+
+        public FortuneView(IEnumerable<Fortune> model)
+        {
+            Model = model;
+        }
+
+        public override bool HasBody => true;
+
+        public IEnumerable<Fortune> Model { get; set; }
+
+        public override IHeaderItem ContentType => HTML_UTF8;
+
+        public override void Write(PipeStream stream, HttpResponse response)
+        {
+            stream.Write(_fortunesTableStart.Data, 0, _fortunesTableStart.Length);
+            foreach (var item in Model)
+            {
+                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);
+        }
+    }
+
+}

+ 7 - 1
frameworks/CSharp/beetlex/Benchmarks/Program.cs

@@ -47,6 +47,13 @@ namespace Benchmarks
             return new SpanJsonResult(result);
         }
 
+        public async Task<object> fortunes()
+        {
+            var data = await mPgsql.LoadFortunesRows();
+            return new FortuneView(data);
+        }
+
+
         private RawDb mPgsql;
 
         [NotAction]
@@ -77,7 +84,6 @@ namespace Benchmarks
             mApiServer.Options.LogLevel = BeetleX.EventArgs.LogType.Error;
             mApiServer.Options.LogToConsole = true;
             mApiServer.Options.PrivateBufferPool = true;
-            mApiServer.Options.IOQueueEnabled = true;
             mApiServer.Register(typeof(Program).Assembly);
             mApiServer.Open();
             return Task.CompletedTask;

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

@@ -3,6 +3,7 @@
   "tests": [
     {
       "default": {
+        "fortune_url": "/fortunes",
         "plaintext_url": "/plaintext",
         "json_url": "/json",
         "db_url": "/db",