github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ccl/backupccl/bench_test.go (about)

     1  // Copyright 2016 The Cockroach Authors.
     2  //
     3  // Licensed as a CockroachDB Enterprise file under the Cockroach Community
     4  // License (the "License"); you may not use this file except in compliance with
     5  // the License. You may obtain a copy of the License at
     6  //
     7  //     https://github.com/cockroachdb/cockroach/blob/master/licenses/CCL.txt
     8  
     9  package backupccl_test
    10  
    11  import (
    12  	"bytes"
    13  	gosql "database/sql"
    14  	"fmt"
    15  	"io"
    16  	"path/filepath"
    17  	"strings"
    18  	"testing"
    19  
    20  	"github.com/cockroachdb/cockroach/pkg/ccl/importccl"
    21  	"github.com/cockroachdb/cockroach/pkg/ccl/utilccl/sampledataccl"
    22  	"github.com/cockroachdb/cockroach/pkg/util/hlc"
    23  	"github.com/cockroachdb/cockroach/pkg/workload/bank"
    24  	"github.com/cockroachdb/cockroach/pkg/workload/workloadsql"
    25  )
    26  
    27  func bankBuf(numAccounts int) *bytes.Buffer {
    28  	bankData := bank.FromRows(numAccounts).Tables()[0]
    29  	var buf bytes.Buffer
    30  	fmt.Fprintf(&buf, "CREATE TABLE %s %s;\n", bankData.Name, bankData.Schema)
    31  	for rowIdx := 0; rowIdx < bankData.InitialRows.NumBatches; rowIdx++ {
    32  		for _, row := range bankData.InitialRows.BatchRows(rowIdx) {
    33  			rowBatch := strings.Join(workloadsql.StringTuple(row), `,`)
    34  			fmt.Fprintf(&buf, "INSERT INTO %s VALUES (%s);\n", bankData.Name, rowBatch)
    35  		}
    36  	}
    37  	return &buf
    38  }
    39  
    40  func BenchmarkClusterBackup(b *testing.B) {
    41  	if testing.Short() {
    42  		b.Skip("TODO: fix benchmark")
    43  	}
    44  	// NB: This benchmark takes liberties in how b.N is used compared to the go
    45  	// documentation's description. We're getting useful information out of it,
    46  	// but this is not a pattern to cargo-cult.
    47  
    48  	_, _, sqlDB, dir, cleanupFn := backupRestoreTestSetup(b, multiNode, 0, initNone)
    49  	defer cleanupFn()
    50  	sqlDB.Exec(b, `DROP TABLE data.bank`)
    51  
    52  	bankData := bank.FromRows(b.N).Tables()[0]
    53  	loadDir := filepath.Join(dir, "load")
    54  	if _, err := sampledataccl.ToBackup(b, bankData, loadDir); err != nil {
    55  		b.Fatalf("%+v", err)
    56  	}
    57  	sqlDB.Exec(b, fmt.Sprintf(`RESTORE data.* FROM '%s'`, loadDir))
    58  
    59  	// TODO(dan): Ideally, this would split and rebalance the ranges in a more
    60  	// controlled way. A previous version of this code did it manually with
    61  	// `SPLIT AT` and TestCluster's TransferRangeLease, but it seemed to still
    62  	// be doing work after returning, which threw off the timing and the results
    63  	// of the benchmark. DistSQL is working on improving this infrastructure, so
    64  	// use what they build.
    65  
    66  	b.ResetTimer()
    67  	var unused string
    68  	var dataSize int64
    69  	sqlDB.QueryRow(b, fmt.Sprintf(`BACKUP DATABASE data TO '%s'`, dir)).Scan(
    70  		&unused, &unused, &unused, &unused, &unused, &unused, &dataSize,
    71  	)
    72  	b.StopTimer()
    73  	b.SetBytes(dataSize / int64(b.N))
    74  }
    75  
    76  func BenchmarkClusterRestore(b *testing.B) {
    77  	// NB: This benchmark takes liberties in how b.N is used compared to the go
    78  	// documentation's description. We're getting useful information out of it,
    79  	// but this is not a pattern to cargo-cult.
    80  
    81  	_, _, sqlDB, dir, cleanup := backupRestoreTestSetup(b, multiNode, 0, initNone)
    82  	defer cleanup()
    83  	sqlDB.Exec(b, `DROP TABLE data.bank`)
    84  
    85  	bankData := bank.FromRows(b.N).Tables()[0]
    86  	backup, err := sampledataccl.ToBackup(b, bankData, filepath.Join(dir, "foo"))
    87  	if err != nil {
    88  		b.Fatalf("%+v", err)
    89  	}
    90  	b.SetBytes(backup.Desc.EntryCounts.DataSize / int64(b.N))
    91  
    92  	b.ResetTimer()
    93  	sqlDB.Exec(b, `RESTORE data.* FROM 'nodelocal://0/foo'`)
    94  	b.StopTimer()
    95  }
    96  
    97  func BenchmarkLoadRestore(b *testing.B) {
    98  	if testing.Short() {
    99  		b.Skip("TODO: fix benchmark")
   100  	}
   101  	// NB: This benchmark takes liberties in how b.N is used compared to the go
   102  	// documentation's description. We're getting useful information out of it,
   103  	// but this is not a pattern to cargo-cult.
   104  
   105  	ctx, _, sqlDB, dir, cleanup := backupRestoreTestSetup(b, multiNode, 0, initNone)
   106  	defer cleanup()
   107  	sqlDB.Exec(b, `DROP TABLE data.bank`)
   108  
   109  	buf := bankBuf(b.N)
   110  	b.SetBytes(int64(buf.Len() / b.N))
   111  	ts := hlc.Timestamp{WallTime: hlc.UnixNano()}
   112  	b.ResetTimer()
   113  	if _, err := importccl.Load(ctx, sqlDB.DB.(*gosql.DB), buf, "data", dir, ts, 0, dir, dir); err != nil {
   114  		b.Fatalf("%+v", err)
   115  	}
   116  	sqlDB.Exec(b, fmt.Sprintf(`RESTORE data.* FROM '%s'`, dir))
   117  	b.StopTimer()
   118  }
   119  
   120  func BenchmarkLoadSQL(b *testing.B) {
   121  	// NB: This benchmark takes liberties in how b.N is used compared to the go
   122  	// documentation's description. We're getting useful information out of it,
   123  	// but this is not a pattern to cargo-cult.
   124  	_, _, sqlDB, _, cleanup := backupRestoreTestSetup(b, multiNode, 0, initNone)
   125  	defer cleanup()
   126  	sqlDB.Exec(b, `DROP TABLE data.bank`)
   127  
   128  	buf := bankBuf(b.N)
   129  	b.SetBytes(int64(buf.Len() / b.N))
   130  	lines := make([]string, 0, b.N)
   131  	for {
   132  		line, err := buf.ReadString(';')
   133  		if err == io.EOF {
   134  			break
   135  		} else if err != nil {
   136  			b.Fatalf("%+v", err)
   137  		}
   138  		lines = append(lines, line)
   139  	}
   140  
   141  	b.ResetTimer()
   142  	for _, line := range lines {
   143  		sqlDB.Exec(b, line)
   144  	}
   145  	b.StopTimer()
   146  }
   147  
   148  func BenchmarkClusterEmptyIncrementalBackup(b *testing.B) {
   149  	if testing.Short() {
   150  		b.Skip("TODO: fix benchmark")
   151  	}
   152  	const numStatements = 100000
   153  
   154  	_, _, sqlDB, _, cleanupFn := backupRestoreTestSetup(b, multiNode, 0, initNone)
   155  	defer cleanupFn()
   156  
   157  	restoreDir := filepath.Join(localFoo, "restore")
   158  	fullDir := filepath.Join(localFoo, "full")
   159  
   160  	bankData := bank.FromRows(numStatements).Tables()[0]
   161  	_, err := sampledataccl.ToBackup(b, bankData, restoreDir)
   162  	if err != nil {
   163  		b.Fatalf("%+v", err)
   164  	}
   165  	sqlDB.Exec(b, `DROP TABLE data.bank`)
   166  	sqlDB.Exec(b, `RESTORE data.* FROM $1`, restoreDir)
   167  
   168  	var unused string
   169  	var dataSize int64
   170  	sqlDB.QueryRow(b, `BACKUP DATABASE data TO $1`, fullDir).Scan(
   171  		&unused, &unused, &unused, &unused, &unused, &unused, &dataSize,
   172  	)
   173  
   174  	// We intentionally don't write anything to the database between the full and
   175  	// incremental backup.
   176  
   177  	b.ResetTimer()
   178  	for i := 0; i < b.N; i++ {
   179  		incrementalDir := filepath.Join(localFoo, fmt.Sprintf("incremental%d", i))
   180  		sqlDB.Exec(b, `BACKUP DATABASE data TO $1 INCREMENTAL FROM $2`, incrementalDir, fullDir)
   181  	}
   182  	b.StopTimer()
   183  
   184  	// We report the number of bytes that incremental backup was able to
   185  	// *skip*--i.e., the number of bytes in the full backup.
   186  	b.SetBytes(int64(b.N) * dataSize)
   187  }