PageRenderTime 4ms CodeModel.GetById 2ms app.highlight 43ms RepoModel.GetById 1ms app.codeStats 1ms

/Dapper.Tests.Performance/LegacyTests.cs

https://bitbucket.org/Ecarestia/dapper
C# | 403 lines | 320 code | 54 blank | 29 comment | 12 complexity | ee28f3a22ab45c6d8a54bd55db18ac72 MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.Data;
  4using System.Data.Linq;
  5using System.Data.SqlClient;
  6using System.Diagnostics;
  7using System.Linq;
  8
  9//using BLToolkit.Data; // Note: this doesn't load in the new .csproj system...likely a bug
 10using Dapper.Tests.Performance.EntityFramework;
 11using Dapper.Tests.Performance.Linq2Sql;
 12using Dapper.Tests.Performance.NHibernate;
 13using Dapper.Contrib.Extensions;
 14using Massive;
 15using NHibernate.Criterion;
 16using NHibernate.Linq;
 17using ServiceStack.OrmLite;
 18using ServiceStack.OrmLite.Dapper;
 19using Susanoo;
 20using System.Configuration;
 21using System.Threading.Tasks;
 22using Dapper.Tests.Performance.EntityFrameworkCore;
 23using Microsoft.EntityFrameworkCore;
 24
 25namespace Dapper.Tests.Performance
 26{
 27    public class LegacyTests
 28    {
 29        private class Test
 30        {
 31            public Test(Action<int> iteration, string name)
 32            {
 33                Iteration = iteration;
 34                Name = name;
 35            }
 36
 37            public Test(Func<int, Task> iterationAsync, string name)
 38            {
 39                IterationAsync = iterationAsync;
 40                Name = name;
 41            }
 42
 43            public Action<int> Iteration { get; set; }
 44            public Func<int, Task> IterationAsync { get; set; }
 45            public string Name { get; set; }
 46            public Stopwatch Watch { get; set; }
 47        }
 48
 49        private class Tests : List<Test>
 50        {
 51            public void Add(Action<int> iteration, string name)
 52            {
 53                Add(new Test(iteration, name));
 54            }
 55
 56            public void AsyncAdd(Func<int, Task> iterationAsync, string name)
 57            {
 58                Add(new Test(iterationAsync, name));
 59            }
 60
 61            public async Task RunAsync(int iterations)
 62            {
 63                // warmup 
 64                foreach (var test in this)
 65                {
 66                    test.Iteration?.Invoke(iterations + 1);
 67                    if (test.IterationAsync != null) await test.IterationAsync(iterations + 1).ConfigureAwait(false);
 68                    test.Watch = new Stopwatch();
 69                    test.Watch.Reset();
 70                }
 71
 72                var rand = new Random();
 73                for (int i = 1; i <= iterations; i++)
 74                {
 75                    foreach (var test in this.OrderBy(ignore => rand.Next()))
 76                    {
 77                        test.Watch.Start();
 78                        test.Iteration?.Invoke(i);
 79                        if (test.IterationAsync != null) await test.IterationAsync(i).ConfigureAwait(false);
 80                        test.Watch.Stop();
 81                    }
 82                }
 83
 84                foreach (var test in this.OrderBy(t => t.Watch.ElapsedMilliseconds))
 85                {
 86                    var ms = test.Watch.ElapsedMilliseconds.ToString();
 87                    Console.Write(ms);
 88                    Program.WriteColor("ms ".PadRight(8 - ms.Length), ConsoleColor.DarkGray);
 89                    Console.WriteLine(test.Name);
 90                }
 91            }
 92        }
 93
 94        public static string ConnectionString { get; } = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
 95
 96        public static SqlConnection GetOpenConnection()
 97        {
 98            var connection = new SqlConnection(ConnectionString);
 99            connection.Open();
100            return connection;
101        }
102
103        private static DataClassesDataContext GetL2SContext(SqlConnection connection) =>
104            new DataClassesDataContext(connection);
105
106        private static void Try(Action action, string blame)
107        {
108            try
109            {
110                action();
111            }
112            catch (Exception ex)
113            {
114                Console.Error.WriteLine($"{blame}: {ex.Message}");
115            }
116        }
117
118        public async Task RunAsync(int iterations)
119        {
120            using (var connection = GetOpenConnection())
121            {
122#pragma warning disable IDE0017 // Simplify object initialization
123#pragma warning disable RCS1121 // Use [] instead of calling 'First'.
124                var tests = new Tests();
125
126                // Linq2SQL
127                Try(() =>
128                {
129                    var l2scontext1 = GetL2SContext(connection);
130                    tests.Add(id => l2scontext1.Posts.First(p => p.Id == id), "Linq2Sql: Normal");
131
132                    var l2scontext2 = GetL2SContext(connection);
133                    var compiledGetPost = CompiledQuery.Compile((Linq2Sql.DataClassesDataContext ctx, int id) => ctx.Posts.First(p => p.Id == id));
134                    tests.Add(id => compiledGetPost(l2scontext2, id), "Linq2Sql: Compiled");
135
136                    var l2scontext3 = GetL2SContext(connection);
137                    tests.Add(id => l2scontext3.ExecuteQuery<Post>("select * from Posts where Id = {0}", id).First(), "Linq2Sql: ExecuteQuery");
138                }, "LINQ-to-SQL");
139
140                // Entity Framework
141                Try(() =>
142                {
143                    var entityContext = new EFContext(connection);
144                    tests.Add(id => entityContext.Posts.First(p => p.Id == id), "Entity Framework");
145
146                    var entityContext2 = new EFContext(connection);
147                    tests.Add(id => entityContext2.Database.SqlQuery<Post>("select * from Posts where Id = {0}", id).First(), "Entity Framework: SqlQuery");
148
149                    var entityContext3 = new EFContext(connection);
150                    tests.Add(id => entityContext3.Posts.AsNoTracking().First(p => p.Id == id), "Entity Framework: No Tracking");
151                }, "Entity Framework");
152
153                // Entity Framework Core
154                Try(() =>
155                {
156                    var entityContext = new EFCoreContext(ConnectionString);
157                    tests.Add(id => entityContext.Posts.First(p => p.Id == id), "Entity Framework Core");
158
159                    var entityContext2 = new EFCoreContext(ConnectionString);
160                    tests.Add(id => entityContext2.Posts.FromSql("select * from Posts where Id = {0}", id).First(), "Entity Framework Core: FromSql");
161
162                    var entityContext3 = new EFContext(connection);
163                    tests.Add(id => entityContext3.Posts.AsNoTracking().First(p => p.Id == id), "Entity Framework Core: No Tracking");
164                }, "Entity Framework Core");
165
166                // Dapper
167                Try(() =>
168                {
169                    var mapperConnection = GetOpenConnection();
170                    tests.Add(id => mapperConnection.Query<Post>("select * from Posts where Id = @Id", new { Id = id }, buffered: true).First(), "Dapper: Query (buffered)");
171                    tests.Add(id => mapperConnection.Query<Post>("select * from Posts where Id = @Id", new { Id = id }, buffered: false).First(), "Dapper: Query (non-buffered)");
172                    tests.Add(id => mapperConnection.QueryFirstOrDefault<Post>("select * from Posts where Id = @Id", new { Id = id }), "Dapper: QueryFirstOrDefault");
173
174                    var mapperConnection2 = GetOpenConnection();
175                    tests.Add(id => mapperConnection2.Query("select * from Posts where Id = @Id", new { Id = id }, buffered: true).First(), "Dapper: Dynamic Query (buffered)");
176                    tests.Add(id => mapperConnection2.Query("select * from Posts where Id = @Id", new { Id = id }, buffered: false).First(), "Dapper: Dynamic Query (non-buffered)");
177                    tests.Add(id => mapperConnection2.QueryFirstOrDefault("select * from Posts where Id = @Id", new { Id = id }), "Dapper: Dynamic QueryFirstOrDefault");
178
179                    // dapper.contrib
180                    var mapperConnection3 = GetOpenConnection();
181                    tests.Add(id => mapperConnection3.Get<Post>(id), "Dapper.Contrib");
182                }, "Dapper");
183
184                // Massive
185                Try(() =>
186                {
187                    var massiveModel = new DynamicModel(ConnectionString);
188                    var massiveConnection = GetOpenConnection();
189                    tests.Add(id => massiveModel.Query("select * from Posts where Id = @0", massiveConnection, id).First(), "Massive: Dynamic ORM Query");
190                }, "Massive");
191
192                // PetaPoco
193                Try(() =>
194                {
195                    // PetaPoco test with all default options
196                    var petapoco = new PetaPoco.Database(ConnectionString, "System.Data.SqlClient");
197                    petapoco.OpenSharedConnection();
198                    tests.Add(id => petapoco.Fetch<Post>("SELECT * from Posts where Id=@0", id).First(), "PetaPoco: Normal");
199
200                    // PetaPoco with some "smart" functionality disabled
201                    var petapocoFast = new PetaPoco.Database(ConnectionString, "System.Data.SqlClient");
202                    petapocoFast.OpenSharedConnection();
203                    petapocoFast.EnableAutoSelect = false;
204                    petapocoFast.EnableNamedParams = false;
205                    petapocoFast.ForceDateTimesToUtc = false;
206                    tests.Add(id => petapocoFast.Fetch<Post>("SELECT * from Posts where Id=@0", id).First(), "PetaPoco: Fast");
207                }, "PetaPoco");
208
209                // NHibernate
210                Try(() =>
211                {
212                    var nhSession1 = NHibernateHelper.OpenSession();
213                    tests.Add(id => nhSession1.CreateSQLQuery("select * from Posts where Id = :id")
214                        .SetInt32("id", id)
215                        .List(), "NHibernate: SQL");
216
217                    var nhSession2 = NHibernateHelper.OpenSession();
218                    tests.Add(id => nhSession2.CreateQuery("from Post as p where p.Id = :id")
219                        .SetInt32("id", id)
220                        .List(), "NHibernate: HQL");
221
222                    var nhSession3 = NHibernateHelper.OpenSession();
223                    tests.Add(id => nhSession3.CreateCriteria<Post>()
224                        .Add(Restrictions.IdEq(id))
225                        .List(), "NHibernate: Criteria");
226
227                    var nhSession4 = NHibernateHelper.OpenSession();
228                    tests.Add(id => nhSession4
229                        .Query<Post>()
230                        .First(p => p.Id == id), "NHibernate: LINQ");
231
232                    var nhSession5 = NHibernateHelper.OpenSession();
233                    tests.Add(id => nhSession5.Get<Post>(id), "NHibernate: Session.Get");
234                }, "NHibernate");
235
236                // Simple.Data
237                Try(() =>
238                {
239                    var sdb = Simple.Data.Database.OpenConnection(ConnectionString);
240                    tests.Add(id => sdb.Posts.FindById(id).FirstOrDefault(), "Simple.Data");
241                }, "Simple.Data");
242
243                // Belgrade
244                Try(() =>
245                {
246                    var query = new Belgrade.SqlClient.SqlDb.QueryMapper(ConnectionString);
247                    tests.AsyncAdd(id => query.ExecuteReader("SELECT TOP 1 * FROM Posts WHERE Id = " + id,
248                        reader =>
249                        {
250                            var post = new Post();
251                            post.Id = reader.GetInt32(0);
252                            post.Text = reader.GetString(1);
253                            post.CreationDate = reader.GetDateTime(2);
254                            post.LastChangeDate = reader.GetDateTime(3);
255
256                            post.Counter1 = reader.IsDBNull(4) ? null : (int?)reader.GetInt32(4);
257                            post.Counter2 = reader.IsDBNull(5) ? null : (int?)reader.GetInt32(5);
258                            post.Counter3 = reader.IsDBNull(6) ? null : (int?)reader.GetInt32(6);
259                            post.Counter4 = reader.IsDBNull(7) ? null : (int?)reader.GetInt32(7);
260                            post.Counter5 = reader.IsDBNull(8) ? null : (int?)reader.GetInt32(8);
261                            post.Counter6 = reader.IsDBNull(9) ? null : (int?)reader.GetInt32(9);
262                            post.Counter7 = reader.IsDBNull(10) ? null : (int?)reader.GetInt32(10);
263                            post.Counter8 = reader.IsDBNull(11) ? null : (int?)reader.GetInt32(11);
264                            post.Counter9 = reader.IsDBNull(12) ? null : (int?)reader.GetInt32(12);
265                        }), "Belgrade Sql Client");
266                }, "Belgrade Sql Client");
267
268                //Susanoo
269                Try(() =>
270                {
271                    var susanooDb = new DatabaseManager(connection);
272
273                    var susanooPreDefinedCommand =
274                        CommandManager.Instance.DefineCommand("SELECT * FROM Posts WHERE Id = @Id", CommandType.Text)
275                            .DefineResults<Post>()
276                            .Realize();
277
278                    var susanooDynamicPreDefinedCommand =
279                        CommandManager.Instance.DefineCommand("SELECT * FROM Posts WHERE Id = @Id", CommandType.Text)
280                            .DefineResults<dynamic>()
281                            .Realize();
282
283                    tests.Add(Id =>
284                        CommandManager.Instance.DefineCommand("SELECT * FROM Posts WHERE Id = @Id", CommandType.Text)
285                            .DefineResults<Post>()
286                            .Realize()
287                            .Execute(susanooDb, new { Id }).First(), "Susanoo: Mapping Cache Retrieval");
288
289                    tests.Add(Id =>
290                        CommandManager.Instance.DefineCommand("SELECT * FROM Posts WHERE Id = @Id", CommandType.Text)
291                            .DefineResults<dynamic>()
292                            .Realize()
293                            .Execute(susanooDb, new { Id }).First(), "Susanoo: Dynamic Mapping Cache Retrieval");
294
295                    tests.Add(Id => susanooDynamicPreDefinedCommand
296                            .Execute(susanooDb, new { Id }).First(), "Susanoo: Dynamic Mapping Static");
297
298                    tests.Add(Id => susanooPreDefinedCommand
299                            .Execute(susanooDb, new { Id }).First(), "Susanoo: Mapping Static");
300                }, "Susanoo");
301
302                //ServiceStack's OrmLite:
303                Try(() =>
304                {
305                    var dbFactory = new OrmLiteConnectionFactory(ConnectionString, SqlServerDialect.Provider);
306                    var db = dbFactory.Open();
307                    tests.Add(id => db.SingleById<Post>(id), "ServiceStack.OrmLite: SingleById");
308                }, "ServiceStack.OrmLite");
309
310                // Hand Coded
311                Try(() =>
312                {
313                    var postCommand = new SqlCommand()
314                    {
315                        Connection = connection,
316                        CommandText = @"select Id, [Text], [CreationDate], LastChangeDate, 
317                Counter1,Counter2,Counter3,Counter4,Counter5,Counter6,Counter7,Counter8,Counter9 from Posts where Id = @Id"
318                    };
319                    var idParam = postCommand.Parameters.Add("@Id", SqlDbType.Int);
320
321                    tests.Add(id =>
322                    {
323                        idParam.Value = id;
324
325                        using (var reader = postCommand.ExecuteReader())
326                        {
327                            reader.Read();
328                            var post = new Post();
329                            post.Id = reader.GetInt32(0);
330                            post.Text = reader.GetNullableString(1);
331                            post.CreationDate = reader.GetDateTime(2);
332                            post.LastChangeDate = reader.GetDateTime(3);
333
334                            post.Counter1 = reader.GetNullableValue<int>(4);
335                            post.Counter2 = reader.GetNullableValue<int>(5);
336                            post.Counter3 = reader.GetNullableValue<int>(6);
337                            post.Counter4 = reader.GetNullableValue<int>(7);
338                            post.Counter5 = reader.GetNullableValue<int>(8);
339                            post.Counter6 = reader.GetNullableValue<int>(9);
340                            post.Counter7 = reader.GetNullableValue<int>(10);
341                            post.Counter8 = reader.GetNullableValue<int>(11);
342                            post.Counter9 = reader.GetNullableValue<int>(12);
343                        }
344                    }, "Hand Coded");
345
346#if !NETSTANDARD1_3
347                    var table = new DataTable
348                    {
349                        Columns =
350                    {
351                        {"Id", typeof (int)},
352                        {"Text", typeof (string)},
353                        {"CreationDate", typeof (DateTime)},
354                        {"LastChangeDate", typeof (DateTime)},
355                        {"Counter1", typeof (int)},
356                        {"Counter2", typeof (int)},
357                        {"Counter3", typeof (int)},
358                        {"Counter4", typeof (int)},
359                        {"Counter5", typeof (int)},
360                        {"Counter6", typeof (int)},
361                        {"Counter7", typeof (int)},
362                        {"Counter8", typeof (int)},
363                        {"Counter9", typeof (int)},
364                    }
365                    };
366                    tests.Add(id =>
367                    {
368                        idParam.Value = id;
369                        object[] values = new object[13];
370                        using (var reader = postCommand.ExecuteReader())
371                        {
372                            reader.Read();
373                            reader.GetValues(values);
374                            table.Rows.Add(values);
375                        }
376                    }, "DataTable via IDataReader.GetValues");
377#endif
378                }, "Hand Coded");
379
380                // Subsonic isn't maintained anymore - doesn't import correctly
381                //Try(() =>
382                //    {
383                //    // Subsonic ActiveRecord 
384                //    tests.Add(id => 3SubSonic.Post.SingleOrDefault(x => x.Id == id), "SubSonic ActiveRecord.SingleOrDefault");
385
386                //    // Subsonic coding horror
387                //    SubSonic.tempdbDB db = new SubSonic.tempdbDB();
388                //    tests.Add(id => new SubSonic.Query.CodingHorror(db.Provider, "select * from Posts where Id = @0", id).ExecuteTypedList<Post>(), "SubSonic Coding Horror");
389                //}, "Subsonic");
390
391                //// BLToolkit - doesn't import correctly in the new .csproj world
392                //var db1 = new DbManager(GetOpenConnection());
393                //tests.Add(id => db1.SetCommand("select * from Posts where Id = @id", db1.Parameter("id", id)).ExecuteList<Post>(), "BLToolkit");
394
395                Console.WriteLine();
396                Console.WriteLine("Running...");
397                await tests.RunAsync(iterations).ConfigureAwait(false);
398#pragma warning restore RCS1121 // Use [] instead of calling 'First'.
399#pragma warning restore IDE0017 // Simplify object initialization
400            }
401        }
402    }
403}