Производительность драйвера golang mongo

Я написал код для тестирования mongodb. Но скорость у него такая плохая. Что не так?

func mgoSpeedTest(N int) int64 {
    session, err := mgo.Dial(MongoHost)
    if err != nil {
        panic(err)
    }
    defer session.Close()
    session.SetMode(mgo.Monotonic, true)

    start := time.Now()
    for i := 0; i < N; i++ {
        sessionCopy := session.Copy()
        c := session.DB(MongoDB).C(MongoCol)
        _, err = c.Find(bson.M{"id": 1}).Count()
        if err != nil {
            log.Fatal(err)
        }
        sessionCopy.Close()
    }
    t := time.Now()
    elapsed := t.Sub(start)
    return elapsed.Milliseconds()
}

func main() {
    // speed test
    N := 1000
    ms = mgoSpeedTest(N)
    println(fmt.Sprintf("mgo: %d", ms))
}

Ответ ~~ 3500мс Пробовал использовать mongo-client, но скорость та же ~ 3700-3800

Вы выполняете 1 тысячу запросов, в среднем 3,5 мс (включая передачу по сети туда и обратно, выполнение базы данных, обработку результатов, копирование и закрытие сеанса). Что считается хорошим? Учитывая то, что происходит под капотом, я не думаю, что это плохо. Используйте тот же сеанс, если хотите повысить производительность.   —  person Егор Козельский    schedule 16.10.2019

Я также пробовал вставить 1000 документов в базу данных localhost. 1000 вставок = 36 секунд. Но в официальных скоростных характеристиках разница в скорости   —  person Егор Козельский    schedule 16.10.2019

Я бы также выполнил вызов mgo.Dial() перед запуском таймера, чтобы убедиться, что ваш сеанс готов.   —  person Егор Козельский    schedule 16.10.2019

И вы исключаете возможность того, что это ваш код плохо себя ведет? Я бы не стал. Раскройте код, и мы сможем выяснить, в чем проблема. Подсказка: если бы это было обычным явлением, никто бы не использовал драйвер mongo. Даже MongoDB Inc. И все их инструменты (mongodump и т. Д.) Написаны на Go.   —  person Егор Козельский    schedule 16.10.2019

Кроме того, вы смотрите вверх id (не _id, заметьте). Это в основном означает, что выполняется сканирование коллекции. Суть: MongoDB необходимо открывать каждый документ, читать его, сравнивать значение поля id с 1. Кстати, ваш код даже не компилируется — у меня такое ощущение, что вы скрываете информацию случайно или намеренно. Если код отсутствует, это не позволяет нам помочь вам должным образом.   —  person Егор Козельский    schedule 18.10.2019

