ronantakizawa/codereview-bench huggingface dataset:
Repository: derailed/k9s
File: internal/view/browser.go (Go)

Code before:
		if _, e := b.app.factory.CanForResource(ns, b.GVR(), client.ListAccess); e != nil {
			return e
		}
	}
	if b.App().IsRunning() {
		b.app.CmdBuff().Reset()
	}
	b.SetReadOnly(b.app.Config.IsReadOnly())
	b.SetNoIcon(b.app.Config.K9s.UI.NoIcons)
	b.SetFullGVR(b.app.Config.K9s.UI.UseFullGVRTitle)

	b.bindKeys(b.Actions())
	for _, f := range b.bindKeysFn {
		f(b.Actions())
	}
	b.accessor, err = dao.AccessorFor(b.app.factory, b.GVR())
	if err != nil {
		return err
	}

	b.setNamespace(ns)
	row, _ := b.GetSelection()
	if row == 0 && b.GetRowCount() > 0 {
		b.Select(1, 0)
	}
	b.GetModel().SetRefreshRate(time.Duration(b.App().Config.K9s.GetRefreshRate() * float64(time.Second)))

	b.CmdBuff().SetSuggestionFn(b.suggestFilter())

	return nil
}

// InCmdMode checks if prompt is active.
func (b *Browser) InCmdMode() bool {
	return b.CmdBuff().InCmdMode()
}

