Skip to content

Commit 1254118

Browse files
authored
test: tweak benchamark tests (#71)
1 parent a263a20 commit 1254118

File tree

5 files changed

+189
-179
lines changed

5 files changed

+189
-179
lines changed

benchmark_test.go

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ package simdcsv
55
import (
66
"bytes"
77
"encoding/csv"
8+
"fmt"
89
"io"
10+
"strings"
911
"testing"
1012
)
1113

@@ -274,3 +276,190 @@ func BenchmarkParseBytes_EscapedQuotes_10K(b *testing.B) {
274276
_, _ = ParseBytes(data, ',')
275277
}
276278
}
279+
280+
// =============================================================================
281+
// findClosingQuote Benchmarks
282+
// =============================================================================
283+
284+
func BenchmarkFindClosingQuote_Short(b *testing.B) {
285+
input := []byte(`"hello world"`)
286+
for b.Loop() {
287+
findClosingQuote(input, 1)
288+
}
289+
}
290+
291+
func BenchmarkFindClosingQuote_Long(b *testing.B) {
292+
input := []byte(`"` + strings.Repeat("abcdefgh", 100) + `"`)
293+
for b.Loop() {
294+
findClosingQuote(input, 1)
295+
}
296+
}
297+
298+
func BenchmarkFindClosingQuote_LongScalar(b *testing.B) {
299+
input := []byte(`"` + strings.Repeat("abcdefgh", 100) + `"`)
300+
for b.Loop() {
301+
findClosingQuoteScalar(input, 1)
302+
}
303+
}
304+
305+
func BenchmarkFindClosingQuote_LongWithEscapes(b *testing.B) {
306+
input := []byte(`"` + strings.Repeat(`a""b`, 50) + `"`)
307+
for b.Loop() {
308+
findClosingQuote(input, 1)
309+
}
310+
}
311+
312+
// =============================================================================
313+
// fieldNeedsQuotes Benchmarks
314+
// =============================================================================
315+
316+
func BenchmarkFieldNeedsQuotes_Short(b *testing.B) {
317+
w := NewWriter(nil)
318+
field := "hello,world"
319+
for b.Loop() {
320+
w.fieldNeedsQuotes(field)
321+
}
322+
}
323+
324+
func BenchmarkFieldNeedsQuotes_Long(b *testing.B) {
325+
w := NewWriter(nil)
326+
field := strings.Repeat("abcdefgh", 100)
327+
for b.Loop() {
328+
w.fieldNeedsQuotes(field)
329+
}
330+
}
331+
332+
func BenchmarkFieldNeedsQuotes_LongScalar(b *testing.B) {
333+
w := NewWriter(nil)
334+
field := strings.Repeat("abcdefgh", 100)
335+
for b.Loop() {
336+
w.fieldNeedsQuotesScalar(field)
337+
}
338+
}
339+
340+
func BenchmarkFieldNeedsQuotes_LongWithSpecial(b *testing.B) {
341+
w := NewWriter(nil)
342+
field := strings.Repeat("abcdefgh", 100) + ","
343+
for b.Loop() {
344+
w.fieldNeedsQuotes(field)
345+
}
346+
}
347+
348+
func BenchmarkWriteQuotedField_Long(b *testing.B) {
349+
field := strings.Repeat("a", 50) + `"` + strings.Repeat("b", 50)
350+
for b.Loop() {
351+
var buf bytes.Buffer
352+
w := NewWriter(&buf)
353+
_ = w.Write([]string{field})
354+
_ = w.Flush()
355+
}
356+
}
357+
358+
// =============================================================================
359+
// scanBuffer Benchmarks
360+
// =============================================================================
361+
362+
func BenchmarkGenerateMasks(b *testing.B) {
363+
data := make([]byte, 64)
364+
copy(data, []byte(`"field1","field2","field3","field4","field5","field6","fie"`))
365+
366+
b.ResetTimer()
367+
for i := 0; i < b.N; i++ {
368+
generateMasks(data, ',')
369+
}
370+
}
371+
372+
func BenchmarkGenerateMasksPadded(b *testing.B) {
373+
sizes := []int{1, 16, 32, 48, 63}
374+
375+
for _, size := range sizes {
376+
b.Run(fmt.Sprintf("size_%d", size), func(b *testing.B) {
377+
data := make([]byte, size)
378+
for i := range data {
379+
if i%2 == 0 {
380+
data[i] = ','
381+
} else {
382+
data[i] = 'a'
383+
}
384+
}
385+
386+
b.ResetTimer()
387+
for i := 0; i < b.N; i++ {
388+
generateMasksPadded(data, ',')
389+
}
390+
})
391+
}
392+
}
393+
394+
func BenchmarkScanBuffer(b *testing.B) {
395+
sizes := []int{64, 1024, 64 * 1024, 1024 * 1024}
396+
397+
for _, size := range sizes {
398+
b.Run(fmt.Sprintf("size_%d", size), func(b *testing.B) {
399+
// Create realistic CSV-like data
400+
data := make([]byte, size)
401+
for i := range data {
402+
switch i % 10 {
403+
case 3, 7:
404+
data[i] = ','
405+
case 9:
406+
data[i] = '\n'
407+
default:
408+
data[i] = 'a' + byte(i%26)
409+
}
410+
}
411+
412+
b.ResetTimer()
413+
b.SetBytes(int64(size))
414+
for i := 0; i < b.N; i++ {
415+
scanBuffer(data, ',')
416+
}
417+
})
418+
}
419+
}
420+
421+
// =============================================================================
422+
// parseBuffer Benchmarks
423+
// =============================================================================
424+
425+
func BenchmarkParseBuffer(b *testing.B) {
426+
// Generate test data: 10000 rows of "field1,field2,field3\n"
427+
numRows := 10000
428+
var data []byte
429+
for i := 0; i < numRows; i++ {
430+
data = append(data, []byte("field1,field2,field3\n")...)
431+
}
432+
433+
// Pre-compute masks
434+
chunkCount := (len(data) + 63) / 64
435+
sepMasks := make([]uint64, chunkCount)
436+
nlMasks := make([]uint64, chunkCount)
437+
438+
for i := 0; i < len(data); i++ {
439+
chunkIdx := i / 64
440+
bitPos := i % 64
441+
if data[i] == ',' {
442+
sepMasks[chunkIdx] |= 1 << bitPos
443+
} else if data[i] == '\n' {
444+
nlMasks[chunkIdx] |= 1 << bitPos
445+
}
446+
}
447+
448+
sr := &scanResult{
449+
quoteMasks: make([]uint64, chunkCount),
450+
separatorMasks: sepMasks,
451+
newlineMasks: nlMasks,
452+
chunkCount: chunkCount,
453+
lastChunkBits: len(data) % 64,
454+
}
455+
if sr.lastChunkBits == 0 {
456+
sr.lastChunkBits = 64
457+
}
458+
459+
b.ResetTimer()
460+
b.ReportAllocs()
461+
462+
for i := 0; i < b.N; i++ {
463+
_ = parseBuffer(data, sr)
464+
}
465+
}

