Skip to content

Commit 4b3cb9a

Browse files
committed
workload: fix large_row panic (#3926)
close #3927
1 parent f7d46b5 commit 4b3cb9a

File tree

1 file changed

+55
-35
lines changed

1 file changed

+55
-35
lines changed

tools/workload/schema/largerow/large_row.go

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import (
1717
"fmt"
1818
"math/rand"
1919
"strings"
20+
"sync"
21+
"sync/atomic"
2022
"time"
2123

2224
"github.com/pingcap/log"
@@ -53,7 +55,7 @@ func newRowValues(r *rand.Rand, columnSize int, columnCount int, batchSize int)
5355
if sb.Len() != 0 {
5456
sb.Write([]byte(","))
5557
}
56-
index := rand.Int() % numColumnValues
58+
index := r.Intn(numColumnValues)
5759
columnValue := columns[index]
5860

5961
sb.WriteByte('\'')
@@ -65,16 +67,6 @@ func newRowValues(r *rand.Rand, columnSize int, columnCount int, batchSize int)
6567
return result
6668
}
6769

68-
func (l *LargeRowWorkload) getSmallRow() string {
69-
index := l.r.Int() % len(l.smallRows)
70-
return l.smallRows[index]
71-
}
72-
73-
func (l *LargeRowWorkload) getLargeRow() string {
74-
index := l.r.Int() % len(l.largeRows)
75-
return l.largeRows[index]
76-
}
77-
7870
type LargeRowWorkload struct {
7971
smallRows []string
8072
largeRows []string
@@ -83,26 +75,44 @@ type LargeRowWorkload struct {
8375

8476
columnCount int
8577

86-
r *rand.Rand
78+
seed atomic.Int64
79+
randPool sync.Pool
80+
}
81+
82+
func (l *LargeRowWorkload) getRand() *rand.Rand {
83+
return l.randPool.Get().(*rand.Rand)
84+
}
85+
86+
func (l *LargeRowWorkload) putRand(r *rand.Rand) {
87+
l.randPool.Put(r)
88+
}
89+
90+
func (l *LargeRowWorkload) getSmallRow(r *rand.Rand) string {
91+
return l.smallRows[r.Intn(len(l.smallRows))]
92+
}
93+
94+
func (l *LargeRowWorkload) getLargeRow(r *rand.Rand) string {
95+
return l.largeRows[r.Intn(len(l.largeRows))]
8796
}
8897

8998
func NewLargeRowWorkload(
9099
normalRowSize, largeRowSize int, largeRatio float64,
91100
) schema.Workload {
92-
columnCount := int(float64(largeRowSize) / varcharColumnMaxLen)
93-
94101
r := rand.New(rand.NewSource(time.Now().UnixNano()))
102+
columnCount := int(float64(largeRowSize) / varcharColumnMaxLen)
95103
smallColumnSize := int(float64(normalRowSize) / float64(columnCount))
96104

97-
return &LargeRowWorkload{
98-
r: r,
99-
largeRatio: largeRatio,
100-
105+
l := &LargeRowWorkload{
106+
largeRatio: largeRatio,
101107
columnCount: columnCount,
102-
103-
smallRows: newRowValues(r, smallColumnSize, columnCount, 512),
104-
largeRows: newRowValues(r, varcharColumnMaxLen, columnCount, 128),
108+
smallRows: newRowValues(r, smallColumnSize, columnCount, 512),
109+
largeRows: newRowValues(r, varcharColumnMaxLen, columnCount, 128),
105110
}
111+
l.seed.Store(time.Now().UnixNano())
112+
l.randPool.New = func() any {
113+
return rand.New(rand.NewSource(l.seed.Add(1)))
114+
}
115+
return l
106116
}
107117

108118
func getTableName(n int) string {
@@ -124,37 +134,44 @@ func (l *LargeRowWorkload) BuildCreateTableStatement(n int) string {
124134

125135
func (l *LargeRowWorkload) BuildInsertSql(tableN int, batchSize int) string {
126136
tableName := getTableName(tableN)
127-
insertSQL := fmt.Sprintf("INSERT INTO %s VALUES (%d,%s)", tableName, rand.Int63()%maxValue, l.getSmallRow())
137+
r := l.getRand()
138+
defer l.putRand(r)
139+
140+
var sb strings.Builder
141+
sb.WriteString(fmt.Sprintf("INSERT INTO %s VALUES (%d,%s)", tableName, r.Int63()%maxValue, l.getSmallRow(r)))
128142

129143
var largeRowCount int
130144
for i := 1; i < batchSize; i++ {
131-
if l.r.Float64() < l.largeRatio {
132-
insertSQL = fmt.Sprintf("%s,(%d,%s)", insertSQL, rand.Int63()%maxValue, l.getLargeRow())
145+
if r.Float64() < l.largeRatio {
146+
sb.WriteString(fmt.Sprintf(",(%d,%s)", r.Int63()%maxValue, l.getLargeRow(r)))
133147
largeRowCount++
134148
} else {
135-
insertSQL = fmt.Sprintf("%s,(%d,%s)", insertSQL, rand.Int63()%maxValue, l.getSmallRow())
149+
sb.WriteString(fmt.Sprintf(",(%d,%s)", r.Int63()%maxValue, l.getSmallRow(r)))
136150
}
137151
}
138152

139153
log.Debug("large row workload, insert the table",
140154
zap.Int("table", tableN), zap.Int("batchSize", batchSize),
141-
zap.Int("largeRowCount", largeRowCount), zap.Int("length", len(insertSQL)))
155+
zap.Int("largeRowCount", largeRowCount), zap.Int("length", sb.Len()))
142156

143-
return insertSQL
157+
return sb.String()
144158
}
145159

146160
func (l *LargeRowWorkload) BuildUpdateSql(opts schema.UpdateOption) string {
147161
tableName := getTableName(opts.TableIndex)
162+
r := l.getRand()
163+
defer l.putRand(r)
164+
148165
upsertSQL := strings.Builder{}
149-
upsertSQL.WriteString(fmt.Sprintf("INSERT INTO %s VALUES (%d,%s)", tableName, rand.Int63()%maxValue, l.getSmallRow()))
166+
upsertSQL.WriteString(fmt.Sprintf("INSERT INTO %s VALUES (%d,%s)", tableName, r.Int63()%maxValue, l.getSmallRow(r)))
150167

151168
var largeRowCount int
152169
for i := 1; i < opts.Batch; i++ {
153-
if l.r.Float64() < l.largeRatio {
154-
upsertSQL.WriteString(fmt.Sprintf(",(%d,%s)", rand.Int63()%maxValue, l.getLargeRow()))
170+
if r.Float64() < l.largeRatio {
171+
upsertSQL.WriteString(fmt.Sprintf(",(%d,%s)", r.Int63()%maxValue, l.getLargeRow(r)))
155172
largeRowCount++
156173
} else {
157-
upsertSQL.WriteString(fmt.Sprintf(",(%d,%s)", rand.Int63()%maxValue, l.getSmallRow()))
174+
upsertSQL.WriteString(fmt.Sprintf(",(%d,%s)", r.Int63()%maxValue, l.getSmallRow(r)))
158175
}
159176
}
160177
upsertSQL.WriteString(" ON DUPLICATE KEY UPDATE col_0=VALUES(col_0)")
@@ -166,15 +183,18 @@ func (l *LargeRowWorkload) BuildUpdateSql(opts schema.UpdateOption) string {
166183
}
167184

168185
func (l *LargeRowWorkload) BuildDeleteSql(opts schema.DeleteOption) string {
169-
deleteType := rand.Intn(3)
186+
r := l.getRand()
187+
defer l.putRand(r)
188+
189+
deleteType := r.Intn(3)
170190
tableName := getTableName(opts.TableIndex)
171191

172192
switch deleteType {
173193
case 0:
174194
// Strategy 1: Random single/multiple row delete by ID
175195
var buf strings.Builder
176196
for i := 0; i < opts.Batch; i++ {
177-
id := rand.Int63() % maxValue
197+
id := r.Int63() % maxValue
178198
if i > 0 {
179199
buf.WriteString(";")
180200
}
@@ -184,7 +204,7 @@ func (l *LargeRowWorkload) BuildDeleteSql(opts schema.DeleteOption) string {
184204

185205
case 1:
186206
// Strategy 2: Range delete by ID
187-
startID := rand.Int63() % maxValue
207+
startID := r.Int63() % maxValue
188208
endID := startID + int64(opts.Batch*100)
189209
if endID > maxValue {
190210
endID = maxValue
@@ -194,7 +214,7 @@ func (l *LargeRowWorkload) BuildDeleteSql(opts schema.DeleteOption) string {
194214

195215
case 2:
196216
// Strategy 3: Conditional delete by random ID modulo
197-
modValue := rand.Intn(1000)
217+
modValue := r.Intn(1000)
198218
return fmt.Sprintf("DELETE FROM %s WHERE id %% 1000 = %d LIMIT %d",
199219
tableName, modValue, opts.Batch)
200220

0 commit comments

Comments
 (0)