См. также:  Как создать пакет библиотеки стилизованных компонентов для работы с Gatsby
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. Егор Козельский

    Важно

    К моему большому разочарованию, я не могу предложить больше использовать mgo, поскольку он выглядит как больше не поддерживается на момент написания этой статьи.

    Мне было любопытно, и я составил собственный небольшой тест. Он использует один экземпляр MongoDB через докер:

    $ docker run -d --name mongobench -p 27017:27017 mongo
    731e5f57d677718244c2304a992abd44a5a4bbad6f1fd8e5a23e53b3c4f9ada4
    

    Примечание: полученный хеш будет другим.

    Согласно эталону, это двоякое: простая вставка и объемная вставка. Массовые вставки — это предпочтительный способ борьбы с массовыми вставками.

    Он проверяет как драйвер mgo, так и драйвер mongo-go:

    package mongobench
    
    // Use
    //  docker run -d --name mongobench -p 27017:27017 mongo
    // to create a suitable test instance and access it via
    //  docker exec -it mongobench mongo
    
    import (
        "context"
        "log"
        "testing"
    
        "github.com/globalsign/mgo"
        "github.com/globalsign/mgo/bson"
        "go.mongodb.org/mongo-driver/mongo"
        "go.mongodb.org/mongo-driver/mongo/options"
    )
    
    type Data struct {
        ID      primitive.ObjectID `bson:"_id"`
        Counter int
    }
    
    const DefaultHost = "localhost:27017"
    const DefaultDB = "test"
    const DefaultCollection = "bench"
    
    var sess *mgo.Session
    var client *mongo.Client
    
    func init() {
        var err error
    
        sess, err = mgo.Dial(DefaultHost)
        if err != nil {
            log.Fatalf("setting up session: %s", err)
        }
    
        client, err = mongo.NewClient(options.Client().ApplyURI("mongodb://" + DefaultHost))
        if err != nil {
            log.Fatalf("setting up client: %s", err)
        }
    
        if err = client.Connect(context.Background()); err != nil {
            log.Fatalf("connecting with client: %s", err)
        }
    }
    func BenchmarkMgoInsert(b *testing.B) {
    
        c := sess.DB(DefaultDB).C("simple")
        if _, err := c.RemoveAll(bson.M{}); err != nil {
            b.Logf("cleaning collection 'simple': %s", err)
            b.FailNow()
        }
    
        b.ResetTimer()
    
        for i := 0; i < b.N; i++ {
            if err := c.Insert(&Data{ID: bson.NewObjectId(), Counter: i}); err != nil {
                b.Logf("error inserting: %s", err)
                b.FailNow()
            }
        }
    }
    
    func BenchmarkMgoBulk(b *testing.B) {
        c := sess.DB(DefaultDB).C("bulk")
        if _, err := c.RemoveAll(bson.M{}); err != nil {
            b.Logf("cleaning collection 'simple': %s", err)
            b.FailNow()
        }
    
        b.ResetTimer()
    
        bulk := c.Bulk()
    
        for i := 0; i < b.N; i++ {
            bulk.Insert(&Data{ID: bson.NewObjectId(), Counter: i})
        }
    
        if _, err := bulk.Run(); err != nil {
            b.Logf("executing bulk: %s", err)
            b.FailNow()
        }
    }
    
    func BenchmarkMongoInsert(b *testing.B) {
        c := client.Database(DefaultDB).Collection("mongosimple")
        if _, err := c.DeleteMany(context.Background(), bson.M{}); err != nil {
            b.Logf("cleaning collection 'mongosimple': %s", err)
            b.FailNow()
        }
    
        b.ResetTimer()
    
        for i := 0; i < b.N; i++ {
            c.InsertOne(context.Background(), &Data{ID: bson.NewObjectId(), Counter: i})
        }
    }
    
    func BenchmarkMongoBulk(b *testing.B) {
    
        c := client.Database(DefaultDB).Collection("mongobulk")
        if _, err := c.DeleteMany(context.Background(), bson.M{}); err != nil {
            b.Logf("cleaning collection 'mongosimple': %s", err)
            b.FailNow()
        }
    
        d := make([]mongo.WriteModel, b.N)
    
        b.ResetTimer()
    
        for i := 0; i < b.N; i++ {
            d[i] = mongo.NewInsertOneModel().SetDocument(Data{ID: bson.NewObjectId(), Counter: i})
        }
    
        if _, err := c.BulkWrite(context.Background(), d); err != nil {
            b.Logf("inserting bulk: %s", err)
            b.FailNow()
        }
    
    }
    
    goos: darwin
    goarch: amd64
    pkg: github.com/mwmahlberg/so-mongobench
    BenchmarkMgoInsert-4            1164       1100919 ns/op        1501 B/op         44 allocs/op
    BenchmarkMgoBulk-4            201560          6512 ns/op         258 B/op          4 allocs/op
    BenchmarkMongoInsert-4          1171       1019140 ns/op        3642 B/op         66 allocs/op
    BenchmarkMongoBulk-4          181040          7251 ns/op        1151 B/op         15 allocs/op
    

    Мы видим, что оба драйвера на порядки быстрее, чем вы описываете, поэтому можно с уверенностью предположить, что это не драйвер, вызывающий задержки.

    где вы определяете данные {}? person Егор Козельский; 21.01.2020

    @ScottStensland Честно говоря, я этого не делал, так как думал, что это будет слишком очевидно. Добавлю это. person Егор Козельский; 21.01.2020

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: