Browse Source

Get aspnet-stripped working with MySQL, PostgreSQL, MongoDB

Since @pdonald did all the work to get ASP.NET working against these other
databases, we should get this working in aspnet-stripped, so that we can
see how much stripping improved performance with these databases. This
ports @pdonald's related changes from aspnet to aspnet-stripped.

Because some of the URLs have the '&' character in them, I had to fix
framework_test.py to do proper quoting so that the '&' character would not
be interpreted by the shell.
Malcolm Evershed 12 years ago
parent
commit
7641d8004c

BIN
aspnet-stripped/NuGet.exe


+ 36 - 6
aspnet-stripped/benchmark_config

@@ -5,19 +5,49 @@
       "setup_file": "setup_iis",
       "os": "nt",
       "json_url": "/json",
+      "plaintext_url": "/plaintext",
       "port": 8080,
       "sort": 134
     },
-    "sqlserver-raw": {
+    "mysql-raw": {
       "setup_file": "setup_iis",
       "os": "nt",
-      "db_url": "/db",
-      "query_url": "/db?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/updates?queries=",
-      "plaintext_url": "/plaintext",
+      "db_url": "/db?provider=mysql",
+      "query_url": "/db?provider=mysql&queries=",
+      "fortune_url": "/fortunes?provider=mysql",
+      "update_url": "/updates?provider=mysql&queries=",
       "port": 8080,
       "sort": 135
+    },
+    "postgresql-raw": {
+      "setup_file": "setup_iis",
+      "os": "nt",
+      "db_url": "/db?provider=postgresql",
+      "query_url": "/db?provider=postgresql&queries=",
+      "fortune_url": "/fortunes?provider=postgresql",
+      "update_url": "/updates?provider=postgresql&queries=",
+      "port": 8080,
+      "sort": 136
+    },
+    "mongodb-raw": {
+      "setup_file": "setup_iis",
+      "os": "nt",
+      "db_url": "/mongodbdb",
+      "query_url": "/mongodbdb?queries=",
+      "fortune_url": "/mongodbfortunes",
+      "update_url": "/mongodbupdates?queries=",
+      "port": 8080,
+      "sort": 137
+    },
+    "sqlserver-raw": {
+      "setup_file": "setup_iis",
+      "os": "nt",
+      "db_url": "/db?provider=sqlserver",
+      "query_url": "/db?provider=sqlserver&queries=",
+      "fortune_url": "/fortunes?provider=sqlserver",
+      "update_url": "/updates?provider=sqlserver&queries=",
+      "port": 8080,
+      "sort": 138
     }
   }]
 }

+ 11 - 0
aspnet-stripped/setup_iis.ps1

@@ -6,6 +6,17 @@ $source = "C:\FrameworkBenchmarks\aspnet-stripped\src"
 if (Get-WebSite -Name Benchmarks) { Remove-WebSite -Name Benchmarks }
 
 if ($action -eq 'start') {
+    # Because we don't use msbuild to compile the code, we do this all manually.
+    
+    & .\NuGet.exe install -o src\packages src\packages.config
+
+    if (-Not (Test-Path src\bin)) { New-Item -Path src\bin -ItemType directory | Out-Null }
+
+    $dlls = Get-ChildItem -path src\packages -recurse -include *.dll
+    foreach ($dll in $dlls) {
+        Copy-Item $dll src\bin
+    }
+
     # Create a website in IIS
     New-WebSite -Name Benchmarks -Port 8080 -PhysicalPath $source
 }

+ 4 - 2
aspnet-stripped/src/App_Code/Common.cs

