Browse Source

Add Language VB (#3905)

Ben Adams 7 years ago
parent
commit
71e6cdd198
32 changed files with 1076 additions and 0 deletions
  1. 1 0
      .travis.yml
  2. 27 0
      frameworks/VB/README.md
  3. 37 0
      frameworks/VB/aspnetcore/.gitignore
  4. 19 0
      frameworks/VB/aspnetcore/Benchmarks/Benchmarks.vbproj
  5. 9 0
      frameworks/VB/aspnetcore/Benchmarks/Configuration/AppSettings.vb
  6. 9 0
      frameworks/VB/aspnetcore/Benchmarks/Configuration/DatabaseServer.vb
  7. 57 0
      frameworks/VB/aspnetcore/Benchmarks/Data/BatchUpdateString.vb
  8. 33 0
      frameworks/VB/aspnetcore/Benchmarks/Data/ConcurrentRandom.vb
  9. 19 0
      frameworks/VB/aspnetcore/Benchmarks/Data/Fortune.vb
  10. 151 0
      frameworks/VB/aspnetcore/Benchmarks/Data/RawDb.vb
  11. 12 0
      frameworks/VB/aspnetcore/Benchmarks/Data/World.vb
  12. 39 0
      frameworks/VB/aspnetcore/Benchmarks/Middleware/FortunesRawMiddleware.vb
  13. 48 0
      frameworks/VB/aspnetcore/Benchmarks/Middleware/JsonMiddleware.vb
  14. 44 0
      frameworks/VB/aspnetcore/Benchmarks/Middleware/MiddlewareHelpers.vb
  15. 48 0
      frameworks/VB/aspnetcore/Benchmarks/Middleware/MultipleQueriesRawMiddleware.vb
  16. 47 0
      frameworks/VB/aspnetcore/Benchmarks/Middleware/MultipleUpdatesRawMiddleware.vb
  17. 45 0
      frameworks/VB/aspnetcore/Benchmarks/Middleware/PlaintextMiddleware.vb
  18. 49 0
      frameworks/VB/aspnetcore/Benchmarks/Middleware/SingleQueryRawMiddleware.vb
  19. 48 0
      frameworks/VB/aspnetcore/Benchmarks/Middleware/Utf8JsonMiddleware.vb
  20. 7 0
      frameworks/VB/aspnetcore/Benchmarks/NuGet.Config
  21. 37 0
      frameworks/VB/aspnetcore/Benchmarks/Program.vb
  22. 59 0
      frameworks/VB/aspnetcore/Benchmarks/Startup.vb
  23. 52 0
      frameworks/VB/aspnetcore/Benchmarks/Utilities/StringBuilderCache.vb
  24. 3 0
      frameworks/VB/aspnetcore/Benchmarks/appsettings.json
  25. 4 0
      frameworks/VB/aspnetcore/Benchmarks/appsettings.mysql.json
  26. 4 0
      frameworks/VB/aspnetcore/Benchmarks/appsettings.postgresql.json
  27. 34 0
      frameworks/VB/aspnetcore/README.md
  28. 13 0
      frameworks/VB/aspnetcore/aspcore-vb-mw-ado-my.dockerfile
  29. 13 0
      frameworks/VB/aspnetcore/aspcore-vb-mw-ado-pg.dockerfile
  30. 12 0
      frameworks/VB/aspnetcore/aspcore-vb-mw-utf8json.dockerfile
  31. 12 0
      frameworks/VB/aspnetcore/aspcore-vb-mw.dockerfile
  32. 84 0
      frameworks/VB/aspnetcore/benchmark_config.json

+ 1 - 0
.travis.yml

@@ -90,6 +90,7 @@ env:
      - "TESTLANG=Swift"
      - "TESTLANG=Swift"
      - "TESTLANG=Ur"
      - "TESTLANG=Ur"
      - "TESTLANG=Vala"
      - "TESTLANG=Vala"
+     - "TESTLANG=VB"
 
 
 
 
 before_script:
 before_script:

+ 27 - 0
frameworks/VB/README.md

@@ -0,0 +1,27 @@
+# Visual Basic .NET (VB) Frameworks
+
+The information below contains information specific to VB. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/).
+
+## Infrastructure Software Versions
+
+* [VB compiler latest version](https://github.com/dotnet/roslyn)
+
+## Get Help
+
+### VB Experts
+
+_There aren't any VB experts listed, yet. If you're an expert, add yourself!_
+
+### VB Community
+
+_We don't have any community links added. Add some to help further guide 
+future contirbutors._
+
+### Resources
+
+[Visual Basic Guide and Docs](https://docs.microsoft.com/en-us/dotnet/visual-basic/)
+
+[Visual Basic .NET Language Design](https://github.com/dotnet/vblang)
+

+ 37 - 0
frameworks/VB/aspnetcore/.gitignore

@@ -0,0 +1,37 @@
+[Oo]bj/
+[Bb]in/
+TestResults/
+.nuget/
+*.sln.ide/
+_ReSharper.*/
+.idea/
+packages/
+artifacts/
+PublishProfiles/
+.vs/
+*.user
+*.suo
+*.cache
+*.docstates
+_ReSharper.*
+nuget.exe
+*net45.csproj
+*net451.csproj
+*k10.csproj
+*.psess
+*.vsp
+*.pidb
+*.userprefs
+*DS_Store
+*.ncrunchsolution
+*.*sdf
+*.ipch
+*.swp
+*~
+.build/
+.testPublish/
+launchSettings.json
+BenchmarkDotNet.Artifacts/
+BDN.Generated/
+binaries/
+global.json

+ 19 - 0
frameworks/VB/aspnetcore/Benchmarks/Benchmarks.vbproj

@@ -0,0 +1,19 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
+  </PropertyGroup>
+  
+  <ItemGroup>
+      <None Include="appsettings.json" CopyToOutputDirectory="PreserveNewest" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Utf8Json" Version="1.3.7" />
+    <PackageReference Include="Npgsql" Version="4.0.1" />
+    <PackageReference Include="MySqlConnector" Version="0.42.2" />
+    <PackageReference Include="Microsoft.AspNetCore.App" />
+  </ItemGroup>
+
+</Project>

+ 9 - 0
frameworks/VB/aspnetcore/Benchmarks/Configuration/AppSettings.vb

@@ -0,0 +1,9 @@
+' 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. 
+
+Public Class AppSettings
+
+    Property ConnectionString As String
+    Property Database As DatabaseServer = DatabaseServer.None
+
+End Class

+ 9 - 0
frameworks/VB/aspnetcore/Benchmarks/Configuration/DatabaseServer.vb

@@ -0,0 +1,9 @@
+' 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. 
+
+Public Enum DatabaseServer
+    None
+    SqlServer
+    PostgreSql
+    MySql
+End Enum

+ 57 - 0
frameworks/VB/aspnetcore/Benchmarks/Data/BatchUpdateString.vb

@@ -0,0 +1,57 @@
+' 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. 
+
+Imports System.Runtime.CompilerServices
+
+Friend Class BatchUpdateString
+
+    Private Const MaxBatch As Integer = 500
+    Private Shared ReadOnly Queries As String() = New String(499) {}
+
+    Public Shared ReadOnly Property Strings As IList(Of BatchUpdateString) = Enumerable.Range(0, MaxBatch).[Select](Function(i) New BatchUpdateString With {
+        .Id = $"Id_{i}",
+        .Random = $"Random_{i}",
+        .BatchSize = i
+    }).ToArray()
+
+    Private Property BatchSize As Integer
+    Public Property Id As String
+    Public Property Random As String
+
+    Public ReadOnly Property UpdateQuery As String
+        Get
+            Return If(Queries(BatchSize), CreateQuery(BatchSize))
+        End Get
+    End Property
+
+    <MethodImpl(MethodImplOptions.NoInlining)>
+    Private Function CreateQuery(ByVal batchSize As Integer) As String
+
+        Dim sb = StringBuilderCache.Acquire()
+
+        For Each q In Enumerable.Range(0, batchSize + 1).[Select](Function(i) $"UPDATE world SET randomnumber = @Random_{i} WHERE id = @Id_{i};")
+            sb.Append(q)
+        Next
+
+        Dim query = sb.ToString()
+        Queries(batchSize) = query
+        Return query
+
+    End Function
+
+    Public Shared Sub Initalize()
+
+        Observe(Strings(0).UpdateQuery)
+        Observe(Strings(4).UpdateQuery)
+        Observe(Strings(9).UpdateQuery)
+        Observe(Strings(14).UpdateQuery)
+        Observe(Strings(19).UpdateQuery)
+
+    End Sub
+
+    <MethodImpl(MethodImplOptions.NoInlining)>
+    Private Shared Sub Observe(ByVal query As String)
+    End Sub
+
+End Class
+

+ 33 - 0
frameworks/VB/aspnetcore/Benchmarks/Data/ConcurrentRandom.vb

@@ -0,0 +1,33 @@
+' 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. 
+
+Imports System.Runtime.CompilerServices
+Imports System.Threading
+
+Public Class ConcurrentRandom
+
+    Private Shared nextSeed As Integer = 0
+    <ThreadStatic>
+    Private Shared ThreadRandom As Random
+
+    Private Shared ReadOnly Property Instance As Random
+        Get
+            Return If(ThreadRandom, CreateRandom())
+        End Get
+    End Property
+
+    <MethodImpl(MethodImplOptions.NoInlining)>
+    Private Shared Function CreateRandom() As Random
+
+        ThreadRandom = New Random(Interlocked.Increment(nextSeed))
+        Return ThreadRandom
+
+    End Function
+
+    Public Function [Next](ByVal minValue As Integer, ByVal maxValue As Integer) As Integer
+
+        Return Instance.Next(minValue, maxValue)
+
+    End Function
+
+End Class

+ 19 - 0
frameworks/VB/aspnetcore/Benchmarks/Data/Fortune.vb

@@ -0,0 +1,19 @@
+' 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. 
+
+Public Class Fortune
+    Implements IComparable(Of Fortune)
+    Implements IComparable
+
+    Public Property Id As Integer
+    Public Property Message As String
+
+    Public Function CompareTo(ByVal obj As Object) As Integer Implements IComparable.CompareTo
+        Return CompareTo(CType(obj, Fortune))
+    End Function
+
+    Public Function CompareTo(ByVal other As Fortune) As Integer Implements IComparable(Of Fortune).CompareTo
+        Return String.CompareOrdinal(Message, other.Message)
+    End Function
+
+End Class

+ 151 - 0
frameworks/VB/aspnetcore/Benchmarks/Data/RawDb.vb

@@ -0,0 +1,151 @@
+' 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. 
+
+Imports System.Data
+Imports System.Data.Common
+
+Public Class RawDb
+
+    Private Shared ReadOnly WorldSortComparison As Comparison(Of World) = Function(a, b) a.Id.CompareTo(b.Id)
+    Private ReadOnly Random As ConcurrentRandom
+    Private ReadOnly DbProviderFactory As DbProviderFactory
+    Private ReadOnly ConnectionString As String
+
+    Public Sub New(ByVal random As ConcurrentRandom, ByVal dbProviderFactory As DbProviderFactory, ByVal appSettings As AppSettings)
+
+        Me.Random = random
+        Me.DbProviderFactory = dbProviderFactory
+        ConnectionString = appSettings.ConnectionString
+
+    End Sub
+
+    Public Async Function LoadSingleQueryRow() As Task(Of World)
+
+        Using db = DbProviderFactory.CreateConnection()
+            db.ConnectionString = ConnectionString
+            Await db.OpenAsync()
+
+            Using cmd = CreateReadCommand(db)
+                Return Await ReadSingleRow(db, cmd)
+            End Using
+        End Using
+
+    End Function
+
+    Private Async Function ReadSingleRow(ByVal connection As DbConnection, ByVal cmd As DbCommand) As Task(Of World)
+
+        Using rdr = Await cmd.ExecuteReaderAsync(CommandBehavior.SingleRow)
+            Await rdr.ReadAsync()
+            Return New World With {
+                .Id = rdr.GetInt32(0),
+                .RandomNumber = rdr.GetInt32(1)
+            }
+        End Using
+
+    End Function
+
+    Private Function CreateReadCommand(ByVal connection As DbConnection) As DbCommand
+
+        Dim cmd = connection.CreateCommand()
+        cmd.CommandText = "SELECT id, randomnumber FROM world WHERE id = @Id"
+        Dim id = cmd.CreateParameter()
+        id.ParameterName = "@Id"
+        id.DbType = DbType.Int32
+        id.Value = Random.[Next](1, 10001)
+        cmd.Parameters.Add(id)
+        Return cmd
+
+    End Function
+
+    Public Async Function LoadMultipleQueriesRows(ByVal count As Integer) As Task(Of World())
+
+        Using db = DbProviderFactory.CreateConnection()
+            db.ConnectionString = ConnectionString
+            Await db.OpenAsync()
+            Return Await LoadMultipleRows(count, db)
+        End Using
+
+    End Function
+
+    Private Async Function LoadMultipleRows(ByVal count As Integer, ByVal db As DbConnection) As Task(Of World())
+
+        Using cmd = CreateReadCommand(db)
+            cmd.Parameters("@Id").Value = Random.[Next](1, 10001)
+            Dim result = New World(count - 1) {}
+
+            For i As Integer = 0 To result.Length - 1
+                result(i) = Await ReadSingleRow(db, cmd)
+                cmd.Parameters("@Id").Value = Random.[Next](1, 10001)
+            Next
+
+            Return result
+        End Using
+
+    End Function
+
+    Public Async Function LoadMultipleUpdatesRows(ByVal count As Integer) As Task(Of World())
+
+        Using db = DbProviderFactory.CreateConnection()
+            db.ConnectionString = ConnectionString
+            Await db.OpenAsync()
+            Dim results = Await LoadMultipleRows(count, db)
+            Array.Sort(results, WorldSortComparison)
+
+            Using updateCmd = db.CreateCommand()
+
+                For i As Integer = 0 To results.Length - 1
+                    Dim strings = BatchUpdateString.Strings(i)
+                    Dim id = updateCmd.CreateParameter()
+                    id.ParameterName = strings.Id
+                    id.DbType = DbType.Int32
+                    updateCmd.Parameters.Add(id)
+                    Dim random = updateCmd.CreateParameter()
+                    random.ParameterName = strings.Random
+                    random.DbType = DbType.Int32
+                    updateCmd.Parameters.Add(random)
+                    Dim randomNumber = Me.Random.[Next](1, 10001)
+                    id.Value = results(i).Id
+                    random.Value = randomNumber
+                    results(i).RandomNumber = randomNumber
+                Next
+
+                updateCmd.CommandText = BatchUpdateString.Strings(results.Length - 1).UpdateQuery
+                Await updateCmd.ExecuteNonQueryAsync()
+                Return results
+            End Using
+        End Using
+
+    End Function
+
+    Public Async Function LoadFortunesRows() As Task(Of List(Of Fortune))
+
+        Dim result = New List(Of Fortune)()
+
+        Using db = DbProviderFactory.CreateConnection()
+
+            Using cmd = db.CreateCommand()
+                cmd.CommandText = "SELECT id, message FROM fortune"
+                db.ConnectionString = ConnectionString
+                Await db.OpenAsync()
+
+                Using rdr = Await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection)
+
+                    While Await rdr.ReadAsync()
+                        result.Add(New Fortune With {
+                            .Id = rdr.GetInt32(0),
+                            .Message = rdr.GetString(1)
+                        })
+                    End While
+                End Using
+            End Using
+        End Using
+
+        result.Add(New Fortune With {
+            .Message = "Additional fortune added at request time."
+        })
+        result.Sort()
+        Return result
+
+    End Function
+
+End Class

+ 12 - 0
frameworks/VB/aspnetcore/Benchmarks/Data/World.vb

@@ -0,0 +1,12 @@
+' 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. 
+
+Imports System.Runtime.InteropServices
+
+<StructLayout(LayoutKind.Sequential, Size:=8)>
+Public Structure World
+
+    Public Property Id As Integer
+    Public Property RandomNumber As Integer
+
+End Structure

+ 39 - 0
frameworks/VB/aspnetcore/Benchmarks/Middleware/FortunesRawMiddleware.vb

@@ -0,0 +1,39 @@
+' 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. 
+
+Imports System.Runtime.CompilerServices
+Imports System.Text.Encodings.Web
+Imports Microsoft.AspNetCore.Builder
+Imports Microsoft.AspNetCore.Http
+Imports Microsoft.Extensions.DependencyInjection
+
+Public Class FortunesRawMiddleware
+
+    Private ReadOnly NextStage As RequestDelegate
+    Private ReadOnly Encoder As HtmlEncoder
+
+    Public Sub New(ByVal NextStage As RequestDelegate, ByVal htmlEncoder As HtmlEncoder)
+        Me.NextStage = NextStage
+        Encoder = htmlEncoder
+    End Sub
+
+    Public Async Function Invoke(ByVal httpContext As HttpContext) As Task
+
+        If httpContext.Request.Path.StartsWithSegments("/fortunes", StringComparison.Ordinal) Then
+            Dim db = httpContext.RequestServices.GetService(Of RawDb)()
+            Dim rows = Await db.LoadFortunesRows()
+            Await MiddlewareHelpers.RenderFortunesHtml(rows, httpContext, Encoder)
+            Return
+        End If
+
+        Await NextStage(httpContext)
+
+    End Function
+End Class
+
+Module FortunesRawMiddlewareExtensions
+    <Extension()>
+    Function UseFortunesRaw(ByVal builder As IApplicationBuilder) As IApplicationBuilder
+        Return builder.UseMiddleware(Of FortunesRawMiddleware)()
+    End Function
+End Module

+ 48 - 0
frameworks/VB/aspnetcore/Benchmarks/Middleware/JsonMiddleware.vb

@@ -0,0 +1,48 @@
+' 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. 
+
+Imports System.IO
+Imports System.Runtime.CompilerServices
+Imports System.Text
+Imports Microsoft.AspNetCore.Builder
+Imports Microsoft.AspNetCore.Http
+Imports Newtonsoft.Json
+
+Public Class JsonMiddleware
+
+    Private Shared ReadOnly Json As JsonSerializer = New JsonSerializer()
+    Private Shared ReadOnly Encoding As UTF8Encoding = New UTF8Encoding(False)
+    Private Const BufferSize As Integer = 27
+    Private ReadOnly NextStage As RequestDelegate
+
+    Public Sub New(ByVal NextStage As RequestDelegate)
+        Me.NextStage = NextStage
+    End Sub
+
+    Public Function Invoke(ByVal httpContext As HttpContext) As Task
+
+        If httpContext.Request.Path.StartsWithSegments("/json", StringComparison.Ordinal) Then
+            httpContext.Response.StatusCode = 200
+            httpContext.Response.ContentType = "application/json"
+            httpContext.Response.ContentLength = BufferSize
+
+            Using sw = New StreamWriter(httpContext.Response.Body, Encoding, bufferSize:=BufferSize)
+                Json.Serialize(sw, New With {
+                    .message = "Hello, World!"
+                })
+            End Using
+
+            Return Task.CompletedTask
+        End If
+
+        Return NextStage(httpContext)
+
+    End Function
+End Class
+
+Module JsonMiddlewareExtensions
+    <Extension()>
+    Function UseJson(ByVal builder As IApplicationBuilder) As IApplicationBuilder
+        Return builder.UseMiddleware(Of JsonMiddleware)()
+    End Function
+End Module

+ 44 - 0
frameworks/VB/aspnetcore/Benchmarks/Middleware/MiddlewareHelpers.vb

@@ -0,0 +1,44 @@
+' 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. 
+
+Imports System.Globalization
+Imports System.Text
+Imports System.Text.Encodings.Web
+Imports Microsoft.AspNetCore.Http
+
+Class MiddlewareHelpers
+    Shared Function GetMultipleQueriesQueryCount(ByVal httpContext As HttpContext) As Integer
+
+        Dim queries = 1
+        Dim queriesRaw = httpContext.Request.Query("queries")
+
+        If queriesRaw.Count = 1 Then
+            Integer.TryParse(queriesRaw, queries)
+        End If
+
+        Return If(queries > 500, 500, If(queries > 0, queries, 1))
+
+    End Function
+
+    Shared Async Function RenderFortunesHtml(ByVal model As IEnumerable(Of Fortune), ByVal httpContext As HttpContext, ByVal htmlEncoder As HtmlEncoder) As Task
+
+        httpContext.Response.StatusCode = StatusCodes.Status200OK
+        httpContext.Response.ContentType = "text/html; charset=UTF-8"
+        Dim sb = StringBuilderCache.Acquire()
+        sb.Append("<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>")
+
+        For Each item In model
+            sb.Append("<tr><td>")
+            sb.Append(item.Id.ToString(CultureInfo.InvariantCulture))
+            sb.Append("</td><td>")
+            sb.Append(htmlEncoder.Encode(item.Message))
+            sb.Append("</td></tr>")
+        Next
+
+        sb.Append("</table></body></html>")
+        Dim response = StringBuilderCache.GetStringAndRelease(sb)
+        httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(response)
+        Await httpContext.Response.WriteAsync(response)
+
+    End Function
+End Class

+ 48 - 0
frameworks/VB/aspnetcore/Benchmarks/Middleware/MultipleQueriesRawMiddleware.vb

@@ -0,0 +1,48 @@
+' 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. 
+
+Imports System.Runtime.CompilerServices
+Imports Microsoft.AspNetCore.Builder
+Imports Microsoft.AspNetCore.Http
+Imports Microsoft.Extensions.DependencyInjection
+Imports Newtonsoft.Json
+Imports Newtonsoft.Json.Serialization
+
+Public Class MultipleQueriesRawMiddleware
+
+    Private Shared ReadOnly JsonSettings As JsonSerializerSettings = New JsonSerializerSettings With {
+        .ContractResolver = New CamelCasePropertyNamesContractResolver()
+    }
+
+    Private ReadOnly NextStage As RequestDelegate
+
+    Public Sub New(ByVal NextStage As RequestDelegate)
+        Me.NextStage = NextStage
+    End Sub
+
+    Public Async Function Invoke(ByVal httpContext As HttpContext) As Task
+
+        If httpContext.Request.Path.StartsWithSegments("/queries", StringComparison.Ordinal) Then
+            Dim count = MiddlewareHelpers.GetMultipleQueriesQueryCount(httpContext)
+            Dim db = httpContext.RequestServices.GetService(Of RawDb)()
+            Dim rows = Await db.LoadMultipleQueriesRows(count)
+            Dim result = JsonConvert.SerializeObject(rows, JsonSettings)
+            httpContext.Response.StatusCode = StatusCodes.Status200OK
+            httpContext.Response.ContentType = "application/json"
+            httpContext.Response.ContentLength = result.Length
+            Await httpContext.Response.WriteAsync(result)
+            Return
+        End If
+
+        Await NextStage(httpContext)
+
+    End Function
+End Class
+
+Module MultipleQueriesRawMiddlewareExtensions
+    <Extension()>
+    Function UseMultipleQueriesRaw(ByVal builder As IApplicationBuilder) As IApplicationBuilder
+        Return builder.UseMiddleware(Of MultipleQueriesRawMiddleware)()
+    End Function
+End Module
+

+ 47 - 0
frameworks/VB/aspnetcore/Benchmarks/Middleware/MultipleUpdatesRawMiddleware.vb

@@ -0,0 +1,47 @@
+' 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. 
+
+Imports System.Runtime.CompilerServices
+Imports Microsoft.AspNetCore.Builder
+Imports Microsoft.AspNetCore.Http
+Imports Microsoft.Extensions.DependencyInjection
+Imports Newtonsoft.Json
+Imports Newtonsoft.Json.Serialization
+
+Public Class MultipleUpdatesRawMiddleware
+    Private Shared ReadOnly JsonSettings As JsonSerializerSettings = New JsonSerializerSettings With {
+        .ContractResolver = New CamelCasePropertyNamesContractResolver()
+    }
+
+    Private ReadOnly NextStage As RequestDelegate
+
+    Public Sub New(ByVal NextStage As RequestDelegate)
+        Me.NextStage = NextStage
+    End Sub
+
+    Public Async Function Invoke(ByVal httpContext As HttpContext) As Task
+
+        If httpContext.Request.Path.StartsWithSegments("/updates", StringComparison.Ordinal) Then
+            Dim count = MiddlewareHelpers.GetMultipleQueriesQueryCount(httpContext)
+            Dim db = httpContext.RequestServices.GetService(Of RawDb)()
+            Dim rows = Await db.LoadMultipleUpdatesRows(count)
+            Dim result = JsonConvert.SerializeObject(rows, JsonSettings)
+            httpContext.Response.StatusCode = StatusCodes.Status200OK
+            httpContext.Response.ContentType = "application/json"
+            httpContext.Response.ContentLength = result.Length
+            Await httpContext.Response.WriteAsync(result)
+            Return
+        End If
+
+        Await NextStage(httpContext)
+
+    End Function
+
+End Class
+
+Module MultipleUpdatesRawMiddlewareExtensions
+    <Extension()>
+    Function UseMultipleUpdatesRaw(ByVal builder As IApplicationBuilder) As IApplicationBuilder
+        Return builder.UseMiddleware(Of MultipleUpdatesRawMiddleware)()
+    End Function
+End Module

+ 45 - 0
frameworks/VB/aspnetcore/Benchmarks/Middleware/PlaintextMiddleware.vb

@@ -0,0 +1,45 @@
+' 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. 
+
+Imports System.Runtime.CompilerServices
+Imports System.Text
+Imports Microsoft.AspNetCore.Builder
+Imports Microsoft.AspNetCore.Http
+
+Public Class PlaintextMiddleware
+
+    Private Shared ReadOnly HelloWorldPayload As Byte() = Encoding.UTF8.GetBytes("Hello, World!")
+    Private ReadOnly NextStage As RequestDelegate
+
+    Public Sub New(ByVal NextStage As RequestDelegate)
+        Me.NextStage = NextStage
+    End Sub
+
+    Public Function Invoke(ByVal httpContext As HttpContext) As Task
+
+        If httpContext.Request.Path.StartsWithSegments("/plaintext", StringComparison.Ordinal) Then
+            Return WriteResponse(httpContext.Response)
+        End If
+
+        Return NextStage(httpContext)
+
+    End Function
+
+    Public Shared Function WriteResponse(ByVal response As HttpResponse) As Task
+
+        Dim payloadLength = HelloWorldPayload.Length
+        response.StatusCode = 200
+        response.ContentType = "text/plain"
+        response.ContentLength = payloadLength
+        Return response.Body.WriteAsync(HelloWorldPayload, 0, payloadLength)
+
+    End Function
+
+End Class
+
+Module PlaintextMiddlewareExtensions
+    <Extension()>
+    Function UsePlainText(ByVal builder As IApplicationBuilder) As IApplicationBuilder
+        Return builder.UseMiddleware(Of PlaintextMiddleware)()
+    End Function
+End Module

+ 49 - 0
frameworks/VB/aspnetcore/Benchmarks/Middleware/SingleQueryRawMiddleware.vb

@@ -0,0 +1,49 @@
+' 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. 
+
+
+Imports System.Runtime.CompilerServices
+Imports Microsoft.AspNetCore.Builder
+Imports Microsoft.AspNetCore.Http
+Imports Microsoft.Extensions.DependencyInjection
+Imports Newtonsoft.Json
+Imports Newtonsoft.Json.Serialization
+
+Public Class SingleQueryRawMiddleware
+
+    Private Shared ReadOnly JsonSettings As JsonSerializerSettings = New JsonSerializerSettings With {
+        .ContractResolver = New CamelCasePropertyNamesContractResolver()
+    }
+
+    Private ReadOnly NextStage As RequestDelegate
+
+    Public Sub New(ByVal NextStage As RequestDelegate)
+        Me.NextStage = NextStage
+    End Sub
+
+    Public Async Function Invoke(ByVal httpContext As HttpContext) As Task
+
+        If httpContext.Request.Path.StartsWithSegments("/db", StringComparison.Ordinal) Then
+            Dim db = httpContext.RequestServices.GetService(Of RawDb)()
+            Dim row = Await db.LoadSingleQueryRow()
+            Dim result = JsonConvert.SerializeObject(row, JsonSettings)
+            httpContext.Response.StatusCode = StatusCodes.Status200OK
+            httpContext.Response.ContentType = "application/json"
+            httpContext.Response.ContentLength = result.Length
+            Await httpContext.Response.WriteAsync(result)
+            Return
+        End If
+
+        Await NextStage(httpContext)
+
+    End Function
+
+End Class
+
+Module SingleQueryRawMiddlewareExtensions
+    <Extension()>
+    Function UseSingleQueryRaw(ByVal builder As IApplicationBuilder) As IApplicationBuilder
+        Return builder.UseMiddleware(Of SingleQueryRawMiddleware)()
+    End Function
+End Module
+

+ 48 - 0
frameworks/VB/aspnetcore/Benchmarks/Middleware/Utf8JsonMiddleware.vb

@@ -0,0 +1,48 @@
+' 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. 
+
+Imports System.Runtime.CompilerServices
+Imports Microsoft.AspNetCore.Builder
+Imports Microsoft.AspNetCore.Http
+Imports Utf8Json
+
+Public Structure JsonMessage
+#Disable Warning IDE1006 ' Naming Styles
+    Public Property message
+#Enable Warning IDE1006 ' Naming Styles
+End Structure
+
+Public Class Utf8JsonMiddleware
+
+    Private Const BufferSize As Integer = 27
+    Private ReadOnly NextStage As RequestDelegate
+
+    Public Sub New(ByVal NextStage As RequestDelegate)
+        Me.NextStage = NextStage
+    End Sub
+
+    Public Function Invoke(ByVal httpContext As HttpContext) As Task
+
+        If httpContext.Request.Path.StartsWithSegments("/utf8json", StringComparison.Ordinal) Then
+            httpContext.Response.StatusCode = 200
+            httpContext.Response.ContentType = "application/json"
+            httpContext.Response.ContentLength = BufferSize
+            Dim msg = New JsonMessage With {
+                .message = "Hello, World!"
+            }
+            JsonSerializer.Serialize(httpContext.Response.Body, msg)
+            Return Task.CompletedTask
+        End If
+
+        Return NextStage(httpContext)
+
+    End Function
+End Class
+
+Module Utf8JsonMiddlewareExtensions
+    <Extension()>
+    Function UseUtf8Json(ByVal builder As IApplicationBuilder) As IApplicationBuilder
+        Return builder.UseMiddleware(Of Utf8JsonMiddleware)()
+    End Function
+End Module
+

+ 7 - 0
frameworks/VB/aspnetcore/Benchmarks/NuGet.Config

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <packageSources>
+    <clear />
+    <add key="NuGet" value="https://api.nuget.org/v3/index.json" />
+  </packageSources>
+</configuration>

+ 37 - 0
frameworks/VB/aspnetcore/Benchmarks/Program.vb

@@ -0,0 +1,37 @@
+' 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. 
+
+Imports Microsoft.AspNetCore.Hosting
+Imports Microsoft.Extensions.Configuration
+
+Class Program
+
+    Shared Sub Main(args As String())
+
+        BatchUpdateString.Initalize()
+
+        BuildWebHost(args).Run()
+
+    End Sub
+
+    Shared Function BuildWebHost(args As String()) As IWebHost
+
+        Dim config = New ConfigurationBuilder() _
+            .AddJsonFile("appsettings.json") _
+            .AddEnvironmentVariables(prefix:="ASPNETCORE_") _
+            .AddCommandLine(args) _
+            .Build()
+
+        Dim appSettings = config.Get(Of AppSettings)()
+        Console.WriteLine($"Database: {appSettings.Database}")
+
+        Dim host = New WebHostBuilder() _
+            .UseConfiguration(config) _
+            .UseStartup(Of Startup)() _
+            .UseKestrel() _
+            .Build()
+
+        Return host
+
+    End Function
+End Class

+ 59 - 0
frameworks/VB/aspnetcore/Benchmarks/Startup.vb

@@ -0,0 +1,59 @@
+' 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. 
+
+Imports System.Data.Common
+Imports System.Text.Encodings.Web
+Imports System.Text.Unicode
+Imports Microsoft.AspNetCore.Builder
+Imports Microsoft.AspNetCore.Hosting
+Imports Microsoft.Extensions.Configuration
+Imports Microsoft.Extensions.DependencyInjection
+
+Imports MySql.Data.MySqlClient
+Imports Npgsql
+
+Public Class Startup
+
+    Private Configuration As IConfiguration
+
+    Public Sub New(configuration As IConfiguration)
+        Me.Configuration = configuration
+    End Sub
+
+    Public Sub ConfigureServices(ByVal services As IServiceCollection)
+
+        services.Configure(Of AppSettings)(Configuration)
+        services.AddSingleton(Of ConcurrentRandom)()
+
+        Dim appSettings = Configuration.[Get](Of AppSettings)()
+        services.AddSingleton(appSettings)
+
+        If appSettings.Database = DatabaseServer.PostgreSql Then
+            services.AddSingleton(Of DbProviderFactory)(NpgsqlFactory.Instance)
+            services.AddSingleton(Of RawDb)
+        ElseIf appSettings.Database = DatabaseServer.MySql Then
+            services.AddSingleton(Of DbProviderFactory)(MySqlClientFactory.Instance)
+            services.AddSingleton(Of RawDb)
+        End If
+
+        Dim settings = New TextEncoderSettings(UnicodeRanges.BasicLatin, UnicodeRanges.Katakana, UnicodeRanges.Hiragana)
+        settings.AllowCharacter("—"c)
+        services.AddWebEncoders(
+            Sub(options)
+                options.TextEncoderSettings = settings
+            End Sub)
+
+    End Sub
+
+    Public Sub Configure(ByVal app As IApplicationBuilder)
+
+        app.UsePlainText()
+        app.UseJson()
+        app.UseUtf8Json()
+        app.UseFortunesRaw()
+        app.UseSingleQueryRaw()
+        app.UseMultipleQueriesRaw()
+        app.UseMultipleUpdatesRaw()
+
+    End Sub
+End Class

+ 52 - 0
frameworks/VB/aspnetcore/Benchmarks/Utilities/StringBuilderCache.vb

@@ -0,0 +1,52 @@
+' 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. 
+
+Imports System.Text
+
+Friend Class StringBuilderCache
+
+    Private Const DefaultCapacity As Integer = 1386
+    Private Const MaxBuilderSize As Integer = DefaultCapacity * 3
+    <ThreadStatic>
+    Private Shared t_cachedInstance As StringBuilder
+
+    Shared Function Acquire(ByVal Optional capacity As Integer = DefaultCapacity) As StringBuilder
+
+        If capacity <= MaxBuilderSize Then
+            Dim sb As StringBuilder = t_cachedInstance
+
+            If capacity < DefaultCapacity Then
+                capacity = DefaultCapacity
+            End If
+
+            If sb IsNot Nothing Then
+
+                If capacity <= sb.Capacity Then
+                    t_cachedInstance = Nothing
+                    sb.Clear()
+                    Return sb
+                End If
+            End If
+        End If
+
+        Return New StringBuilder(capacity)
+
+    End Function
+
+    Shared Sub Release(ByVal sb As StringBuilder)
+
+        If sb.Capacity <= MaxBuilderSize Then
+            t_cachedInstance = sb
+        End If
+
+    End Sub
+
+    Shared Function GetStringAndRelease(ByVal sb As StringBuilder) As String
+
+        Dim result As String = sb.ToString()
+        Release(sb)
+        Return result
+
+    End Function
+End Class
+

+ 3 - 0
frameworks/VB/aspnetcore/Benchmarks/appsettings.json

@@ -0,0 +1,3 @@
+{
+  "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnetcore-Benchmarks;Trusted_Connection=True;MultipleActiveResultSets=true"
+}

+ 4 - 0
frameworks/VB/aspnetcore/Benchmarks/appsettings.mysql.json

@@ -0,0 +1,4 @@
+{
+  "ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=1024;SslMode=None;ConnectionReset=false;ConnectionIdlePingTime=900;ConnectionIdleTimeout=0",
+  "Database": "mysql"
+}

+ 4 - 0
frameworks/VB/aspnetcore/Benchmarks/appsettings.postgresql.json

@@ -0,0 +1,4 @@
+{
+  "ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=1024;NoResetOnClose=true;Enlist=false;Max Auto Prepare=3",
+  "Database": "postgresql"
+}

+ 34 - 0
frameworks/VB/aspnetcore/README.md

@@ -0,0 +1,34 @@
+# ASP.NET Core Tests on Windows and Linux
+
+See [.NET Core](http://dot.net) and [ASP.NET Core](https://github.com/aspnet) for more information.
+
+This includes tests for plaintext and json serialization.
+
+## Infrastructure Software Versions
+
+**Language**
+
+* VB.NET 15
+
+**Platforms**
+
+* .NET Core (Windows and Linux)
+
+**Web Servers**
+
+* [Kestrel](https://github.com/aspnet/KestrelHttpServer)
+* [HttpSys](https://github.com/aspnet/HttpSysServer)
+
+**Web Stack**
+
+* ASP.NET Core
+
+## Paths & Source for Tests
+
+* [Plaintext](Benchmarks/Middleware/PlaintextMiddleware.cs): "/plaintext"
+* [JSON Serialization](Benchmarks/Middleware/JsonMiddleware.cs): "/json"
+* [JSON Serialization Utf8Json](Benchmarks/Middleware/Utf8JsonMiddleware.cs): "/utf8json"
+* [Single Query Raw](Benchmarks/Middleware/SingleQueryRawMiddleware.cs): "/db"
+* [Multiple Queries Raw](Benchmarks/Middleware/MultipleQueriesRawMiddleware.cs): "/queries"
+* [Data Updates Raw](Benchmarks/Middleware/MultipleUpdatesRawMiddleware.cs): "/updates"
+* [Fortunes Raw](Benchmarks/Middleware/FortunesRawMiddleware.cs): "/fortunes"

+ 13 - 0
frameworks/VB/aspnetcore/aspcore-vb-mw-ado-my.dockerfile

@@ -0,0 +1,13 @@
+FROM microsoft/dotnet:2.1-sdk-stretch AS build
+WORKDIR /app
+COPY Benchmarks .
+RUN dotnet publish -c Release -o out
+COPY Benchmarks/appsettings.mysql.json ./out/appsettings.json
+
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS runtime
+ENV ASPNETCORE_URLS http://+:8080
+ENV COMPlus_ReadyToRun 0
+WORKDIR /app
+COPY --from=build /app/out ./
+
+ENTRYPOINT ["dotnet", "Benchmarks.dll"]

+ 13 - 0
frameworks/VB/aspnetcore/aspcore-vb-mw-ado-pg.dockerfile

@@ -0,0 +1,13 @@
+FROM microsoft/dotnet:2.1-sdk-stretch AS build
+WORKDIR /app
+COPY Benchmarks .
+RUN dotnet publish -c Release -o out
+COPY Benchmarks/appsettings.postgresql.json ./out/appsettings.json
+
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS runtime
+ENV ASPNETCORE_URLS http://+:8080
+ENV COMPlus_ReadyToRun 0
+WORKDIR /app
+COPY --from=build /app/out ./
+
+ENTRYPOINT ["dotnet", "Benchmarks.dll"]

+ 12 - 0
frameworks/VB/aspnetcore/aspcore-vb-mw-utf8json.dockerfile

@@ -0,0 +1,12 @@
+FROM microsoft/dotnet:2.1-sdk-stretch AS build
+WORKDIR /app
+COPY Benchmarks .
+RUN dotnet publish -c Release -o out
+
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS runtime
+ENV ASPNETCORE_URLS http://+:8080
+ENV COMPlus_ReadyToRun 0
+WORKDIR /app
+COPY --from=build /app/out ./
+
+ENTRYPOINT ["dotnet", "Benchmarks.dll"]

+ 12 - 0
frameworks/VB/aspnetcore/aspcore-vb-mw.dockerfile

@@ -0,0 +1,12 @@
+FROM microsoft/dotnet:2.1-sdk-stretch AS build
+WORKDIR /app
+COPY Benchmarks .
+RUN dotnet publish -c Release -o out
+
+FROM microsoft/dotnet:2.1-aspnetcore-runtime AS runtime
+ENV ASPNETCORE_URLS http://+:8080
+ENV COMPlus_ReadyToRun 0
+WORKDIR /app
+COPY --from=build /app/out ./
+
+ENTRYPOINT ["dotnet", "Benchmarks.dll"]

+ 84 - 0
frameworks/VB/aspnetcore/benchmark_config.json

@@ -0,0 +1,84 @@
+{
+  "framework": "aspcore-vb-mw",
+  "tests": [{
+    "default": {
+      "plaintext_url": "/plaintext",
+      "json_url": "/json",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "None",
+      "framework": "ASP.NET Core",
+      "language": "VB",
+      "orm": "Raw",
+      "platform": ".NET",
+      "flavor": "CoreCLR",
+      "webserver": "Kestrel",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "ASP.NET Core, Middleware",
+      "notes": "",
+      "versus": "aspcore"
+    },
+    "utf8json": {
+      "json_url": "/utf8json",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "None",
+      "framework": "ASP.NET Core",
+      "language": "VB",
+      "orm": "Raw",
+      "platform": ".NET",
+      "flavor": "CoreCLR",
+      "webserver": "Kestrel",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "ASP.NET Core, Middleware, Utf8Json",
+      "notes": "",
+      "versus": "aspcore"
+    },
+    "ado-pg": {
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "update_url": "/updates?queries=",
+      "fortune_url": "/fortunes",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "Postgres",
+      "framework": "ASP.NET Core",
+      "language": "VB",
+      "orm": "Raw",
+      "platform": ".NET",
+      "flavor": "CoreCLR",
+      "webserver": "Kestrel",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "ASP.NET Core, Middleware, ADO.NET",
+      "notes": "",
+      "versus": "aspcore-ado-pg"
+    },
+    "ado-my": {
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "update_url": "/updates?queries=",
+      "fortune_url": "/fortunes",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "ASP.NET Core",
+      "language": "VB",
+      "orm": "Raw",
+      "platform": ".NET",
+      "flavor": "CoreCLR",
+      "webserver": "Kestrel",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "ASP.NET Core, Middleware, ADO.NET",
+      "notes": "",
+      "versus": "aspcore-ado-my"
+    }
+  }]
+}