123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- 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<World> worlds = new List<World>(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<Fortune> fortunes = new List<Fortune>();
- 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<World> worlds = new List<World>(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<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)));
- }
- 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<Fortune> 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<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);
- }
- response.ContentType = "application/json";
- return new JavaScriptSerializer().Serialize(
- worlds.Count > 1 ? (Object)worlds : (Object)worlds[0]);
- }
- }
- }
|