@@ -8,8 +8,10 @@ public class Common
 {
     public static DbConnection CreateConnection(HttpRequest request)
     {
-        // Never tried this with any other provider
-        string providerName = "sqlserver";
+        string providerName = request.QueryString["provider"];
+        if (providerName == null) {
+            throw new ApplicationException("Missing provider querystring argument");
+        }
         ConnectionStringSettings connectionSettings = ConfigurationManager.ConnectionStrings[providerName];
         DbProviderFactory factory = DbProviderFactories.GetFactory(connectionSettings.ProviderName);
         DbConnection connection = factory.CreateConnection();

+ 53 - 0
aspnet-stripped/src/App_Code/Models/MongoDB.cs

@@ -0,0 +1,53 @@
+using System.Configuration;
+using System.Web.Script.Serialization;
+
+using MongoDB.Bson;
+using MongoDB.Bson.Serialization;
+using MongoDB.Driver;
+
+namespace Benchmarks.AspNet.Models
+{
+    public class MongoDB
+    {
+        public MongoCollection<MongoWorld> Worlds { get; private set; }
+        public MongoCollection<Fortune> Fortunes { get; private set; }
+
+        static MongoDB()
+        {
+            BsonClassMap.RegisterClassMap<World>(m =>
+            {
+                m.MapProperty(w => w.id);
+                m.MapProperty(w => w.randomNumber);
+            });
+
+            BsonClassMap.RegisterClassMap<MongoWorld>(m =>
+            {
+                m.MapIdProperty(w => w._id);
+            });
+
+            BsonClassMap.RegisterClassMap<Fortune>(m =>
+            {
+                m.MapProperty(f => f.ID).SetElementName("id");
+                m.MapProperty(f => f.Message).SetElementName("message");
+            });
+        }
+
+        public MongoDB(string connectionStringName)
+        {
+            string connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
+
+            MongoClient client = new MongoClient(connectionString);
+            MongoServer server = client.GetServer();
+            MongoDatabase database = server.GetDatabase("hello_world");
+
+            Worlds = database.GetCollection<MongoWorld>("world");
+            Fortunes = database.GetCollection<Fortune>("fortune");
+        }
+    }
+
+    public class MongoWorld : World
+    {
+        [ScriptIgnore]
+        public ObjectId _id { get; set; }
+    }
+}

+ 94 - 0
aspnet-stripped/src/App_Code/MongoDBHandlers.cs

@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Linq;
+using System.Web;
+using System.Web.Script.Serialization;
+
+using MongoDB.Driver.Builders;
+
+using Benchmarks.AspNet.Models;
+
+public class MongoDBDbHandler : IHttpHandler
+{
+    bool IHttpHandler.IsReusable
+    {
+        get { return true; }
+    }
+
+    void IHttpHandler.ProcessRequest(HttpContext context)
+    {
+        Random random = new Random();
+        
+        int queries = Common.GetQueries(context.Request);
+        List<World> worlds = new List<World>(queries);
+
+        Benchmarks.AspNet.Models.MongoDB db = new Benchmarks.AspNet.Models.MongoDB("MongoDB");
+
+        for (int i = 0; i < worlds.Capacity; i++)
+        {
+            int randomID = random.Next(0, 10000) + 1;
+            worlds.Add(db.Worlds.FindOne(Query<World>.EQ(w => w.id, randomID)));
+        }
+
+        HttpResponse response = context.Response;
+        response.ContentType = "application/json";
+        response.Write(new JavaScriptSerializer().Serialize(
+            worlds.Count > 1 ? (Object)worlds : (Object)worlds[0]));
+    }
+}
+
+public partial class MongoDBFortunesPage : System.Web.UI.Page
+{
+    protected void Page_Load(object sender, EventArgs e)
+    {
+        Benchmarks.AspNet.Models.MongoDB db = new Benchmarks.AspNet.Models.MongoDB("MongoDB");
+
+        List<Fortune> fortunes = db.Fortunes.FindAll().ToList();
+
+        fortunes.Add(new Fortune { ID = 0, Message = "Additional fortune added at request time." });
+        fortunes.Sort();
+
+        Fortunes = fortunes;
+    }
+
+    public List<Fortune> Fortunes
+    {
+        get; set;
+    }
+}
+
+public class MongoDBUpdatesHandler : IHttpHandler
+{
+    bool IHttpHandler.IsReusable
+    {
+        get { return true; }
+    }
+
+    void IHttpHandler.ProcessRequest(HttpContext context)
+    {
+        Random random = new Random();
+        
+        Benchmarks.AspNet.Models.MongoDB db = new Benchmarks.AspNet.Models.MongoDB("MongoDB");
+
+        int queries = Common.GetQueries(context.Request);
+        List<World> worlds = new List<World>(queries);
+
+        for (int i = 0; i < worlds.Capacity; i++)
+        {
+            int randomID = random.Next(0, 10000) + 1;
+            int randomNumber = random.Next(0, 10000) + 1;
+
+            World world = db.Worlds.FindOne(Query<World>.EQ(w => w.id, randomID));
+            world.randomNumber = randomNumber;
+            worlds.Add(world);
+
+            db.Worlds.Save(world);
+        }
+
+        HttpResponse response = context.Response;
+        response.ContentType = "application/json";
+        response.Write(new JavaScriptSerializer().Serialize(
+            worlds.Count > 1 ? (Object)worlds : (Object)worlds[0]));
+    }
+}

+ 9 - 0
aspnet-stripped/src/Web.config

@@ -1,5 +1,8 @@
 <configuration>
   <connectionStrings>
+    <add name="MySQL" connectionString="server=localhost; user id=benchmarkdbuser; password=benchmarkdbpass; database=hello_world" providerName="MySql.Data.MySqlClient"/>
+    <add name="PostgreSQL" connectionString="server=localhost; user id=benchmarkdbuser; password=benchmarkdbpass; database=hello_world" providerName="Npgsql"/>
+    <add name="MongoDB" connectionString="mongodb://localhost"/>
     <!-- Set max pool size to SQL Server's default max_connections value. In practice, we don't seem to be getting close to the max at all. -->
     <add name="SQLServer" connectionString="server=localhost; user id=benchmarkdbuser; password=B3nchmarkDBPass; database=hello_world; max pool size=32767" providerName="System.Data.SqlClient"/>
   </connectionStrings>
@@ -7,6 +10,8 @@
   <system.data>
     <DbProviderFactories>
       <clear/>
+      <add name="MySql.Data.MySqlClient" description="Data Provider for MySQL" invariant="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.7.2.0"/>
+      <add name="Npgsql" description="Data Provider for PostgreSQL" invariant="Npgsql" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.12.0"/>
       <add name="SqlClient Data Provider" description=".Net Framework Data Provider for SqlServer" invariant="System.Data.SqlClient" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
     </DbProviderFactories>
   </system.data>
@@ -55,6 +60,10 @@
             <add name="Fortunes_aspx" path="fortunes" verb="*" type="NoAspxHandlerFactory" resourceType="Unspecified" preCondition="integratedMode" />
             <add name="UpdatesHandler" path="updates" verb="*" type="UpdatesHandler" resourceType="Unspecified" preCondition="integratedMode" />
             <add name="PlaintextHandler" path="plaintext" verb="*" type="PlaintextHandler" resourceType="Unspecified" preCondition="integratedMode" />
+
+            <add name="MongoDBDbHandler" path="mongodbdb" verb="*" type="MongoDBDbHandler" resourceType="Unspecified" preCondition="integratedMode" />
+            <add name="MongoDBFortunes_aspx" path="mongodbfortunes" verb="*" type="NoAspxHandlerFactory" resourceType="Unspecified" preCondition="integratedMode" />
+            <add name="MongoDBUpdatesHandler" path="mongodbupdates" verb="*" type="MongoDBUpdatesHandler" resourceType="Unspecified" preCondition="integratedMode" />
         </handlers>
     </system.webServer>
 </configuration>

+ 1 - 0
aspnet-stripped/src/mongodbfortunes.aspx

@@ -0,0 +1 @@
+<%@ Page Language="C#" AutoEventWireup="true" Inherits="MongoDBFortunesPage" %><!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><% foreach (var fortune in Fortunes) { %><tr><td><% = fortune.ID %></td><td><%: fortune.Message %></td></tr><% } %></table></body></html>

+ 6 - 0
aspnet-stripped/src/packages.config

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="mongocsharpdriver" version="1.8.1" targetFramework="net45" />
+  <package id="MySql.Data.Entity" version="6.7.2-beta-ef6" targetFramework="net45" />
+  <package id="Npgsql.EF6" version="2.0.12-pre4" targetFramework="net45" />
+</packages>

+ 12 - 12
framework_test.py

@@ -16,29 +16,29 @@ class FrameworkTest:
     echo ""
     echo "---------------------------------------------------------"
     echo " Running Primer {name}"
-    echo " {wrk} {headers} -d 60 -c 8 -t 8 http://{server_host}:{port}{url}"
+    echo " {wrk} {headers} -d 60 -c 8 -t 8 \"http://{server_host}:{port}{url}\""
     echo "---------------------------------------------------------"
     echo ""
-    {wrk} {headers} -d 5 -c 8 -t 8 http://{server_host}:{port}{url}
+    {wrk} {headers} -d 5 -c 8 -t 8 "http://{server_host}:{port}{url}"
     sleep 5
     
     echo ""
     echo "---------------------------------------------------------"
     echo " Running Warmup {name}"
-    echo " {wrk} {headers} -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}"
+    echo " {wrk} {headers} -d {duration} -c {max_concurrency} -t {max_threads} \"http://{server_host}:{port}{url}\""
     echo "---------------------------------------------------------"
     echo ""
-    {wrk} {headers} -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}
+    {wrk} {headers} -d {duration} -c {max_concurrency} -t {max_threads} "http://{server_host}:{port}{url}"
     sleep 5
     for c in {interval}
     do
       echo ""
       echo "---------------------------------------------------------"
       echo " Concurrency: $c for {name}"
-      echo " {wrk} {headers} -d {duration} -c $c -t $(($c>{max_threads}?{max_threads}:$c)) http://{server_host}:{port}{url}"
+      echo " {wrk} {headers} -d {duration} -c $c -t $(($c>{max_threads}?{max_threads}:$c)) \"http://{server_host}:{port}{url}\""
       echo "---------------------------------------------------------"
       echo ""
-      {wrk} {headers} -d {duration} -c "$c" -t "$(($c>{max_threads}?{max_threads}:$c))" http://{server_host}:{port}{url}
+      {wrk} {headers} -d {duration} -c "$c" -t "$(($c>{max_threads}?{max_threads}:$c))" "http://{server_host}:{port}{url}"
       sleep 2
     done
   """
@@ -48,29 +48,29 @@ class FrameworkTest:
     echo ""
     echo "---------------------------------------------------------"
     echo " Running Primer {name}"
-    echo " wrk {headers} -d 5 -c 8 -t 8 http://{server_host}:{port}{url}2"
+    echo " wrk {headers} -d 5 -c 8 -t 8 \"http://{server_host}:{port}{url}2\""
     echo "---------------------------------------------------------"
     echo ""
-    wrk {headers} -d 5 -c 8 -t 8 http://{server_host}:{port}{url}2
+    wrk {headers} -d 5 -c 8 -t 8 "http://{server_host}:{port}{url}2"
     sleep 5
     
     echo ""
     echo "---------------------------------------------------------"
     echo " Running Warmup {name}"
-    echo " wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}2"
+    echo " wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} \"http://{server_host}:{port}{url}2\""
     echo "---------------------------------------------------------"
     echo ""
-    wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}2
+    wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} "http://{server_host}:{port}{url}2"
     sleep 5
     for c in {interval}
     do
       echo ""
       echo "---------------------------------------------------------"
       echo " Queries: $c for {name}"
-      echo " wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}$c"
+      echo " wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} \"http://{server_host}:{port}{url}$c\""
       echo "---------------------------------------------------------"
       echo ""
-      wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}"$c"
+      wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} "http://{server_host}:{port}{url}$c"
       sleep 2
     done
   """