field_parser_test.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,52 +1093,6 @@ func TestLargeInput(t *testing.T) {
10931093
})
10941094
}
10951095

1096-
// =============================================================================
1097-
// Benchmark Tests
1098-
// =============================================================================
1099-
1100-
func BenchmarkParseBuffer(b *testing.B) {
1101-
// Generate test data: 10000 rows of "field1,field2,field3\n"
1102-
numRows := 10000
1103-
var data []byte
1104-
for i := 0; i < numRows; i++ {
1105-
data = append(data, []byte("field1,field2,field3\n")...)
1106-
}
1107-
1108-
// Pre-compute masks
1109-
chunkCount := (len(data) + 63) / 64
1110-
sepMasks := make([]uint64, chunkCount)
1111-
nlMasks := make([]uint64, chunkCount)
1112-
1113-
for i := 0; i < len(data); i++ {
1114-
chunkIdx := i / 64
1115-
bitPos := i % 64
1116-
if data[i] == ',' {
1117-
sepMasks[chunkIdx] |= 1 << bitPos
1118-
} else if data[i] == '\n' {
1119-
nlMasks[chunkIdx] |= 1 << bitPos
1120-
}
1121-
}
1122-
1123-
sr := &scanResult{
1124-
quoteMasks: make([]uint64, chunkCount),
1125-
separatorMasks: sepMasks,
1126-
newlineMasks: nlMasks,
1127-
chunkCount: chunkCount,
1128-
lastChunkBits: len(data) % 64,
1129-
}
1130-
if sr.lastChunkBits == 0 {
1131-
sr.lastChunkBits = 64
1132-
}
1133-
1134-
b.ResetTimer()
1135-
b.ReportAllocs()
1136-
1137-
for i := 0; i < b.N; i++ {
1138-
_ = parseBuffer(data, sr)
1139-
}
1140-
}
1141-
11421096
// =============================================================================
11431097
// Helper Functions
11441098
// =============================================================================

