blob: 154649438e21265f1452882ebff368245e8dac9b [file] [log] [blame] [edit]
/*
* Copyright 2017 Dgraph Labs, Inc. and Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package badger
import (
"expvar"
"math/rand"
"testing"
"github.com/stretchr/testify/require"
)
func clearAllMetrics() {
expvar.Do(func(kv expvar.KeyValue) {
// Reset the value of each expvar variable based on its type
switch v := kv.Value.(type) {
case *expvar.Int:
v.Set(0)
case *expvar.Float:
v.Set(0)
case *expvar.Map:
v.Init()
case *expvar.String:
v.Set("")
}
})
}
func TestWriteMetrics(t *testing.T) {
opt := getTestOptions("")
opt.managedTxns = true
opt.CompactL0OnClose = true
runBadgerTest(t, &opt, func(t *testing.T, db *DB) {
clearAllMetrics()
num := 10
val := make([]byte, 1<<12)
key := make([]byte, 40)
for i := 0; i < num; i++ {
_, err := rand.Read(key)
require.NoError(t, err)
_, err = rand.Read(val)
require.NoError(t, err)
writer := db.NewManagedWriteBatch()
require.NoError(t, writer.SetEntryAt(NewEntry(key, val), 1))
writer.Flush()
}
expectedSize := int64(len(val)) + 48 + 2 // 48 := size of key (40 + 8(ts)), 2 := meta
write_metric := expvar.Get("badger_write_bytes_user")
require.Equal(t, expectedSize*int64(num), write_metric.(*expvar.Int).Value())
put_metric := expvar.Get("badger_put_num_user")
require.Equal(t, int64(num), put_metric.(*expvar.Int).Value())
lsm_metric := expvar.Get("badger_write_bytes_l0")
require.Equal(t, expectedSize*int64(num), lsm_metric.(*expvar.Int).Value())
compactionMetric := expvar.Get("badger_write_bytes_compaction").(*expvar.Map)
require.Equal(t, nil, compactionMetric.Get("l6"))
// Force compaction
db.Close()
_, err := OpenManaged(opt)
require.NoError(t, err)
compactionMetric = expvar.Get("badger_write_bytes_compaction").(*expvar.Map)
require.GreaterOrEqual(t, expectedSize*int64(num)+int64(num*200), compactionMetric.Get("l6").(*expvar.Int).Value())
// Because we have random values, compression is not able to do much, so we incur a cost on total size
})
}
func TestVlogMetrics(t *testing.T) {
opt := getTestOptions("")
opt.managedTxns = true
opt.CompactL0OnClose = true
runBadgerTest(t, &opt, func(t *testing.T, db *DB) {
clearAllMetrics()
num := 10
val := make([]byte, 1<<20) // Large Value
key := make([]byte, 40)
for i := 0; i < num; i++ {
_, err := rand.Read(key)
require.NoError(t, err)
_, err = rand.Read(val)
require.NoError(t, err)
writer := db.NewManagedWriteBatch()
require.NoError(t, writer.SetEntryAt(NewEntry(key, val), 1))
writer.Flush()
}
expectedSize := int64(len(val)) + 200 // vlog expected size
totalWrites := expvar.Get("badger_write_num_vlog")
require.Equal(t, int64(num), totalWrites.(*expvar.Int).Value())
bytesWritten := expvar.Get("badger_write_bytes_vlog")
require.GreaterOrEqual(t, expectedSize*int64(num), bytesWritten.(*expvar.Int).Value())
txn := db.NewTransactionAt(2, false)
item, err := txn.Get(key)
require.NoError(t, err)
require.Equal(t, uint64(1), item.Version())
err = item.Value(func(val []byte) error {
totalReads := expvar.Get("badger_read_num_vlog")
bytesRead := expvar.Get("badger_read_bytes_vlog")
require.Equal(t, int64(1), totalReads.(*expvar.Int).Value())
require.GreaterOrEqual(t, expectedSize, bytesRead.(*expvar.Int).Value())
return nil
})
require.NoError(t, err)
})
}
func TestReadMetrics(t *testing.T) {
opt := getTestOptions("")
opt.managedTxns = true
opt.CompactL0OnClose = true
runBadgerTest(t, &opt, func(t *testing.T, db *DB) {
clearAllMetrics()
num := 10
val := make([]byte, 1<<15)
keys := [][]byte{}
writer := db.NewManagedWriteBatch()
for i := 0; i < num; i++ {
keyB := key("byte", 1)
keys = append(keys, []byte(keyB))
_, err := rand.Read(val)
require.NoError(t, err)
require.NoError(t, writer.SetEntryAt(NewEntry([]byte(keyB), val), 1))
}
writer.Flush()
txn := db.NewTransactionAt(2, false)
item, err := txn.Get(keys[0])
require.NoError(t, err)
require.Equal(t, uint64(1), item.Version())
totalGets := expvar.Get("badger_get_num_user")
require.Equal(t, int64(1), totalGets.(*expvar.Int).Value())
totalMemtableReads := expvar.Get("badger_get_num_memtable")
require.Equal(t, int64(1), totalMemtableReads.(*expvar.Int).Value())
totalLSMGets := expvar.Get("badger_get_num_lsm")
require.Nil(t, totalLSMGets.(*expvar.Map).Get("l6"))
// Force compaction
db.Close()
db, err = OpenManaged(opt)
require.NoError(t, err)
txn = db.NewTransactionAt(2, false)
item, err = txn.Get(keys[0])
require.NoError(t, err)
require.Equal(t, uint64(1), item.Version())
_, err = txn.Get([]byte(key("abdbyte", 1000))) // val should be far enough that bloom filter doesn't hit
require.Error(t, err)
totalLSMGets = expvar.Get("badger_get_num_lsm")
require.Equal(t, int64(0x1), totalLSMGets.(*expvar.Map).Get("l6").(*expvar.Int).Value())
totalBloom := expvar.Get("badger_hit_num_lsm_bloom_filter")
require.Equal(t, int64(0x1), totalBloom.(*expvar.Map).Get("l6").(*expvar.Int).Value())
require.Equal(t, int64(0x1), totalBloom.(*expvar.Map).Get("DoesNotHave_HIT").(*expvar.Int).Value())
require.Equal(t, int64(0x2), totalBloom.(*expvar.Map).Get("DoesNotHave_ALL").(*expvar.Int).Value())
bytesLSM := expvar.Get("badger_read_bytes_lsm")
require.Equal(t, int64(len(val)), bytesLSM.(*expvar.Int).Value())
getWithResult := expvar.Get("badger_get_with_result_num_user")
require.Equal(t, int64(2), getWithResult.(*expvar.Int).Value())
iterOpts := DefaultIteratorOptions
iter := txn.NewKeyIterator(keys[0], iterOpts)
iter.Seek(keys[0])
rangeQueries := expvar.Get("badger_iterator_num_user")
require.Equal(t, int64(1), rangeQueries.(*expvar.Int).Value())
})
}