Transaction与OpenCloseTransaction效率分析

前些天在群里讨论到Transaction读写实体的效率问题,今天就做了一段代码说明一下Transaction的效.Transaction是什么东西这里就不做讨论了,有兴趣的朋友可以在论坛里面搜索以前的帖子. Transaction有一个子类,叫做OpenCloseTransation,在文档中这样描述它

This class may be used instead of the transaction class in certain scenarios..It wraps the ObjectId.Open/Close functions, but makes it easier to correctly pair these functions by storing references to every object opened and automatically closing them.

也就是说在对实体进行打开关闭操作的时候,它可以替代Transaction类. 我们通过下面代码来测试OpenCloseTransation和Transaction的效率上的区别.

[CommandMethod("GetTransTime")]
public void GetTransTime() {
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
    Stopwatch watch = new Stopwatch();
    PromptSelectionResult res = ed.SelectAll();
    if (res.Status != PromptStatus.OK) {
        return;
    }
    ed.WriteMessage("\nCount of entities : {0}", res.Value.Count.ToString());

    watch.Start();
    using (Transaction trans = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()) {
        foreach (ObjectId id in res.Value.GetObjectIds()) {
            Entity ent = trans.GetObject(id, OpenMode.ForWrite) as Entity;
            ent.ColorIndex = 1;
        }
        trans.Commit();
    }
    watch.Stop();
    ed.WriteMessage("\nOne Transaction write cost: {0}(ms)", watch.ElapsedMilliseconds.ToString());

    watch.Reset();
    watch.Start();
    using (Transaction trans = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()) {
        foreach (ObjectId id in res.Value.GetObjectIds()) {
            Entity ent = trans.GetObject(id, OpenMode.ForRead) as Entity;
            int nColor = ent.ColorIndex;
        }
    }
    watch.Stop();
    ed.WriteMessage("\nOne Transaction read cost: {0}(ms)", watch.ElapsedMilliseconds.ToString());

    watch.Reset();
    watch.Start();
    using (OpenCloseTransaction trans = HostApplicationServices.WorkingDatabase.TransactionManager.StartOpenCloseTransaction()) {
        foreach (ObjectId id in res.Value.GetObjectIds()) {
            Entity ent = trans.GetObject(id, OpenMode.ForWrite) as Entity;
            ent.ColorIndex = 2;
        }
        trans.Commit();
    }
    watch.Stop();
    ed.WriteMessage("\nOne OpenCloseTransaction write cost: {0}(ms)", watch.ElapsedMilliseconds.ToString());

    watch.Reset();
    watch.Start();
    using (OpenCloseTransaction trans = HostApplicationServices.WorkingDatabase.TransactionManager.StartOpenCloseTransaction()) {
        foreach (ObjectId id in res.Value.GetObjectIds()) {
            Entity ent = trans.GetObject(id, OpenMode.ForRead) as Entity;
            int nColor = ent.ColorIndex;
        }
    }
    watch.Stop();
    ed.WriteMessage("\nOne OpenCloseTransaction read cost: {0}(ms)", watch.ElapsedMilliseconds.ToString());

    watch.Reset();
    watch.Start();
    foreach (ObjectId id in res.Value.GetObjectIds()) {
        using (OpenCloseTransaction trans = HostApplicationServices.WorkingDatabase.TransactionManager.StartOpenCloseTransaction()) {
            Entity ent = trans.GetObject(id, OpenMode.ForRead) as Entity;
            int nColor = ent.ColorIndex;
        }
    }
    watch.Stop();
    ed.WriteMessage("\nMulty OpenCloseTransaction read cost: {0}(ms)", watch.ElapsedMilliseconds.ToString());


    watch.Reset();
    watch.Start();
    foreach (ObjectId id in res.Value.GetObjectIds()) {
        using (Transaction trans = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()) {
            Entity ent = trans.GetObject(id, OpenMode.ForRead) as Entity;
            int nColor = ent.ColorIndex;
        }
    }
    watch.Stop();
    ed.WriteMessage("\nMulty Transaction read cost: {0}(ms)", watch.ElapsedMilliseconds.ToString());
}

上述代码在VS 2017 + Civil3d 2016中对于一张现有图形的运行结果如下

命令: GETTRANSTIME

Count of entities : 4124

One Transaction write cost: 782(ms)

One Transaction read cost: 60(ms)

One OpenCloseTransaction write cost: 241(ms)

One OpenCloseTransaction read cost: 5(ms)

Multy OpenCloseTransaction read cost: 36(ms)

Multy Transaction read cost: 51201(ms)

我们由此可以得到一个结论,OpenCloseTransation对于处理实体的读操作,效率比Transaction要高很多, 特别是需要处理多个事务时,效率提升更加明显.并且,一次一个Transaction处理多个实体,比每个实体新建一个Transaction效率要高的多.