func (b *Browser) suggestFilter() model.SuggestionFunc {
	return func(s string) (entries sort.StringSlice) {
		if s == "" {
			if b.App().filterHistory.Empty() {
				return
			}
			return b.App().filterHistory.List()
		}

		s = strings.ToLower(s)
		for _, h := range b.App().filterHistory.List() {
			if s == h {
				continue
			}

Review comment (refactor):
we should make this a helper and just return a duration aka something like `config.RefreshDuration`

Code after:
		if _, e := b.app.factory.CanForResource(ns, b.GVR(), client.ListAccess); e != nil {
			return e
		}
	}
	if b.App().IsRunning() {
		b.app.CmdBuff().Reset()
	}
	b.SetReadOnly(b.app.Config.IsReadOnly())
	b.SetNoIcon(b.app.Config.K9s.UI.NoIcons)
	b.SetFullGVR(b.app.Config.K9s.UI.UseFullGVRTitle)

	b.bindKeys(b.Actions())
	for _, f := range b.bindKeysFn {
		f(b.Actions())
	}
	b.accessor, err = dao.AccessorFor(b.app.factory, b.GVR())
	if err != nil {
		return err
	}

	b.setNamespace(ns)
	row, _ := b.GetSelection()
	if row == 0 && b.GetRowCount() > 0 {
		b.Select(1, 0)
	}
	b.GetModel().SetRefreshRate(b.App().Config.K9s.RefreshDuration())

	b.CmdBuff().SetSuggestionFn(b.suggestFilter())

	return nil
}

// InCmdMode checks if prompt is active.
func (b *Browser) InCmdMode() bool {
	return b.CmdBuff().InCmdMode()
}

func (b *Browser) suggestFilter() model.SuggestionFunc {
	return func(s string) (entries sort.StringSlice) {
		if s == "" {
			if b.App().filterHistory.Empty() {
				return
			}
			return b.App().filterHistory.List()
		}

		s = strings.ToLower(s)
		for _, h := range b.App().filterHistory.List() {
			if s == h {
				continue
			}
Repository: derailed/k9s
File: internal/dao/log_items.go (Go)

Code before:
	q = strings.TrimSpace(q)
	matches, indices = make([]int, 0, len(l.items)), make([][]int, 0, len(l.items))
	mm := fuzzy.Find(q, l.StrLines(index, showTime))
	for _, m := range mm {
		matches = append(matches, m.Index)
		indices = append(indices, m.MatchedIndexes)
	}

	return matches, indices
}

func (l *LogItems) filterLogs(index int, q string, showTime bool) (matches []int, indices [][]int, err error) {
	var invert bool
	if internal.IsInverseSelector(q) {
		invert = true
		q = q[1:]
	}
	rx, err := regexp.Compile(`(?i)` + q)
	if err != nil {
		return nil, nil, err
	}
	matches, indices = make([]int, 0, len(l.items)), make([][]int, 0, len(l.items))
	ll := make([][]byte, len(l.items[index:]))
	l.Lines(index, showTime, ll)
	for i, line := range ll {
		lineStr := string(line)
		locs := rx.FindAllStringIndex(lineStr, -1)
		if locs != nil && invert {
			continue
		}
		if locs == nil && !invert {
			continue
		}
		matches = append(matches, i)
		ii := make([]int, 0, 10)
		for _, loc := range locs {
			// Convert string indices to byte indices
			startBytes := len([]byte(lineStr[:loc[0]]))
			endBytes := len([]byte(lineStr[:loc[1]]))
			for j := startBytes; j < endBytes; j++ {
				ii = append(ii, j)
			}
		}
		indices = append(indices, ii)
	}

	return matches, indices, nil
}


Review comment (performance):
This is a tight loop and cardinality can be high. Converting bytes to string causes allocations which we are trying to avoid hence we deal with bytes.
This will need additional tests and ensure benchmarks are still on par

Code after:
	q = strings.TrimSpace(q)
	matches, indices = make([]int, 0, len(l.items)), make([][]int, 0, len(l.items))
	mm := fuzzy.Find(q, l.StrLines(index, showTime))
	for _, m := range mm {
		matches = append(matches, m.Index)
		indices = append(indices, m.MatchedIndexes)
	}

	return matches, indices
}

func (l *LogItems) filterLogs(index int, q string, showTime bool) (matches []int, indices [][]int, err error) {
	var invert bool
	if internal.IsInverseSelector(q) {
		invert = true
		q = q[1:]
	}
	rx, err := regexp.Compile(`(?i)` + q)
	if err != nil {
		return nil, nil, err
	}
	matches, indices = make([]int, 0, len(l.items)), make([][]int, 0, len(l.items))
	ll := make([][]byte, len(l.items[index:]))
	l.Lines(index, showTime, ll)
	for i, line := range ll {
		locs := rx.FindAllIndex(line, -1)
		if locs != nil && invert {
			continue
		}
		if locs == nil && !invert {
			continue
		}
		matches = append(matches, i)
		ii := make([]int, 0, 10)
		for _, loc := range locs {
			for j := loc[0]; j < loc[1]; j++ {
				ii = append(ii, j)
			}
		}
		indices = append(indices, ii)
	}

	return matches, indices, nil
}
Repository: derailed/k9s
File: internal/dao/pod.go (Go)

Code before:
}

// ----------------------------------------------------------------------------
// Helpers...

func tailLogs(ctx context.Context, logger Logger, opts *LogOptions) LogChan {
	out := make(LogChan, logChannelBuffer)
	var wg sync.WaitGroup

	wg.Add(1)
	go func() {
		defer wg.Done()
		podOpts := opts.ToPodLogOptions()

		// Setup exponential backoff following project pattern
		bf := backoff.NewExponentialBackOff()
		bf.InitialInterval = logBackoffInitial
		bf.MaxElapsedTime = 0
		bf.MaxInterval = logBackoffMax / 2
		backoffCtx := backoff.WithContext(bf, ctx)
		delay := logBackoffInitial
		firstAttempt := true

		for range logRetryCount {
			// Check if we should stop retrying based on pod status
			if !firstAttempt {
				if pod, ok := logger.(*Pod); ok && pod.shouldStopRetrying(opts.Path) {
					slog.Debug("Stopping log retry - pod is terminating or deleted",
						slogs.Container, opts.Info(),
					)
					return
				}
			}

			req, err := logger.Logs(opts.Path, podOpts)
			if err != nil {
				slog.Error("Log request failed",
					slogs.Container, opts.Info(),
					slogs.Error, err,
				)
				select {
				case <-ctx.Done():
					return
				case <-time.After(delay):
					if delay = backoffCtx.NextBackOff(); delay == backoff.Stop {
						return
					}
				}
				continue
			}


Review comment (bug):
I think we could reverse the logic here and make this a post check. ie try to get the logs if it fails then check whether we should retry. This would avoid the bool check and also handles previous logs.
Would this make sense?

Code after:
}

// ----------------------------------------------------------------------------
// Helpers...

func tailLogs(ctx context.Context, logger Logger, opts *LogOptions) LogChan {
	out := make(LogChan, logChannelBuffer)
	var wg sync.WaitGroup

	wg.Add(1)
	go func() {
		defer wg.Done()
		podOpts := opts.ToPodLogOptions()

		// Setup exponential backoff following project pattern
		bf := backoff.NewExponentialBackOff()
		bf.InitialInterval = logBackoffInitial
		bf.MaxElapsedTime = 0
		bf.MaxInterval = logBackoffMax / 2
		backoffCtx := backoff.WithContext(bf, ctx)
		delay := logBackoffInitial

		for range logRetryCount {
			req, err := logger.Logs(opts.Path, podOpts)
			if err != nil {
				slog.Error("Log request failed",
					slogs.Container, opts.Info(),
					slogs.Error, err,
				)
				// Check if we should stop retrying based on pod status
				if pod, ok := logger.(*Pod); ok && pod.shouldStopRetrying(opts.Path) {
					slog.Debug("Stopping log retry - pod is terminating or deleted",
						slogs.Container, opts.Info(),
					)
					return
				}
				select {
				case <-ctx.Done():
					return
				case <-time.After(delay):
					if delay = backoffCtx.NextBackOff(); delay == backoff.Stop {
						return
					}
				}
				continue
			}

			stream, e := req.Stream(ctx)
			if e != nil {
				slog.Error("Stream logs failed",
					slogs.Error, e,
Repository: derailed/k9s
File: internal/ui/table.go (Go)

Code before:
	return t.sortCol
}

func (t *Table) setMSort(b bool) {
	t.mx.Lock()
	defer t.mx.Unlock()

	t.manualSort = b
}

func (t *Table) getMSort() bool {
	t.mx.RLock()
	defer t.mx.RUnlock()

	return t.manualSort
}

func (t *Table) getSelectedColIdx() int {
	t.mx.RLock()
	defer t.mx.RUnlock()

	return t.selectedColIdx
}

// SelectNextColumn moves the column selection to the right.
func (t *Table) SelectNextColumn() {
	data := t.GetFilteredData()
	if data == nil || data.HeaderCount() == 0 {
		return
	}

	// Count visible columns
	visibleCount := 0
	for _, h := range data.Header() {
		if !t.shouldExcludeColumn(h) {
			visibleCount++
		}
	}

	if visibleCount == 0 {
		return
	}

	t.mx.Lock()
	t.selectedColIdx++
	if t.selectedColIdx >= visibleCount {
		t.selectedColIdx = 0
	}
	t.mx.Unlock()

	t.Refresh()

Review comment (refactor):
I think this could be 'DRY' up using something like `getSortColumnIndex(up bool)` or something along this line.
Hence whether you are going up or down in the header column a single call can handle it.

More importantly, we need to honor the current sort column i.e if a sortCol is set we need to start from that index. Whether it's the default sort for a given resource or the user is using custom views we need to honor that setting and start indexing from that mark.  As it stands with custom views at play the column highlight no longer index the active sort column and we end up with a very confusing display with the sort indicator on one column and a highlight on a different column...




Code after:
	return t.sortCol
}

func (t *Table) setMSort(b bool) {
	t.mx.Lock()
	defer t.mx.Unlock()

	t.manualSort = b
}

func (t *Table) getMSort() bool {
	t.mx.RLock()
	defer t.mx.RUnlock()

	return t.manualSort
}

func (t *Table) getSelectedColIdx() int {
	t.mx.RLock()
	defer t.mx.RUnlock()

	return t.selectedColIdx
}

// initSelectedColumn initializes the selected column index based on current sort column.
func (t *Table) initSelectedColumn() {
	data := t.GetFilteredData()
	if data == nil || data.HeaderCount() == 0 {
		return
	}

	sc := t.getSortCol()
	if sc.Name == "" {
		t.mx.Lock()
		t.selectedColIdx = 0
		t.mx.Unlock()
		return
	}

	// Find the visual column index for the current sort column
	header := data.Header()
	visibleCol := 0
	for _, h := range header {
		if t.shouldExcludeColumn(h) {
			continue
		}
		if h.Name == sc.Name {
			t.mx.Lock()
			t.selectedColIdx = visibleCol
			t.mx.Unlock()
			return
Repository: dgraph-io/dgraph
File: worker/draft.go (Go)

Code before:
	stopTask := func(id op) {
		n.opsLock.Lock()
		delete(n.ops, id)
		n.opsLock.Unlock()
		glog.Infof("Operation completed with id: %s", id)

		// If we were doing any other operation, let's restart rollups.
		if id != opRollup {
			time.Sleep(10 * time.Second) // Wait for 10s to start rollup operation.
			n.startTask(opRollup)
		}
	}

	closer := y.NewCloser(1)
	switch id {
	case opRollup:
		if len(n.ops) > 0 {
			return nil, errors.Errorf("another operation is already running")
		}
		go posting.IncrRollup.Process(closer)

	case opSnapshot, opIndexing:
		for otherId, otherCloser := range n.ops {
			if otherId == opRollup {
				otherCloser.SignalAndWait()
			} else {
				return nil, errors.Errorf("operation %s is already running", otherId)
			}
		}
	default:
		glog.Errorf("Got an unhandled operation %s. Ignoring...", id)
		return nil, nil
	}

	n.ops[id] = closer
	glog.Infof("Operation started with id: %s", id)
	go func(id op, closer *y.Closer) {
		closer.Wait()
		stopTask(id)
	}(id, closer)
	return closer, nil
}

func (n *node) waitForTask(id op) {
	n.opsLock.Lock()
	closer, ok := n.ops[id]
	n.opsLock.Unlock()
	if !ok {
		return
	}
	closer.Wait()

Review comment (suggestion):
Shouldn't we pause rollup only when we know for sure there are no other operation. Let's say, 
n.ops has opRollup and opIndexing. Then opRollup will be stopped but since there is also an opIndexing, we will return from line 126 having paused opRollup. 

Code after:
	stopTask := func(id op) {
		n.opsLock.Lock()
		delete(n.ops, id)
		n.opsLock.Unlock()
		glog.Infof("Operation completed with id: %s", id)

		// If we were doing any other operation, let's restart rollups.
		if id != opRollup {
			time.Sleep(10 * time.Second) // Wait for 10s to start rollup operation.
			// If any other operation is running, this would error out. So, ignore error.
			n.startTask(opRollup)
		}
	}

	closer := y.NewCloser(1)
	switch id {
	case opRollup:
		if len(n.ops) > 0 {
			return nil, errors.Errorf("another operation is already running")
		}
		go posting.IncrRollup.Process(closer)

	case opSnapshot, opIndexing:
		for otherId, otherCloser := range n.ops {
			if otherId == opRollup {
				otherCloser.SignalAndWait()
			} else {
				return nil, errors.Errorf("operation %s is already running", otherId)
			}
		}
	default:
		glog.Errorf("Got an unhandled operation %s. Ignoring...", id)
		return nil, nil
	}

	n.ops[id] = closer
	glog.Infof("Operation started with id: %s", id)
	go func(id op, closer *y.Closer) {
		closer.Wait()
		stopTask(id)
	}(id, closer)
	return closer, nil
}

func (n *node) waitForTask(id op) {
	n.opsLock.Lock()
	closer, ok := n.ops[id]
	n.opsLock.Unlock()
	if !ok {
		return
	}
Repository: dgraph-io/dgraph
File: posting/writer_test.go (Go)

Code before:
	WithLogRotatesToFlush(10).
	WithMaxCacheSize(50) // TODO(Aman): Disable cache altogether

var db, err2 = badger.OpenManaged(dbOpts)

func BenchmarkTxnWriter(b *testing.B) {
	for i := 0; i < 50000; i++ {
		n := kv{key: []byte(string(i)), value: []byte("Check Value")}
		KVList = append(KVList, n)
	}

	w := NewTxnWriter(db)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, typ := range KVList {
			k := typ.key
			v := typ.value
			x.Check(w.SetAt(k, v, BitSchemaPosting, 1))
		}
	}

}

func BenchmarkWriteBatch(b *testing.B) {
	for i := 0; i < 50000; i++ {
		n := kv{key: []byte(string(i)), value: []byte("Check Value")}
		KVList = append(KVList, n)
	}

	batch := db.NewWriteBatchAt(1)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, typ := range KVList {
			k := typ.key
			v := typ.value
			x.Check(batch.Set(k, v))
		}
	}

}


Review comment (suggestion):
you could loop until `b.N` instead of constant value.

Code after:
	// Creates separate writer for each thread
	writeInBadgerMThreadsB := func(db *badger.DB, KVList *bpb.KVList, wg *sync.WaitGroup) {
		defer wg.Done()
		wb := db.NewManagedWriteBatch()
		if err := wb.Write(KVList); err != nil {
			panic(err)
		}
		require.NoError(b, wb.Flush())

	}

	// Resuses one writer for all threads
	writeInBadgerMThreadsW := func(wb *badger.WriteBatch, KVList *bpb.KVList, wg *sync.WaitGroup) {
		defer wg.Done()

		if err := wb.Write(KVList); err != nil {
			panic(err)
		}

	}
	// Creates separate writer for each thread
	writeInBadgerSingleThreadB := func(db *badger.DB, KVList *bpb.KVList) {
		wb := db.NewManagedWriteBatch()
		if err := wb.Write(KVList); err != nil {
			panic(err)
		}
		require.NoError(b, wb.Flush())

	}
	// Resuses one writer for all threads
	writeInBadgerSingleThreadW := func(wb *badger.WriteBatch, KVList *bpb.KVList) {
		if err := wb.Write(KVList); err != nil {
			panic(err)
		}

	}

	dbOpts := badger.DefaultOptions("").
		WithLogger(nil).
		WithSyncWrites(false).
		WithNumVersionsToKeep(math.MaxInt64).
		WithCompression(options.None)

	KVList := createKVList()

	// Vanilla TxnWriter
	b.Run("TxnWriter", func(b *testing.B) {
		tmpIndexDir, err := ioutil.TempDir("", "dgraph")
		require.NoError(b, err)
		defer os.RemoveAll(tmpIndexDir)
Repository: dgraph-io/dgraph
File: posting/writer_test.go (Go)

Code before:

var tmpIndexDir, err = ioutil.TempDir("", "dgraph_index_")

var dbOpts = badger.DefaultOptions(tmpIndexDir).
	WithSyncWrites(false).
	WithNumVersionsToKeep(math.MaxInt64).
	WithLogger(&x.ToGlog{}).
	WithCompression(options.None).
	WithEventLogging(false).
	WithLogRotatesToFlush(10).
	WithMaxCacheSize(50) // TODO(Aman): Disable cache altogether

var db, err2 = badger.OpenManaged(dbOpts)

func createKVList() []kv {
	var KVList = []kv{}
	for i := 0; i < 50000; i++ {
		n := kv{key: []byte(string(i)), value: []byte("Check Value")}
		KVList = append(KVList, n)
	}
	return KVList
}

func BenchmarkTxnWriter(b *testing.B) {
	KVList := createKVList()
	w := NewTxnWriter(db)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, typ := range KVList {
			k := typ.key
			v := typ.value
			x.Check(w.SetAt(k, v, BitSchemaPosting, 1))
		}
		if err := w.Flush(); err != nil {
			fmt.Printf("Got error while flushing txnwriter: %v\n", err)
		}
	}

}

func BenchmarkWriteBatch(b *testing.B) {
	KVList := createKVList()
	batch := db.NewWriteBatchAt(1)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, typ := range KVList {
			k := typ.key
			v := typ.value
			x.Check(batch.Set(k, v))
		}
		if err := batch.Flush(); err != nil {

Review comment (suggestion):
This writer should be created in the `for loop`. You would get an error on using this txn writer after calling flush.

Code after:
func BenchmarkWriter(b *testing.B) {
	createKVList := func() bpb.KVList {
		var KVList bpb.KVList
		for i := 0; i < 5000000; i++ {
			n := &bpb.KV{Key: []byte(string(i)), Value: val, Version: 5}
			KVList.Kv = append(KVList.Kv, n)
		}
		return KVList
	}

	// Creates separate writer for each thread
	writeInBadgerMThreadsB := func(db *badger.DB, KVList *bpb.KVList, wg *sync.WaitGroup) {
		defer wg.Done()
		wb := db.NewManagedWriteBatch()
		if err := wb.Write(KVList); err != nil {
			panic(err)
		}
		require.NoError(b, wb.Flush())

	}

	// Resuses one writer for all threads
	writeInBadgerMThreadsW := func(wb *badger.WriteBatch, KVList *bpb.KVList, wg *sync.WaitGroup) {
		defer wg.Done()

		if err := wb.Write(KVList); err != nil {
			panic(err)
		}

	}
	// Creates separate writer for each thread
	writeInBadgerSingleThreadB := func(db *badger.DB, KVList *bpb.KVList) {
		wb := db.NewManagedWriteBatch()
		if err := wb.Write(KVList); err != nil {
			panic(err)
		}
		require.NoError(b, wb.Flush())

	}
	// Resuses one writer for all threads
	writeInBadgerSingleThreadW := func(wb *badger.WriteBatch, KVList *bpb.KVList) {
		if err := wb.Write(KVList); err != nil {
			panic(err)
		}

	}

	dbOpts := badger.DefaultOptions("").
		WithLogger(nil).
		WithSyncWrites(false).
		WithNumVersionsToKeep(math.MaxInt64).
Repository: dgraph-io/dgraph
File: posting/writer_test.go (Go)

Code before:
	w := NewTxnWriter(db)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, typ := range KVList {
			k := typ.key
			v := typ.value
			x.Check(w.SetAt(k, v, BitSchemaPosting, 1))
		}
		if err := w.Flush(); err != nil {
			fmt.Printf("Got error while flushing txnwriter: %v\n", err)
		}
	}

}

func BenchmarkWriteBatch(b *testing.B) {
	KVList := createKVList()
	batch := db.NewWriteBatchAt(1)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, typ := range KVList {
			k := typ.key
			v := typ.value
			x.Check(batch.Set(k, v))
		}
		if err := batch.Flush(); err != nil {
			fmt.Printf("Got error while flushing batch: %v\n", err)
		}
	}

}


Review comment (performance):
When you call flush, we commit the current txn https://github.com/dgraph-io/badger/blob/4b539b98851fd2fb32683098cfe23f172c437a3f/batch.go#L155 .

So the next call to `batch.Set` would try to insert the entry in the discard txn. The error is expected.

Code after:
		if err := wb.Write(KVList); err != nil {
			panic(err)
		}

	}
	// Creates separate writer for each thread
	writeInBadgerSingleThreadB := func(db *badger.DB, KVList *bpb.KVList) {
		wb := db.NewManagedWriteBatch()
		if err := wb.Write(KVList); err != nil {
			panic(err)
		}
		require.NoError(b, wb.Flush())

	}
	// Resuses one writer for all threads
	writeInBadgerSingleThreadW := func(wb *badger.WriteBatch, KVList *bpb.KVList) {
		if err := wb.Write(KVList); err != nil {
			panic(err)
		}

	}

	dbOpts := badger.DefaultOptions("").
		WithLogger(nil).
		WithSyncWrites(false).
		WithNumVersionsToKeep(math.MaxInt64).
		WithCompression(options.None)

	KVList := createKVList()

	// Vanilla TxnWriter
	b.Run("TxnWriter", func(b *testing.B) {
		tmpIndexDir, err := ioutil.TempDir("", "dgraph")
		require.NoError(b, err)
		defer os.RemoveAll(tmpIndexDir)

		dbOpts.Dir = tmpIndexDir
		dbOpts.ValueDir = tmpIndexDir
		var db, err2 = badger.OpenManaged(dbOpts)
		require.NoError(b, err2)
		defer db.Close()

		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			w := NewTxnWriter(db)
			for _, typ := range KVList.Kv {
				k := typ.Key
				v := typ.Value
				err := w.SetAt(k, v, BitSchemaPosting, 1)
				require.NoError(b, err)
			}
Repository: dgraph-io/dgraph
File: posting/writer_test.go (Go)

Code before:

package posting

import (
	"fmt"
	"io/ioutil"
	"math"
	"testing"

	"github.com/dgraph-io/badger/v2"
	"github.com/dgraph-io/badger/v2/options"
	"github.com/dgraph-io/dgraph/x"
)

type kv struct {
	key   []byte
	value []byte
}

var tmpIndexDir, err = ioutil.TempDir("", "dgraph_index_")

var dbOpts = badger.DefaultOptions(tmpIndexDir).
	WithSyncWrites(false).
	WithNumVersionsToKeep(math.MaxInt64).
	WithLogger(&x.ToGlog{}).
	WithCompression(options.None).
	WithEventLogging(false).
	WithLogRotatesToFlush(10).
	WithMaxCacheSize(50) // TODO(Aman): Disable cache altogether

var db, err2 = badger.OpenManaged(dbOpts)

func createKVList() []kv {
	var KVList = []kv{}
	for i := 0; i < 50000; i++ {
		n := kv{key: []byte(string(i)), value: []byte("Check Value")}
		KVList = append(KVList, n)
	}
	return KVList
}

func BenchmarkTxnWriter(b *testing.B) {
	KVList := createKVList()
	w := NewTxnWriter(db)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		for _, typ := range KVList {
			k := typ.key
			v := typ.value
			x.Check(w.SetAt(k, v, BitSchemaPosting, 1))
		}

Review comment (suggestion):
You can remove all the badger options from this line onwards. We don't need them. The defaults should be fine.

Code after:

package posting

import (
	"io/ioutil"
	"math"
	"os"
	"sync"
	"testing"

	"github.com/dgraph-io/badger/v2"
	"github.com/dgraph-io/badger/v2/options"
	bpb "github.com/dgraph-io/badger/v2/pb"
	"github.com/stretchr/testify/require"
)

var val = make([]byte, 128)

func BenchmarkWriter(b *testing.B) {
	createKVList := func() bpb.KVList {
		var KVList bpb.KVList
		for i := 0; i < 5000000; i++ {
			n := &bpb.KV{Key: []byte(string(i)), Value: val, Version: 5}
			KVList.Kv = append(KVList.Kv, n)
		}
		return KVList
	}

	// Creates separate writer for each thread
	writeInBadgerMThreadsB := func(db *badger.DB, KVList *bpb.KVList, wg *sync.WaitGroup) {
		defer wg.Done()
		wb := db.NewManagedWriteBatch()
		if err := wb.Write(KVList); err != nil {
			panic(err)
		}
		require.NoError(b, wb.Flush())

	}

	// Resuses one writer for all threads
	writeInBadgerMThreadsW := func(wb *badger.WriteBatch, KVList *bpb.KVList, wg *sync.WaitGroup) {
		defer wg.Done()

		if err := wb.Write(KVList); err != nil {
			panic(err)
		}

	}
	// Creates separate writer for each thread
	writeInBadgerSingleThreadB := func(db *badger.DB, KVList *bpb.KVList) {
		wb := db.NewManagedWriteBatch()