github.com/klaytn/klaytn@v1.12.1/storage/database/leveldb_bench_multidisks_test.go (about)

     1  // Copyright 2018 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  //go:build multidisktest
    17  // +build multidisktest
    18  
    19  package database
    20  
    21  import (
    22  	"math/rand"
    23  	"os"
    24  	"sync"
    25  	"testing"
    26  	"time"
    27  )
    28  
    29  type multiDiskOption struct {
    30  	numDisks  int
    31  	numShards int
    32  	numRows   int
    33  	numBytes  int
    34  }
    35  
    36  // adjust diskPaths according to your setting
    37  var diskPaths = [...]string{"", "/disk1", "/disk2", "/disk3", "/disk4", "/disk5", "/disk6", "/disk7"}
    38  
    39  func genDirForMDPTest(b *testing.B, numDisks, numShards int) []string {
    40  	if numDisks > len(diskPaths) {
    41  		b.Fatalf("entered numDisks %v is larger than diskPaths %v", numDisks, len(diskPaths))
    42  	}
    43  
    44  	dirs := make([]string, numShards, numShards)
    45  	for i := 0; i < numShards; i++ {
    46  		diskNum := i % numDisks
    47  		dir, err := os.MkdirTemp(diskPaths[diskNum], "klaytn-db-bench-mdp")
    48  		if err != nil {
    49  			b.Fatalf("cannot create temporary directory: %v", err)
    50  		}
    51  		dirs[i] = dir
    52  	}
    53  	return dirs
    54  }
    55  
    56  func benchmark_MDP_Put_GoRoutine(b *testing.B, mdo *multiDiskOption) {
    57  	b.StopTimer()
    58  
    59  	dirs := genDirForMDPTest(b, mdo.numDisks, mdo.numShards)
    60  	defer removeDirs(dirs)
    61  
    62  	opts := getKlayLDBOptions()
    63  	databases := genDatabases(b, dirs, opts)
    64  	defer closeDBs(databases)
    65  
    66  	for i := 0; i < b.N; i++ {
    67  		b.StopTimer()
    68  		keys, values := genKeysAndValues(mdo.numBytes, mdo.numRows)
    69  		b.StartTimer()
    70  
    71  		var wait sync.WaitGroup
    72  		wait.Add(mdo.numRows)
    73  
    74  		for k := 0; k < mdo.numRows; k++ {
    75  			shard := getShardForTest(keys, k, mdo.numShards)
    76  			db := databases[shard]
    77  
    78  			go func(currDB Database, idx int) {
    79  				defer wait.Done()
    80  				currDB.Put(keys[idx], values[idx])
    81  			}(db, k)
    82  		}
    83  		wait.Wait()
    84  	}
    85  }
    86  
    87  func benchmark_MDP_Put_NoGoRoutine(b *testing.B, mdo *multiDiskOption) {
    88  	b.StopTimer()
    89  
    90  	numDisks := mdo.numDisks
    91  	numBytes := mdo.numBytes
    92  	numRows := mdo.numRows
    93  	numShards := mdo.numShards
    94  
    95  	dirs := genDirForMDPTest(b, numDisks, numShards)
    96  	defer removeDirs(dirs)
    97  
    98  	opts := getKlayLDBOptions()
    99  	databases := genDatabases(b, dirs, opts)
   100  	defer closeDBs(databases)
   101  
   102  	for i := 0; i < b.N; i++ {
   103  		b.StopTimer()
   104  		keys, values := genKeysAndValues(numBytes, numRows)
   105  		b.StartTimer()
   106  
   107  		for k := 0; k < numRows; k++ {
   108  			shard := getShardForTest(keys, k, mdo.numShards)
   109  			db := databases[shard]
   110  			db.Put(keys[k], values[k])
   111  		}
   112  	}
   113  }
   114  
   115  // please change below rowSize to change the size of an input row for MDP_Put tests (GoRoutine & NoGoRoutine)
   116  const (
   117  	rowSizePutMDP = 250
   118  	numRowsPutMDP = 1000 * 10
   119  )
   120  
   121  var putMDPBenchmarks = [...]struct {
   122  	name string
   123  	mdo  multiDiskOption
   124  }{
   125  	// 10k Rows, 250 bytes, 1 disk, different number of shards
   126  	{"10k_1D_1P_250", multiDiskOption{1, 1, numRowsPutMDP, rowSizePutMDP}},
   127  	{"10k_1D_2P_250", multiDiskOption{1, 2, numRowsPutMDP, rowSizePutMDP}},
   128  	{"10k_1D_4P_250", multiDiskOption{1, 4, numRowsPutMDP, rowSizePutMDP}},
   129  	{"10k_1D_8P_250", multiDiskOption{1, 8, numRowsPutMDP, rowSizePutMDP}},
   130  
   131  	// 10k Rows, 250 bytes, 8 shards (fixed), different number of disks
   132  	{"10k_1D_8P_250", multiDiskOption{1, 8, numRowsPutMDP, rowSizePutMDP}},
   133  	{"10k_2D_8P_250", multiDiskOption{2, 8, numRowsPutMDP, rowSizePutMDP}},
   134  	{"10k_4D_8P_250", multiDiskOption{4, 8, numRowsPutMDP, rowSizePutMDP}},
   135  	{"10k_8D_8P_250", multiDiskOption{8, 8, numRowsPutMDP, rowSizePutMDP}},
   136  
   137  	// 10k Rows, 250 bytes, different number of disks & shards
   138  	{"10k_1D_1P_250", multiDiskOption{1, 1, numRowsPutMDP, rowSizePutMDP}},
   139  	{"10k_2D_2P_250", multiDiskOption{2, 2, numRowsPutMDP, rowSizePutMDP}},
   140  	{"10k_4D_4P_250", multiDiskOption{4, 4, numRowsPutMDP, rowSizePutMDP}},
   141  	{"10k_8D_8P_250", multiDiskOption{8, 8, numRowsPutMDP, rowSizePutMDP}},
   142  }
   143  
   144  func Benchmark_MDP_Put_GoRoutine(b *testing.B) {
   145  	for _, bm := range putMDPBenchmarks {
   146  		b.Run(bm.name, func(b *testing.B) {
   147  			benchmark_MDP_Put_GoRoutine(b, &bm.mdo)
   148  		})
   149  	}
   150  }
   151  
   152  func Benchmark_MDP_Put_NoGoRoutine(b *testing.B) {
   153  	for _, bm := range putMDPBenchmarks {
   154  		b.Run(bm.name, func(b *testing.B) {
   155  			benchmark_MDP_Put_NoGoRoutine(b, &bm.mdo)
   156  		})
   157  	}
   158  }
   159  
   160  func benchmark_MDP_Batch_GoRoutine(b *testing.B, mdo *multiDiskOption) {
   161  	b.StopTimer()
   162  
   163  	numDisks := mdo.numDisks
   164  	numBytes := mdo.numBytes
   165  	numRows := mdo.numRows
   166  	numShards := mdo.numShards
   167  
   168  	dirs := genDirForMDPTest(b, numDisks, numShards)
   169  	defer removeDirs(dirs)
   170  
   171  	opts := getKlayLDBOptions()
   172  	databases := genDatabases(b, dirs, opts)
   173  	defer closeDBs(databases)
   174  
   175  	zeroSizeBatch := 0
   176  	batchSizeSum := 0
   177  	numBatches := 0
   178  	for i := 0; i < b.N; i++ {
   179  		b.StopTimer()
   180  		// make same number of batches as numShards
   181  		batches := make([]Batch, numShards, numShards)
   182  		for k := 0; k < numShards; k++ {
   183  			batches[k] = databases[k].NewBatch()
   184  		}
   185  		keys, values := genKeysAndValues(numBytes, numRows)
   186  		b.StartTimer()
   187  		for k := 0; k < numRows; k++ {
   188  			shard := getShardForTest(keys, k, numShards)
   189  			batches[shard].Put(keys[k], values[k])
   190  		}
   191  
   192  		for _, batch := range batches {
   193  			if batch.ValueSize() == 0 {
   194  				zeroSizeBatch++
   195  			}
   196  			batchSizeSum += batch.ValueSize()
   197  			numBatches++
   198  		}
   199  		var wait sync.WaitGroup
   200  		wait.Add(numShards)
   201  		for _, batch := range batches {
   202  			go func(currBatch Batch) {
   203  				defer wait.Done()
   204  				currBatch.Write()
   205  			}(batch)
   206  		}
   207  		wait.Wait()
   208  	}
   209  
   210  	if zeroSizeBatch != 0 {
   211  		b.Log("zeroSizeBatch: ", zeroSizeBatch)
   212  	}
   213  }
   214  
   215  func benchmark_MDP_Batch_NoGoRoutine(b *testing.B, mdo *multiDiskOption) {
   216  	b.StopTimer()
   217  
   218  	numDisks := mdo.numDisks
   219  	numBytes := mdo.numBytes
   220  	numRows := mdo.numRows
   221  	numShards := mdo.numShards
   222  
   223  	dirs := genDirForMDPTest(b, numDisks, numShards)
   224  	defer removeDirs(dirs)
   225  
   226  	opts := getKlayLDBOptions()
   227  	databases := genDatabases(b, dirs, opts)
   228  	defer closeDBs(databases)
   229  
   230  	zeroSizeBatch := 0
   231  	batchSizeSum := 0
   232  	numBatches := 0
   233  	for i := 0; i < b.N; i++ {
   234  		b.StopTimer()
   235  		// make same number of batches as numShards
   236  		batches := make([]Batch, numShards, numShards)
   237  		for k := 0; k < numShards; k++ {
   238  			batches[k] = databases[k].NewBatch()
   239  		}
   240  		keys, values := genKeysAndValues(numBytes, numRows)
   241  		b.StartTimer()
   242  		for k := 0; k < numRows; k++ {
   243  			shard := getShardForTest(keys, k, numShards)
   244  			batches[shard].Put(keys[k], values[k])
   245  		}
   246  
   247  		for _, batch := range batches {
   248  			if batch.ValueSize() == 0 {
   249  				zeroSizeBatch++
   250  			}
   251  			batchSizeSum += batch.ValueSize()
   252  			numBatches++
   253  		}
   254  
   255  		for _, batch := range batches {
   256  			batch.Write()
   257  		}
   258  
   259  	}
   260  
   261  	if zeroSizeBatch != 0 {
   262  		b.Log("zeroSizeBatch: ", zeroSizeBatch)
   263  	}
   264  }
   265  
   266  // please change below rowSize to change the size of an input row for MDP_Batch tests (GoRoutine & NoGoRoutine)
   267  const (
   268  	rowSizeBatchMDP = 250
   269  	numRowsBatchMDP = 1000 * 10
   270  )
   271  
   272  var batchMDPBenchmarks = [...]struct {
   273  	name string
   274  	mdo  multiDiskOption
   275  }{
   276  	// 10k Rows, 250 bytes, 1 disk, different number of shards
   277  	{"10k_1D_1P_250", multiDiskOption{1, 1, numRowsBatchMDP, rowSizeBatchMDP}},
   278  	{"10k_1D_2P_250", multiDiskOption{1, 2, numRowsBatchMDP, rowSizeBatchMDP}},
   279  	{"10k_1D_4P_250", multiDiskOption{1, 4, numRowsBatchMDP, rowSizeBatchMDP}},
   280  	{"10k_1D_8P_250", multiDiskOption{1, 8, numRowsBatchMDP, rowSizeBatchMDP}},
   281  
   282  	// 10k Rows, 250 bytes, 8 shards (fixed), different number of disks
   283  	{"10k_1D_8P_250", multiDiskOption{1, 8, numRowsBatchMDP, rowSizeBatchMDP}},
   284  	{"10k_2D_8P_250", multiDiskOption{2, 8, numRowsBatchMDP, rowSizeBatchMDP}},
   285  	{"10k_4D_8P_250", multiDiskOption{4, 8, numRowsBatchMDP, rowSizeBatchMDP}},
   286  	{"10k_8D_8P_250", multiDiskOption{8, 8, numRowsBatchMDP, rowSizeBatchMDP}},
   287  
   288  	// 10k Rows, 250 bytes, different number of disks & shards
   289  	{"10k_1D_1P_250", multiDiskOption{1, 1, numRowsBatchMDP, rowSizeBatchMDP}},
   290  	{"10k_2D_2P_250", multiDiskOption{2, 2, numRowsBatchMDP, rowSizeBatchMDP}},
   291  	{"10k_4D_4P_250", multiDiskOption{4, 4, numRowsBatchMDP, rowSizeBatchMDP}},
   292  	{"10k_8D_8P_250", multiDiskOption{8, 8, numRowsBatchMDP, rowSizeBatchMDP}},
   293  }
   294  
   295  func Benchmark_MDP_Batch_GoRoutine(b *testing.B) {
   296  	for _, bm := range batchMDPBenchmarks {
   297  		b.Run(bm.name, func(b *testing.B) {
   298  			benchmark_MDP_Batch_GoRoutine(b, &bm.mdo)
   299  		})
   300  	}
   301  }
   302  
   303  func Benchmark_MDP_Batch_NoGoRoutine(b *testing.B) {
   304  	for _, bm := range batchMDPBenchmarks {
   305  		b.Run(bm.name, func(b *testing.B) {
   306  			benchmark_MDP_Batch_NoGoRoutine(b, &bm.mdo)
   307  		})
   308  	}
   309  }
   310  
   311  func benchmark_MDP_Get_NoGoRotine(b *testing.B, mdo *multiDiskOption, numReads int, readType func(int, int) int) {
   312  	b.StopTimer()
   313  
   314  	numDisks := mdo.numDisks
   315  	numBytes := mdo.numBytes
   316  	numRows := mdo.numRows
   317  	numShards := mdo.numShards
   318  
   319  	dirs := genDirForMDPTest(b, numDisks, numShards)
   320  	defer removeDirs(dirs)
   321  
   322  	opts := getKlayLDBOptions()
   323  	databases := genDatabases(b, dirs, opts)
   324  	defer closeDBs(databases)
   325  
   326  	for i := 0; i < b.N; i++ {
   327  		b.StopTimer()
   328  
   329  		keys, values := genKeysAndValues(numBytes, numRows)
   330  
   331  		for k := 0; k < numRows; k++ {
   332  			shard := getShardForTest(keys, k, numShards)
   333  			db := databases[shard]
   334  			db.Put(keys[k], values[k])
   335  		}
   336  
   337  		b.StartTimer()
   338  		for k := 0; k < numReads; k++ {
   339  			keyPos := readType(k, numRows)
   340  			if keyPos >= len(keys) {
   341  				b.Fatal("index out of range", keyPos)
   342  			}
   343  			shard := getShardForTest(keys, k, numShards)
   344  			db := databases[shard]
   345  			db.Get(keys[keyPos])
   346  		}
   347  	}
   348  }
   349  
   350  func benchmark_MDP_Get_GoRoutine(b *testing.B, mdo *multiDiskOption, numReads int, readType func(int, int) int) {
   351  	b.StopTimer()
   352  
   353  	numDisks := mdo.numDisks
   354  	numBytes := mdo.numBytes
   355  	numRows := mdo.numRows
   356  	numShards := mdo.numShards
   357  
   358  	dirs := genDirForMDPTest(b, numDisks, numShards)
   359  	defer removeDirs(dirs)
   360  
   361  	opts := getKlayLDBOptions()
   362  	databases := genDatabases(b, dirs, opts)
   363  	defer closeDBs(databases)
   364  
   365  	for i := 0; i < b.N; i++ {
   366  		b.StopTimer()
   367  
   368  		keys, values := genKeysAndValues(numBytes, numRows)
   369  
   370  		for k := 0; k < numRows; k++ {
   371  			shard := getShardForTest(keys, k, numShards)
   372  			db := databases[shard]
   373  			db.Put(keys[k], values[k])
   374  		}
   375  
   376  		b.StartTimer()
   377  		var wg sync.WaitGroup
   378  		wg.Add(numReads)
   379  		for k := 0; k < numReads; k++ {
   380  			keyPos := readType(k, numRows)
   381  			if keyPos >= len(keys) {
   382  				b.Fatalf("index out of range: keyPos: %v, k: %v, numRows: %v", keyPos, k, numRows)
   383  			}
   384  
   385  			shard := getShardForTest(keys, keyPos, numShards)
   386  			db := databases[shard]
   387  
   388  			go func(currDB Database, kPos int) {
   389  				defer wg.Done()
   390  				_, err := currDB.Get(keys[kPos])
   391  				if err != nil {
   392  					b.Fatalf("get failed: %v", err)
   393  				}
   394  			}(db, keyPos)
   395  
   396  		}
   397  		wg.Wait()
   398  	}
   399  }
   400  
   401  // please change below rowSize to change the size of an input row for MDP_Get tests (GoRoutine & NoGoRoutine)
   402  const rowSizeGetMDP = 250
   403  
   404  const (
   405  	insertedRowsBeforeGetMDP = 1000 * 100 // pre-insertion size before read
   406  	numReadsMDP              = 1000
   407  )
   408  
   409  var getMDPBenchmarks = [...]struct {
   410  	name     string
   411  	mdo      multiDiskOption
   412  	numReads int
   413  }{
   414  	// 10k Rows, 250 bytes, 1 disk, different number of shards
   415  	{"10k_1D_1P_250", multiDiskOption{1, 1, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   416  	{"10k_1D_2P_250", multiDiskOption{1, 2, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   417  	{"10k_1D_4P_250", multiDiskOption{1, 4, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   418  	{"10k_1D_8P_250", multiDiskOption{1, 8, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   419  
   420  	// 10k Rows, 250 bytes, 8 shards (fixed), different number of disks
   421  	{"10k_1D_8P_250", multiDiskOption{1, 8, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   422  	{"10k_2D_8P_250", multiDiskOption{2, 8, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   423  	{"10k_4D_8P_250", multiDiskOption{4, 8, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   424  	{"10k_8D_8P_250", multiDiskOption{8, 8, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   425  
   426  	// 10k Rows, 250 bytes, different number of disks & shards
   427  	{"10k_1D_1P_250", multiDiskOption{1, 1, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   428  	{"10k_2D_2P_250", multiDiskOption{2, 2, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   429  	{"10k_4D_4P_250", multiDiskOption{4, 4, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   430  	{"10k_8D_8P_250", multiDiskOption{8, 8, insertedRowsBeforeGetMDP, rowSizeGetMDP}, numReadsMDP},
   431  }
   432  
   433  func Benchmark_MDP_Get_Random_1kRows_GoRoutine(b *testing.B) {
   434  	for _, bm := range getMDPBenchmarks {
   435  		b.Run(bm.name, func(b *testing.B) {
   436  			benchmark_MDP_Get_GoRoutine(b, &bm.mdo, bm.numReads, randomRead)
   437  		})
   438  	}
   439  }
   440  
   441  func Benchmark_MDP_Get_Random_1kRows_NoGoRoutine(b *testing.B) {
   442  	for _, bm := range getMDPBenchmarks {
   443  		b.Run(bm.name, func(b *testing.B) {
   444  			benchmark_MDP_Get_NoGoRotine(b, &bm.mdo, bm.numReads, randomRead)
   445  		})
   446  	}
   447  }
   448  
   449  func Benchmark_MDP_Parallel_Get(b *testing.B) {
   450  	for _, bm := range getMDPBenchmarks {
   451  		b.Run(bm.name, func(b *testing.B) {
   452  			b.StopTimer()
   453  			mdo := bm.mdo
   454  			numDisks := mdo.numDisks
   455  			numBytes := mdo.numBytes
   456  			numRows := mdo.numRows
   457  			numShards := mdo.numShards
   458  
   459  			dirs := genDirForMDPTest(b, numDisks, numShards)
   460  			defer removeDirs(dirs)
   461  
   462  			opts := getKlayLDBOptions()
   463  			databases := genDatabases(b, dirs, opts)
   464  			defer closeDBs(databases)
   465  
   466  			keys, values := genKeysAndValues(numBytes, numRows)
   467  
   468  			for k := 0; k < numRows; k++ {
   469  				shard := getShardForTest(keys, k, numShards)
   470  				db := databases[shard]
   471  				db.Put(keys[k], values[k])
   472  			}
   473  
   474  			rand.Seed(time.Now().UnixNano())
   475  			b.StartTimer()
   476  			b.RunParallel(func(pb *testing.PB) {
   477  				for pb.Next() {
   478  					idx := rand.Intn(numRows)
   479  					shard := getShardForTest(keys, idx, numShards)
   480  					_, err := databases[shard].Get(keys[idx])
   481  					if err != nil {
   482  						b.Fatalf("get failed: %v", err)
   483  					}
   484  				}
   485  			})
   486  		})
   487  	}
   488  }
   489  
   490  func Benchmark_MDP_Parallel_Put(b *testing.B) {
   491  	for _, bm := range putMDPBenchmarks {
   492  		b.Run(bm.name, func(b *testing.B) {
   493  			b.StopTimer()
   494  			mdo := bm.mdo
   495  			numDisks := mdo.numDisks
   496  			numBytes := mdo.numBytes
   497  			numRows := mdo.numRows * 10 // extend candidate keys and values for randomness
   498  			numShards := mdo.numShards
   499  
   500  			dirs := genDirForMDPTest(b, numDisks, numShards)
   501  			defer removeDirs(dirs)
   502  
   503  			opts := getKlayLDBOptions()
   504  			databases := genDatabases(b, dirs, opts)
   505  			defer closeDBs(databases)
   506  
   507  			keys, values := genKeysAndValues(numBytes, numRows)
   508  
   509  			rand.Seed(time.Now().UnixNano())
   510  			b.StartTimer()
   511  			b.RunParallel(func(pb *testing.PB) {
   512  				for pb.Next() {
   513  					idx := rand.Intn(numRows)
   514  					shard := getShardForTest(keys, idx, numShards)
   515  					db := databases[shard]
   516  					db.Put(keys[idx], values[idx])
   517  				}
   518  			})
   519  		})
   520  	}
   521  }
   522  
   523  const parallelBatchSizeMDP = 100
   524  
   525  func Benchmark_MDP_Parallel_Batch(b *testing.B) {
   526  	for _, bm := range batchMDPBenchmarks {
   527  		b.Run(bm.name, func(b *testing.B) {
   528  			b.StopTimer()
   529  			mdo := bm.mdo
   530  			numDisks := mdo.numDisks
   531  			numBytes := mdo.numBytes
   532  			numRows := mdo.numRows * 10 // extend candidate keys and values for randomness
   533  			numShards := mdo.numShards
   534  
   535  			dirs := genDirForMDPTest(b, numDisks, numShards)
   536  			defer removeDirs(dirs)
   537  
   538  			opts := getKlayLDBOptions()
   539  			databases := genDatabases(b, dirs, opts)
   540  			defer closeDBs(databases)
   541  
   542  			keys, values := genKeysAndValues(numBytes, numRows)
   543  
   544  			rand.Seed(time.Now().UnixNano())
   545  			b.StartTimer()
   546  			b.RunParallel(func(pb *testing.PB) {
   547  				for pb.Next() {
   548  					shard := rand.Intn(numShards)
   549  					batch := databases[shard].NewBatch()
   550  					for k := 0; k < parallelBatchSizeMDP; k++ {
   551  						idx := rand.Intn(numRows)
   552  						batch.Put(keys[idx], values[idx])
   553  					}
   554  					batch.Write()
   555  				}
   556  			})
   557  		})
   558  	}
   559  }
   560  
   561  // TODO-Klaytn: MAKE PRE-LOADED TEST FOR BATCH, PUT