quote_test.go

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -320,31 +320,3 @@ func TestFindClosingQuote_LargeInput(t *testing.T) {
320320
})
321321
}
322322
}
323-
324-
func BenchmarkFindClosingQuote_Short(b *testing.B) {
325-
input := []byte(`"hello world"`)
326-
for b.Loop() {
327-
findClosingQuote(input, 1)
328-
}
329-
}
330-
331-
func BenchmarkFindClosingQuote_Long(b *testing.B) {
332-
input := []byte(`"` + strings.Repeat("abcdefgh", 100) + `"`)
333-
for b.Loop() {
334-
findClosingQuote(input, 1)
335-
}
336-
}
337-
338-
func BenchmarkFindClosingQuote_LongScalar(b *testing.B) {
339-
input := []byte(`"` + strings.Repeat("abcdefgh", 100) + `"`)
340-
for b.Loop() {
341-
findClosingQuoteScalar(input, 1)
342-
}
343-
}
344-
345-
func BenchmarkFindClosingQuote_LongWithEscapes(b *testing.B) {
346-
input := []byte(`"` + strings.Repeat(`a""b`, 50) + `"`)
347-
for b.Loop() {
348-
findClosingQuote(input, 1)
349-
}
350-
}

simd_scanner_test.go

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,69 +1118,6 @@ func TestScanBuffer_LastChunkBits(t *testing.T) {
11181118
}
11191119
}
11201120

1121-
// ============================================================================
1122-
// Benchmark tests
1123-
// ============================================================================
1124-
1125-
func BenchmarkGenerateMasks(b *testing.B) {
1126-
data := make([]byte, 64)
1127-
copy(data, []byte(`"field1","field2","field3","field4","field5","field6","fie"`))
1128-
1129-
b.ResetTimer()
1130-
for i := 0; i < b.N; i++ {
1131-
generateMasks(data, ',')
1132-
}
1133-
}
1134-
1135-
func BenchmarkGenerateMasksPadded(b *testing.B) {
1136-
sizes := []int{1, 16, 32, 48, 63}
1137-
1138-
for _, size := range sizes {
1139-
b.Run(fmt.Sprintf("size_%d", size), func(b *testing.B) {
1140-
data := make([]byte, size)
1141-
for i := range data {
1142-
if i%2 == 0 {
1143-
data[i] = ','
1144-
} else {
1145-
data[i] = 'a'
1146-
}
1147-
}
1148-
1149-
b.ResetTimer()
1150-
for i := 0; i < b.N; i++ {
1151-
generateMasksPadded(data, ',')
1152-
}
1153-
})
1154-
}
1155-
}
1156-
1157-
func BenchmarkScanBuffer(b *testing.B) {
1158-
sizes := []int{64, 1024, 64 * 1024, 1024 * 1024}
1159-
1160-
for _, size := range sizes {
1161-
b.Run(fmt.Sprintf("size_%d", size), func(b *testing.B) {
1162-
// Create realistic CSV-like data
1163-
data := make([]byte, size)
1164-
for i := range data {
1165-
switch i % 10 {
1166-
case 3, 7:
1167-
data[i] = ','
1168-
case 9:
1169-
data[i] = '\n'
1170-
default:
1171-
data[i] = 'a' + byte(i%26)
1172-
}
1173-
}
1174-
1175-
b.ResetTimer()
1176-
b.SetBytes(int64(size))
1177-
for i := 0; i < b.N; i++ {
1178-
scanBuffer(data, ',')
1179-
}
1180-
})
1181-
}
1182-
}
1183-
11841121
// ============================================================================
11851122
// Helper functions
11861123
// ============================================================================

0 commit comments

Comments
 (0)