mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-21 18:19:36 -06:00
This patch uses process-wide per-store locking to ensure that only one NomsBlockStore instance is ever trying to update the upstream NBS manifest at a time. It also locks out attempts to fetch the manifest contents during that window. Conjoining is now much simpler. Since only one instance can ever be in the critical path of Commit at a time, and conjoining is triggered on that critical path, we now simply perform the conjoin while excluding all other in-process NBS instances. Hopefully, locking out instances who want to fetch the manifest contents during a conjoin won't cripple performance. Fixes issue #3583
102 lines
3.1 KiB
Go
102 lines
3.1 KiB
Go
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
|
// Licensed under the Apache License, version 2.0:
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
package nbs
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/attic-labs/noms/go/chunks"
|
|
"github.com/attic-labs/noms/go/hash"
|
|
"github.com/attic-labs/testify/assert"
|
|
)
|
|
|
|
func TestStats(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
stats := func(store *NomsBlockStore) Stats {
|
|
return store.Stats().(Stats)
|
|
}
|
|
|
|
dir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
store := NewLocalStore(dir, testMemTableSize)
|
|
|
|
assert.EqualValues(1, stats(store).OpenLatency.Samples())
|
|
|
|
// Opening a new store will still incur some read IO, to discover that the manifest doesn't exist
|
|
assert.EqualValues(1, stats(store).ReadManifestLatency.Samples())
|
|
|
|
i1, i2, i3, i4, i5 := []byte("abc"), []byte("def"), []byte("ghi"), []byte("jkl"), []byte("mno")
|
|
|
|
c1, c2, c3, c4, c5 := chunks.NewChunk(i1), chunks.NewChunk(i2), chunks.NewChunk(i3), chunks.NewChunk(i4), chunks.NewChunk(i5)
|
|
|
|
// These just go to mem table, only operation stats
|
|
store.Put(c1)
|
|
store.Put(c2)
|
|
store.Put(c3)
|
|
assert.Equal(uint64(3), stats(store).PutLatency.Samples())
|
|
assert.Equal(uint64(0), stats(store).PersistLatency.Samples())
|
|
|
|
assert.True(store.Has(c1.Hash()))
|
|
assert.True(store.Has(c2.Hash()))
|
|
assert.True(store.Has(c3.Hash()))
|
|
assert.Equal(uint64(3), stats(store).HasLatency.Samples())
|
|
assert.Equal(uint64(4), stats(store).AddressesPerHas.Sum())
|
|
|
|
assert.False(store.Get(c1.Hash()).IsEmpty())
|
|
assert.False(store.Get(c2.Hash()).IsEmpty())
|
|
assert.False(store.Get(c3.Hash()).IsEmpty())
|
|
assert.Equal(uint64(3), stats(store).GetLatency.Samples())
|
|
assert.Equal(uint64(0), stats(store).FileReadLatency.Samples())
|
|
assert.Equal(uint64(4), stats(store).ChunksPerGet.Sum())
|
|
|
|
store.Commit(store.Root(), store.Root())
|
|
|
|
// Commit will update the manifest
|
|
assert.EqualValues(1, stats(store).WriteManifestLatency.Samples())
|
|
assert.EqualValues(1, stats(store).CommitLatency.Samples())
|
|
|
|
// Now we have write IO
|
|
assert.Equal(uint64(1), stats(store).PersistLatency.Samples())
|
|
assert.Equal(uint64(3), stats(store).ChunksPerPersist.Sum())
|
|
assert.Equal(uint64(192), stats(store).BytesPerPersist.Sum())
|
|
|
|
// Now some gets that will incur read IO
|
|
store.Get(c1.Hash())
|
|
store.Get(c2.Hash())
|
|
store.Get(c3.Hash())
|
|
assert.Equal(uint64(3), stats(store).FileReadLatency.Samples())
|
|
assert.Equal(uint64(36), stats(store).FileBytesPerRead.Sum())
|
|
|
|
// Try A GetMany
|
|
chnx := make([]chunks.Chunk, 3)
|
|
chnx[0] = c1
|
|
chnx[1] = c2
|
|
chnx[2] = c3
|
|
hashes := make(hash.HashSlice, len(chnx))
|
|
for i, c := range chnx {
|
|
hashes[i] = c.Hash()
|
|
}
|
|
chunkChan := make(chan *chunks.Chunk, 3)
|
|
store.GetMany(hashes.HashSet(), chunkChan)
|
|
assert.Equal(uint64(4), stats(store).FileReadLatency.Samples())
|
|
assert.Equal(uint64(60), stats(store).FileBytesPerRead.Sum())
|
|
|
|
// Force a conjoin
|
|
store.c = inlineConjoiner{2}
|
|
store.Put(c4)
|
|
store.Commit(store.Root(), store.Root())
|
|
store.Put(c5)
|
|
store.Commit(store.Root(), store.Root())
|
|
|
|
assert.Equal(uint64(1), stats(store).ConjoinLatency.Samples())
|
|
// TODO: Once random conjoin hack is out, test other conjoin stats
|
|
|
|
defer store.Close()
|
|
defer os.RemoveAll(dir)
|
|
}
|