diff --git a/HttpListener/.gitignore b/HttpListener/.gitignore new file mode 100644 index 00000000000..9bebd649577 --- /dev/null +++ b/HttpListener/.gitignore @@ -0,0 +1,8 @@ +*.pyc +*.user +*.suo +*/bin/ +*/obj/ +.nuget/NuGet.exe +packages/ +!packages/repositories.config diff --git a/HttpListener/.nuget/NuGet.Config b/HttpListener/.nuget/NuGet.Config new file mode 100644 index 00000000000..67f8ea046ef --- /dev/null +++ b/HttpListener/.nuget/NuGet.Config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/HttpListener/.nuget/NuGet.targets b/HttpListener/.nuget/NuGet.targets new file mode 100644 index 00000000000..46a1b6ced78 --- /dev/null +++ b/HttpListener/.nuget/NuGet.targets @@ -0,0 +1,133 @@ + + + + $(MSBuildProjectDirectory)\..\ + + + false + + + false + + + true + + + false + + + + + + + + + + + $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) + $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) + + + + + $(SolutionDir).nuget + packages.config + + + + + $(NuGetToolsPath)\NuGet.exe + @(PackageSource) + + "$(NuGetExePath)" + mono --runtime=v4.0.30319 $(NuGetExePath) + + $(TargetDir.Trim('\\')) + + -RequireConsent + -NonInteractive + + + $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir "$(SolutionDir) " + $(NuGetCommand) pack "$(ProjectPath)" -Properties Configuration=$(Configuration) $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols + + + + RestorePackages; + $(BuildDependsOn); + + + + + $(BuildDependsOn); + BuildPackage; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HttpListener/HttpListener.sln b/HttpListener/HttpListener.sln new file mode 100644 index 00000000000..b5ba2342502 --- /dev/null +++ b/HttpListener/HttpListener.sln @@ -0,0 +1,27 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpListener", "HttpListener\HttpListener.csproj", "{C788981C-7F54-4408-B477-C94E486A1AF5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{967712FE-DCC3-412D-A3E4-55F92B833B16}" + ProjectSection(SolutionItems) = preProject + .nuget\NuGet.Config = .nuget\NuGet.Config + .nuget\NuGet.exe = .nuget\NuGet.exe + .nuget\NuGet.targets = .nuget\NuGet.targets + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C788981C-7F54-4408-B477-C94E486A1AF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C788981C-7F54-4408-B477-C94E486A1AF5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C788981C-7F54-4408-B477-C94E486A1AF5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C788981C-7F54-4408-B477-C94E486A1AF5}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/HttpListener/HttpListener/App.config b/HttpListener/HttpListener/App.config new file mode 100644 index 00000000000..8b136ae752b --- /dev/null +++ b/HttpListener/HttpListener/App.config @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HttpListener/HttpListener/Fortunes.cshtml b/HttpListener/HttpListener/Fortunes.cshtml new file mode 100644 index 00000000000..eb2b67fd195 --- /dev/null +++ b/HttpListener/HttpListener/Fortunes.cshtml @@ -0,0 +1,11 @@ +@* Generator: Template *@@* +*@@using System.Web;@* +*@@functions { + public IEnumerable Model { get; set; } +}@* +*@Fortunes@* +*@@foreach (var fortune in Model) +{ +@* +*@} +
idmessage
@fortune.ID@HttpUtility.HtmlEncode(fortune.Message)
\ No newline at end of file diff --git a/HttpListener/HttpListener/Fortunes.generated.cs b/HttpListener/HttpListener/Fortunes.generated.cs new file mode 100644 index 00000000000..49cff0c44aa --- /dev/null +++ b/HttpListener/HttpListener/Fortunes.generated.cs @@ -0,0 +1,106 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18047 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace HttpListener +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + #line 2 "..\..\Fortunes.cshtml" + using System.Web; + + #line default + #line hidden + + [System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")] + public partial class Fortunes : RazorGenerator.Templating.RazorTemplateBase + { +#line hidden + + #line 3 "..\..\Fortunes.cshtml" + + public IEnumerable Model { get; set; } + + #line default + #line hidden + + public override void Execute() + { + + + + + + + + + + +WriteLiteral("Fortunes"); + + + + + + #line 7 "..\..\Fortunes.cshtml" + foreach (var fortune in Model) +{ + + + #line default + #line hidden +WriteLiteral(""); + + + + #line 9 "..\..\Fortunes.cshtml" + + + #line default + #line hidden + + + #line 10 "..\..\Fortunes.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
id<" + +"/th>message
"); + + + + #line 9 "..\..\Fortunes.cshtml" + Write(fortune.ID); + + + #line default + #line hidden +WriteLiteral(""); + + + + #line 9 "..\..\Fortunes.cshtml" + Write(HttpUtility.HtmlEncode(fortune.Message)); + + + #line default + #line hidden +WriteLiteral("
"); + + + } + } +} +#pragma warning restore 1591 diff --git a/HttpListener/HttpListener/HttpListener.csproj b/HttpListener/HttpListener/HttpListener.csproj new file mode 100644 index 00000000000..cbd76c57801 --- /dev/null +++ b/HttpListener/HttpListener/HttpListener.csproj @@ -0,0 +1,140 @@ + + + + + Debug + AnyCPU + {C788981C-7F54-4408-B477-C94E486A1AF5} + Exe + Properties + HttpListener + HttpListener + v4.5 + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + ..\ + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\EntityFramework.6.0.0-beta1\lib\net45\EntityFramework.dll + + + ..\packages\EntityFramework.6.0.0-beta1\lib\net45\EntityFramework.SqlServer.dll + + + ..\packages\mongocsharpdriver.1.8.1\lib\net35\MongoDB.Bson.dll + + + ..\packages\mongocsharpdriver.1.8.1\lib\net35\MongoDB.Driver.dll + + + ..\packages\Npgsql.EF6.2.0.12-pre4\lib\net45\Mono.Security.dll + + + ..\packages\Npgsql.EF6.2.0.12-pre4\lib\net45\Mono.Security.Protocol.Tls.dll + + + ..\packages\MySql.Data.Entity.6.7.2-beta-ef6\lib\net45\MySql.Data.dll + + + ..\packages\MySql.Data.Entity.6.7.2-beta-ef6\lib\net45\MySql.Data.Entity.dll + + + ..\packages\Npgsql.EF6.2.0.12-pre4\lib\net45\Npgsql.dll + + + ..\packages\RazorGenerator.Templating.2.1.1\lib\net40\RazorGenerator.Templating.dll + + + + + + + + + + + + + + + + True + True + Fortunes.cshtml + + + + + + + + + + + RazorGenerator + Fortunes.generated.cs + + + + + + False + Microsoft .NET Framework 4.5 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + \ No newline at end of file diff --git a/HttpListener/HttpListener/Models/Fortune.cs b/HttpListener/HttpListener/Models/Fortune.cs new file mode 100644 index 00000000000..974207fe03f --- /dev/null +++ b/HttpListener/HttpListener/Models/Fortune.cs @@ -0,0 +1,15 @@ +using System; + +namespace Benchmarks.AspNet.Models +{ + public class Fortune : IComparable + { + public int ID { get; set; } + public string Message { get; set; } + + public int CompareTo(Fortune other) + { + return Message.CompareTo(other.Message); + } + } +} \ No newline at end of file diff --git a/HttpListener/HttpListener/Models/MongoDB.cs b/HttpListener/HttpListener/Models/MongoDB.cs new file mode 100644 index 00000000000..1a4b5c6962f --- /dev/null +++ b/HttpListener/HttpListener/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 Worlds { get; private set; } + public MongoCollection Fortunes { get; private set; } + + static MongoDB() + { + BsonClassMap.RegisterClassMap(m => + { + m.MapProperty(w => w.id); + m.MapProperty(w => w.randomNumber); + }); + + BsonClassMap.RegisterClassMap(m => + { + m.MapIdProperty(w => w._id); + }); + + BsonClassMap.RegisterClassMap(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("world"); + Fortunes = database.GetCollection("fortune"); + } + } + + public class MongoWorld : World + { + [ScriptIgnore] + public ObjectId _id { get; set; } + } +} \ No newline at end of file diff --git a/HttpListener/HttpListener/Models/World.cs b/HttpListener/HttpListener/Models/World.cs new file mode 100644 index 00000000000..fc19f7c222b --- /dev/null +++ b/HttpListener/HttpListener/Models/World.cs @@ -0,0 +1,8 @@ +namespace Benchmarks.AspNet.Models +{ + public class World + { + public int id { get; set; } + public int randomNumber { get; set; } + } +} \ No newline at end of file diff --git a/HttpListener/HttpListener/Program.cs b/HttpListener/HttpListener/Program.cs new file mode 100644 index 00000000000..01db177faa1 --- /dev/null +++ b/HttpListener/HttpListener/Program.cs @@ -0,0 +1,403 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Configuration; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Net; +using System.Threading; +using System.Web.Script.Serialization; + +using MongoDB.Driver.Builders; + +using Benchmarks.AspNet.Models; + +namespace HttpListener +{ + class Program + { + private static void RequestCallback(Object state) + { + HttpListenerContext context = (HttpListenerContext)state; + HttpListenerRequest request = context.Request; + HttpListenerResponse response = context.Response; + + try + { + string responseString = null; + switch (request.Url.LocalPath) + { + case "/plaintext": + responseString = Plaintext(response); + break; + case "/json": + responseString = Json(response); + break; + case "/db": + responseString = Db(request, response); + break; + case "/fortunes": + responseString = Fortunes(request, response); + break; + case "/updates": + responseString = Updates(request, response); + break; + case "/mongodbdb": + responseString = MongoDBDb(request, response); + break; + case "/mongodbfortunes": + responseString = MongoDBFortunes(request, response); + break; + case "/mongodbupdates": + responseString = MongoDBUpdates(request, response); + break; + default: + responseString = NotFound(response); + break; + } + WriteResponse(response, responseString); + } + finally + { + response.Close(); + } + } + + private static void WriteResponse(HttpListenerResponse response, String responseString) + { + response.ContentType = response.ContentType + "; charset=utf-8"; + byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString); + response.ContentLength64 = buffer.Length; + try + { + response.OutputStream.Write(buffer, 0, buffer.Length); + } + catch (Win32Exception) + { + // Ignore I/O errors + } + } + + private static void Threads() + { + // To improve CPU utilization, increase the number of threads that the .NET thread pool expands by when + // a burst of requests come in. We could do this by editing machine.config/system.web/processModel/minWorkerThreads, + // but that seems too global a change, so we do it in code for just our AppPool. More info: + // + // http://support.microsoft.com/kb/821268 + // http://blogs.msdn.com/b/tmarq/archive/2007/07/21/asp-net-thread-usage-on-iis-7-0-and-6-0.aspx + // http://blogs.msdn.com/b/perfworld/archive/2010/01/13/how-can-i-improve-the-performance-of-asp-net-by-adjusting-the-clr-thread-throttling-properties.aspx + + int newMinWorkerThreads = Convert.ToInt32(ConfigurationManager.AppSettings["minWorkerThreadsPerLogicalProcessor"]); + if (newMinWorkerThreads > 0) + { + int minWorkerThreads, minCompletionPortThreads; + ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads); + ThreadPool.SetMinThreads(Environment.ProcessorCount * newMinWorkerThreads, minCompletionPortThreads); + } + } + + static void Main(string[] args) + { + Threads(); + + System.Net.HttpListener listener = new System.Net.HttpListener(); + // This doesn't seem to ignore all write exceptions, so in WriteResponse(), we still have a catch block. + listener.IgnoreWriteExceptions = true; + listener.Prefixes.Add("http://*:8080/"); + + try + { + listener.Start(); + + for (;;) + { + HttpListenerContext context = null; + try + { + context = listener.GetContext(); + + ThreadPool.QueueUserWorkItem(new WaitCallback(RequestCallback), context); + context = null; // ownership has been transferred to RequestCallback + } + catch (HttpListenerException ex) + { + Console.WriteLine(ex.Message); + } + finally + { + if (context != null) + context.Response.Close(); + } + } + } + catch (HttpListenerException ex) + { + Console.WriteLine(ex.Message); + } + finally + { + // Stop listening for requests. + listener.Close(); + Console.WriteLine("Done Listening."); + } + } + + public static DbConnection CreateConnection(HttpListenerRequest request) + { + 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(); + connection.ConnectionString = connectionSettings.ConnectionString; + return connection; + } + + public static int GetQueries(HttpListenerRequest request) + { + int queries = 1; + string queriesString = request.QueryString["queries"]; + if (queriesString != null) + { + // If this fails to parse, queries will be set to zero. + int.TryParse(queriesString, out queries); + queries = Math.Max(1, Math.Min(500, queries)); + } + return queries; + } + + private static string NotFound(HttpListenerResponse response) + { + response.StatusCode = (int)HttpStatusCode.NotFound; + response.ContentType = "text/plain"; + return "not found"; + } + + private static string Plaintext(HttpListenerResponse response) + { + response.ContentType = "text/plain"; + return "Hello, World!"; + } + + private static string Json(HttpListenerResponse response) + { + response.ContentType = "application/json"; + return new JavaScriptSerializer().Serialize(new { message = "Hello, World!" }); + } + + private static string Db(HttpListenerRequest request, HttpListenerResponse response) + { + Random random = new Random(); + + int queries = GetQueries(request); + List worlds = new List(queries); + + using (DbConnection connection = CreateConnection(request)) + { + connection.Open(); + + using (DbCommand command = connection.CreateCommand()) + { + command.CommandText = "SELECT * FROM World WHERE id = @ID"; + + DbParameter parameter = command.CreateParameter(); + parameter.ParameterName = "@ID"; + + command.Parameters.Add(parameter); + + for (int i = 0; i < worlds.Capacity; i++) + { + int randomID = random.Next(0, 10000) + 1; + + parameter.Value = randomID; + + // Don't use CommandBehavior.SingleRow because that will make the MySql provider + // send two extra commands to limit the result to one row. + using (DbDataReader reader = command.ExecuteReader()) + { + if (reader.Read()) + { + worlds.Add(new World + { + id = reader.GetInt32(0), + randomNumber = reader.GetInt32(1) + }); + } + } + } + } + } + + response.ContentType = "application/json"; + return new JavaScriptSerializer().Serialize( + worlds.Count > 1 ? (Object)worlds : (Object)worlds[0]); + } + + private static string Fortunes(HttpListenerRequest request, HttpListenerResponse response) + { + List fortunes = new List(); + + using (DbConnection connection = CreateConnection(request)) + { + connection.Open(); + + using (DbCommand command = connection.CreateCommand()) + { + command.CommandText = "SELECT * FROM Fortune"; + + using (DbDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess)) + { + while (reader.Read()) + { + fortunes.Add(new Fortune + { + ID = reader.GetInt32(0), + Message = reader.GetString(1) + }); + } + } + } + } + + fortunes.Add(new Fortune { ID = 0, Message = "Additional fortune added at request time." }); + fortunes.Sort(); + + response.ContentType = "text/html"; + var template = new Fortunes { Model = fortunes }; + return template.TransformText(); + } + + private static string Updates(HttpListenerRequest request, HttpListenerResponse response) + { + Random random = new Random(); + List worlds = new List(GetQueries(request)); + + using (DbConnection connection = CreateConnection(request)) + { + connection.Open(); + + using (DbCommand selectCommand = connection.CreateCommand(), + updateCommand = connection.CreateCommand()) + { + selectCommand.CommandText = "SELECT * FROM World WHERE id = @ID"; + updateCommand.CommandText = "UPDATE World SET randomNumber = @Number WHERE id = @ID"; + + for (int i = 0; i < worlds.Capacity; i++) + { + int randomID = random.Next(0, 10000) + 1; + int randomNumber = random.Next(0, 10000) + 1; + + DbParameter idParameter = selectCommand.CreateParameter(); + idParameter.ParameterName = "@ID"; + idParameter.Value = randomID; + + selectCommand.Parameters.Clear(); + selectCommand.Parameters.Add(idParameter); + + World world = null; + + // Don't use CommandBehavior.SingleRow because that will make the MySql provider + // send two extra commands to limit the result to one row. + using (DbDataReader reader = selectCommand.ExecuteReader()) + { + if (reader.Read()) + { + world = new World + { + id = reader.GetInt32(0), + randomNumber = reader.GetInt32(1) + }; + } + } + + DbParameter idUpdateParameter = updateCommand.CreateParameter(); + idUpdateParameter.ParameterName = "@ID"; + idUpdateParameter.Value = randomID; + + DbParameter numberParameter = updateCommand.CreateParameter(); + numberParameter.ParameterName = "@Number"; + numberParameter.Value = randomNumber; + + updateCommand.Parameters.Clear(); + updateCommand.Parameters.Add(idUpdateParameter); + updateCommand.Parameters.Add(numberParameter); + + updateCommand.ExecuteNonQuery(); + + world.randomNumber = randomNumber; + worlds.Add(world); + } + } + } + + response.ContentType = "application/json"; + return new JavaScriptSerializer().Serialize( + worlds.Count > 1 ? (Object)worlds : (Object)worlds[0]); + } + + private static string MongoDBDb(HttpListenerRequest request, HttpListenerResponse response) + { + Random random = new Random(); + + int queries = GetQueries(request); + List worlds = new List(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.EQ(w => w.id, randomID))); + } + + response.ContentType = "application/json"; + return new JavaScriptSerializer().Serialize( + worlds.Count > 1 ? (Object)worlds : (Object)worlds[0]); + } + + private static string MongoDBFortunes(HttpListenerRequest request, HttpListenerResponse response) + { + Benchmarks.AspNet.Models.MongoDB db = new Benchmarks.AspNet.Models.MongoDB("MongoDB"); + + List fortunes = db.Fortunes.FindAll().ToList(); + + fortunes.Add(new Fortune { ID = 0, Message = "Additional fortune added at request time." }); + fortunes.Sort(); + + response.ContentType = "text/html"; + var template = new Fortunes { Model = fortunes }; + return template.TransformText(); + } + + private static string MongoDBUpdates(HttpListenerRequest request, HttpListenerResponse response) + { + Random random = new Random(); + + Benchmarks.AspNet.Models.MongoDB db = new Benchmarks.AspNet.Models.MongoDB("MongoDB"); + + int queries = GetQueries(request); + List worlds = new List(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.EQ(w => w.id, randomID)); + world.randomNumber = randomNumber; + worlds.Add(world); + + db.Worlds.Save(world); + } + + response.ContentType = "application/json"; + return new JavaScriptSerializer().Serialize( + worlds.Count > 1 ? (Object)worlds : (Object)worlds[0]); + } + } +} diff --git a/HttpListener/HttpListener/Properties/AssemblyInfo.cs b/HttpListener/HttpListener/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..2c4b03989c5 --- /dev/null +++ b/HttpListener/HttpListener/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("HttpListener")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("HttpListener")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ac13325e-f037-4665-89ed-2de2c30e22c7")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/HttpListener/HttpListener/packages.config b/HttpListener/HttpListener/packages.config new file mode 100644 index 00000000000..2e83f9c328f --- /dev/null +++ b/HttpListener/HttpListener/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/HttpListener/README.md b/HttpListener/README.md new file mode 100644 index 00000000000..f5bed3c9283 --- /dev/null +++ b/HttpListener/README.md @@ -0,0 +1,5 @@ +This uses [.NET's HttpListener class](http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx) which is somewhat similar to Go's net/http package or node.js's built-in HTTP server. HttpListener is a .NET Framework wrapper around [HTTP.SYS](http://www.iis.net/learn/get-started/introduction-to-iis/introduction-to-iis-architecture#Hypertext), the kernel-mode HTTP driver that is used by IIS. + +These tests are based on [aspnet](https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/aspnet) by [@pdonald](https://github.com/pdonald/). + +By using .NET's HttpListener class, we eliminate the overhead of IIS and ASP.NET. This does not use ASP.NET WebForms (.aspx), but instead uses Razor (.cshtml), with the the template parsed at design-time into C# by RazorGenerator. \ No newline at end of file diff --git a/HttpListener/__init__.py b/HttpListener/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/HttpListener/benchmark_config b/HttpListener/benchmark_config new file mode 100644 index 00000000000..665f3706107 --- /dev/null +++ b/HttpListener/benchmark_config @@ -0,0 +1,53 @@ +{ + "framework": "HttpListener", + "tests": [{ + "default": { + "setup_file": "setup", + "os": "nt", + "json_url": "/json", + "plaintext_url": "/plaintext", + "port": 8080, + "sort": 150 + }, + "mysql-raw": { + "setup_file": "setup", + "os": "nt", + "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": 151 + }, + "postgresql-raw": { + "setup_file": "setup", + "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": 152 + }, + "mongodb-raw": { + "setup_file": "setup", + "os": "nt", + "db_url": "/mongodbdb", + "query_url": "/mongodbdb?queries=", + "fortune_url": "/mongodbfortunes", + "update_url": "/mongodbupdates?queries=", + "port": 8080, + "sort": 153 + }, + "sqlserver-raw": { + "setup_file": "setup", + "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": 154 + } + }] +} diff --git a/HttpListener/setup.ps1 b/HttpListener/setup.ps1 new file mode 100644 index 00000000000..eabe8d69a44 --- /dev/null +++ b/HttpListener/setup.ps1 @@ -0,0 +1,14 @@ +param($action) + +$root = "C:\FrameworkBenchmarks\HttpListener" +$msbuild = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe" + +# Stop +Stop-Process -Name HttpListener -ErrorAction SilentlyContinue + +if ($action -eq 'start') { + # Build the project + &$msbuild "$root\HttpListener.sln" /p:DownloadNuGetExe=true /p:RequireRestoreConsent=false /p:Configuration=Release /t:Rebuild + + Start-Process "$root\HttpListener\bin\Release\HttpListener.exe" +} \ No newline at end of file diff --git a/HttpListener/setup.py b/HttpListener/setup.py new file mode 100644 index 00000000000..db7837958c9 --- /dev/null +++ b/HttpListener/setup.py @@ -0,0 +1,22 @@ +import subprocess +import sys +import setup_util +import os + +def start(args): + if os.name != 'nt': + return 1 + + try: + setup_util.replace_text("HttpListener/HttpListener/App.config", "localhost", args.database_host) + subprocess.check_call("powershell -File setup.ps1 start", cwd="HttpListener") + return 0 + except subprocess.CalledProcessError: + return 1 + +def stop(): + if os.name != 'nt': + return 0 + + subprocess.Popen("powershell -File setup.ps1 stop", cwd="HttpListener") + return 0 \ No newline at end of file