MongoDb插入速度非常慢,单线程插入和多个

时间:2013-07-09 08:10:26

标签: c# performance mongodb concurrency

我已经为我写过的存储库编写了一些测试。

public interface IEntity<T> {
    T Id { get; set; }
}

public abstract class Entity<TEntity> : IEntity<TEntity> {
    [BsonId]
    public  TEntity Id { get; set; }

    public override string ToString() {
        return JsonConvert.SerializeObject(this, Formatting.Indented, new JsonSerializerSettings {
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
        });
    }
}

public interface IMongoRepository<TEntity, TE> : IQueryable<TEntity> where TEntity : IEntity<TE> {
    string ConnectionString { get; set; }
    bool Remove<T>(TEntity entity);
    bool Save<T>(TEntity entity);
    bool Update<T>(TEntity entity);
}

public sealed class MongoRepository<TEntity, TU> : IMongoRepository<TEntity, TU>
    where TEntity : Entity<TU> {

    public MongoCollection<TEntity> Collection {
        get {
            var client = new MongoClient(ConnectionString);
            var server = client.GetServer();
            var db = server.GetDatabase("mykantina");
            return db.GetCollection<TEntity>(typeof (TEntity).Name.Pluralize());
        }
    }

    private IQueryable<TEntity> Queryable {
        get { return Collection.FindAll().AsQueryable(); }
    }

    #region IRepository<T,U> Implementation

    public string ConnectionString { get; set; }

    public bool Remove<T>(TEntity entity) {
        try {
            var e = entity as Entity<TU>;
            if (e == null) return false;
            WriteConcernResult resultConcern = Collection.Remove(Query.EQ("_id", e.Id.ToBson()));
            return true;
        }
        catch (Exception e) {
            return false;
        }
    }

    public bool Save<T>(TEntity entity) {
        try {
            WriteConcernResult resultConcern = Collection.Save(entity);
            return true;
        }
        catch (Exception e) {
            return false;
        }
    }

    public bool Update<T>(TEntity entity) {
        throw new NotImplementedException();
    }

    #endregion


    #region IQueryable<T> Implementation

    public IEnumerator<TEntity> GetEnumerator() {
        return Queryable.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return Queryable.GetEnumerator();
    }

    public Type ElementType {
        get { return Queryable.ElementType; }
    }

    public Expression Expression {
        get { return Queryable.Expression; }
    }

    public IQueryProvider Provider {
        get { return Queryable.Provider; }
    }

    #endregion
}

以下是测试:

 [Test]
    public void LinearInsertsToMongoDb() {
        Stopwatch total = Stopwatch.StartNew();
        for (int i = 0; i <= 100000; i++) {
            Stopwatch sw = Stopwatch.StartNew();
            var isOk = _repository.Save<Widget>(new Widget {
                Name = "Calendar" + i
            });
            sw.Stop();
            Trace.WriteLine(string.Format("Took to insert {0}ms - item {1}", sw.ElapsedMilliseconds, i));
        }
        Trace.WriteLine(string.Format("================================================================"));
        total.Stop();
        Trace.WriteLine(string.Format("Total = {0}ms", total.ElapsedMilliseconds));

}

Time result: Total = 212398ms

private static object _sync = new object();

    [Test]
    public void ConcurrentInsertsToMongoDb() {
        Stopwatch total = Stopwatch.StartNew();
        var waitHandlers = new List<WaitHandle>();

        for (int i = 0; i < 50; i++) {
            var threadFinish = new EventWaitHandle(false, EventResetMode.ManualReset);
            waitHandlers.Add(threadFinish);

            var thread = new Thread(() => {
                RunMongoThread();
                threadFinish.Set();
            });

            thread.Start();
        }
        WaitHandle.WaitAll(waitHandles: waitHandlers.ToArray());
        Trace.WriteLine(string.Format("================================================================"));
        total.Stop();
        Trace.WriteLine(string.Format("Total = {0}ms", total.ElapsedMilliseconds));
    }

    private static void RunMongoThread() {
        for (var i = 0; i < 300; i++) {
            bool isLocked = false;
            try {
                Monitor.Enter(_sync, ref isLocked);
                var widget = new Widget {
                    Name = "Calendar" + i
                };
                var isOk = _repository.Save<Widget>(widget);
                Trace.WriteLine(string.Format("Object: {0} - Thread {1}", widget, Thread.CurrentThread.ManagedThreadId));
            }
            finally {
                if(isLocked)
                    Monitor.Exit(_sync);
            }
        }
    }

Time result: Total 31303ms

问题是我做错了什么以及为什么这么慢?

0 个答案:

没有答案