測試EF6.1.3和OrmLite性能

     公司原來用nhibernate,如今考慮要不要換一種ORM,因而找來了EF和ServiceStack.OrmLite。因此就產生了測試這三個性能的要求。對比三個ORM工具的性能,主要是對比ORM配置和啓動速度;建錶速度;插入行速度;修改行速度以及查詢速度,刪除用的比較少,就不測試了,還有發現EF貌似比nhibernate稍微快一些,就只測EF和ServiceStack.OrmLite了。sql

     測試表結構

    public class School
    {
        public Guid ID { get; set; }
        public string Name { get; set; }
        public int AllPersonCount { get; set; }
    }
    public class Person
    {
        public long ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public School InShool { get; set; }
    }

      測試項目

1. 插入10個學校, 學校人數從1遞增,名稱相同爲」SSS」
2. 每一個學校插入1000人,年齡從1遞增,名字相同」PPP」,並返回ID
3. 查詢年齡大於30的人
4. 更新3查詢出的人的年齡到當前值加20
5. 查詢學校人數大於5的全部人
6. 統計學校人數大於5的全部人的人數數據庫

      代碼原則

1. 儘可能簡潔
2. 不能使用sql語句併發

  寫測試代碼

  nhibernate是由另外一個傢伙搞,我就寫EF的測試代碼。首先新建一個控制檯應用程序,右鍵項目管理NuGet添加EF6.1.3。而後新建那兩個表對應的類,接着就開始一個個寫啦。下面每種的兩個代碼段上面的是EF的,下面的是ServiceStack.OrmLite的ide

  ORM配置及啓動

watch.Start();
db = new TestContext();
watch.Stop();
Console.WriteLine("ORM配置及啓動:" + watch.ElapsedMilliseconds);
watch.Start();
OrmLiteConfig.DialectProvider = SqlServerDialect.Provider;
string connStr = ConfigurationManager.ConnectionStrings["SSConnection"].ConnectionString;
db = connStr.OpenDbConnection();
watch.Stop();
Console.WriteLine("ORM配置及啓動:" + watch.ElapsedMilliseconds);

  建表

watch.Restart();
db.Database.Initialize(true);
watch.Stop();
Console.WriteLine("建表:" + watch.ElapsedMilliseconds);
watch.Restart();
db.CreateTable<School>();
db.CreateTable<Person>();
watch.Stop();
Console.WriteLine("建表:" + watch.ElapsedMilliseconds);

  測試項目1

db.Configuration.AutoDetectChangesEnabled = false;
db.Configuration.ValidateOnSaveEnabled = false;
watch.Restart();

for (int i = 1; i < 11; i++)
{
    db.School.Add(new School
    {
        ID = Guid.NewGuid(),
        Name = "SSS",
        AllPersonCount = i
    });
}

db.SaveChanges();
watch.Stop();
Console.WriteLine("測試項目1:" + watch.ElapsedMilliseconds);
watch.Restart();
var schools = new List<School>();

for (int i = 1; i < 11; i++)
{
    schools.Add(new School
    {
        ID = Guid.NewGuid(),
        Name = "SSS",
        AllPersonCount = i
    });
}

db.InsertAll(schools);
watch.Stop();
Console.WriteLine("測試項目1:" + watch.ElapsedMilliseconds);

  測試項目2

watch.Restart();
List<School> schools = db.School.ToList();

schools.ForEach(o =>
{
    for (int i = 1; i < 1001; i++)
    {
        db.Person.Add(new Person
        {
            Age = i,
            Name = "PPP",
            InShool = o
        });
    }
});

db.SaveChanges();
watch.Stop();
Console.WriteLine("測試項目2:" + watch.ElapsedMilliseconds);
schools = db.LoadSelect<School>();
watch.Restart();
var students = new List<Person>();

schools.ForEach(o =>
{
    for (int i = 1; i < 1001; i++)
    {
        students.Add(new Person
        {
            Age = i,
            Name = "PPP",
            ShoolID = o.ID
        });
    }
});

db.InsertAll(students);
watch.Stop();
Console.WriteLine("測試項目2:" + watch.ElapsedMilliseconds);

  測試項目3

db.Configuration.AutoDetectChangesEnabled = true;
watch.Restart();
List<Person> person = db.Person.Where(o => o.Age > 30).ToList();
watch.Stop();
Console.WriteLine("測試項目3:" + watch.ElapsedMilliseconds);
watch.Restart();
List<Person> persons = db.Select<Person>(x => x.Age > 30);
watch.Stop();
Console.WriteLine("測試項目3:" + watch.ElapsedMilliseconds);

  測試項目4

watch.Restart();
person.ForEach(o => o.Age += 20);
db.SaveChanges();
watch.Stop();
Console.WriteLine("測試項目4:" + watch.ElapsedMilliseconds);
watch.Restart();
persons.ForEach(o => o.Age += 20);
db.UpdateAll(persons);
watch.Stop();
Console.WriteLine("測試項目4:" + watch.ElapsedMilliseconds);

  測試項目5

watch.Restart();
List<Person> students = db.Person.AsNoTracking().Where(o => o.InShool.AllPersonCount > 5).ToList();
watch.Stop();
Console.WriteLine("測試項目5:" + watch.ElapsedMilliseconds);
watch.Restart();
students = db.Select(
    db.From<Person>()
        .Join<School>((p, s) => p.ShoolID == s.ID)
        .Where<School>(s => s.AllPersonCount > 5)
    );
watch.Stop();
Console.WriteLine("測試項目5:" + watch.ElapsedMilliseconds);

  測試項目6

watch.Restart();
int count = db.Person.Count(o => o.InShool.AllPersonCount > 5);
watch.Stop();
Console.WriteLine("測試項目6:" + watch.ElapsedMilliseconds);
watch.Restart();
long count = db.Count(
    db.From<Person>()
        .Join<School>((p, s) => p.ShoolID == s.ID)
        .Where<School>(s => s.AllPersonCount > 6)
    );
watch.Stop();
Console.WriteLine("測試項目6:" + watch.ElapsedMilliseconds);

  這裏要說明一下的是測試項目5和6的人數大於5是說學校表的AllPersonCount大於5,並且那個字段並非真的學生總人數,不會隨學生的增長而增長,只是爲了測試的。工具

  EF運行3次的截圖以下:性能

  ServiceStack.OrmLite運行3次的截圖以下:測試

  接下來要開大招了,學校從加10個改成加100個,這樣的話學生就會從10000個增長到100000個,插入10萬行的時候nhibernate直接頂不住了。ui

  EF運行3次的截圖以下:spa

  ServiceStack.OrmLite運行3次的截圖以下:hibernate

  須要說明的是數據庫是mssql2008,而且程序和數據庫都在本機,不一樣的電腦的性能不同,數據庫不同也會影響測試的結果,因此你們若是要對比其餘ORM工具的話,須要把多個程序在同一個電腦上運行,而且鏈接同一個數據庫。經過對比能夠發現,輕量級的OrmLite最快,EF和nhiberate差很少快,EF稍佔優點。不過併發能力的話卻是還沒測試過,不知道那個更好。

  示例代碼下載

TestEF6.1.3

TestOrmLite

相關文章
相關標籤/搜索