BadgerのErrTxnTooBigについて

はじめに

badgerのREADMERead-write transactions に Badger の ErrTxnTooBig について以下のような説明がありました。

An ErrTxnTooBig will be reported in case the number of pending writes/deletes in the transaction exceeds a certain limit. In that case, it is best to commit the transaction and start a new transaction immediately. Here is an example (we are not checking for errors in some places for simplicity):

updates := make(map[string]string)
txn := db.NewTransaction(true)
for k,v := range updates {
  if err := txn.Set([]byte(k),[]byte(v)); err == badger.ErrTxnTooBig {
    _ = txn.Commit()
    txn = db.NewTransaction(true)
    _ = txn.Set([]byte(k),[]byte(v))
  }
}
_ = txn.Commit()

実際のところどれぐらいの大きさで ErrTxnTooBig が出るのか気になったのでコードを読んでみました。

ErrTxnTooBig を返している個所

2 箇所ありました。

その 1: DBsendToWriteCh メソッド内。 db.go#L735-L742

  var count, size int64
  for _, e := range entries {
    size += int64(e.estimateSize(db.opt.ValueThreshold))
    count++
  }
  if count >= db.opt.maxBatchCount || size >= db.opt.maxBatchSize {
    return nil, ErrTxnTooBig
  }

その 2: TxncheckSize メソッド内。 txn.go#L295-L304

func (txn *Txn) checkSize(e *Entry) error {
  count := txn.count + 1
  // Extra bytes for the version in key.
  size := txn.size + int64(e.estimateSize(txn.db.opt.ValueThreshold)) + 10
  if count >= txn.db.opt.maxBatchCount || size >= txn.db.opt.maxBatchSize {
    return ErrTxnTooBig
  }
  txn.count, txn.size = count, size
  return nil
}

db.optmaxBatchCountmaxBatchSize

Options 構造体(抜粋) options.go#L95-L98

  // 4. Flags for testing purposes
  // ------------------------------
  maxBatchCount int64 // max entries in batch
  maxBatchSize  int64 // max batch size in bytes

設定箇所は Open 関数内にありました。 db.go#L195-L196

  opt.maxBatchSize = (15 * opt.MaxTableSize) / 100
  opt.maxBatchCount = opt.maxBatchSize / int64(skl.MaxNodeSize)

skl.MaxNodeSize は定数で Visual Studio Code によると 96 です。 skl/skl.go#L49-L50

// MaxNodeSize is the memory footprint of a node of maximum height.
const MaxNodeSize = int(unsafe.Sizeof(node{}))

DefaultOptions 関数内を見ると MaxTableSize のデフォルト値は 64MiB です。 options.go#L114

    MaxTableSize:            64 << 20,

これから計算すると opt.maxBatchSize は 9.6MiB です。

>>> 15 * 64 / 100.0
9.6

opt.maxBatchCount9.6 / 96 で 0.1Mi = 102.4Ki = 104,857 です。