From d038d3040f6c7ee927b8967bd3100a22979bb375 Mon Sep 17 00:00:00 2001 From: Philipp Emanuel Weidmann Date: Sun, 1 Mar 2020 13:20:10 +0530 Subject: [PATCH] Add more sophisticated buffer benchmark system --- .gitignore | 1 + Makefile | 16 +- internal/buffer/buffer_generated_test.go | 62 ------ internal/buffer/buffer_test.go | 258 ++++++++++++++++++++--- tools/testgen.go | 12 -- 5 files changed, 250 insertions(+), 99 deletions(-) diff --git a/.gitignore b/.gitignore index 51f9a223..62f97acf 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ todo.txt test.txt log.txt *.old +benchmark_results* tools/build-version tools/build-date tools/info-plist diff --git a/Makefile b/Makefile index e6be78b0..8403fe60 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,21 @@ test: go test ./internal/... bench: - go test -bench=. ./internal/... + for i in 1 2 3; do \ + go test -bench=. ./internal/...; \ + done > benchmark_results + benchstat benchmark_results + +bench-baseline: + for i in 1 2 3; do \ + go test -bench=. ./internal/...; \ + done > benchmark_results_baseline + +bench-compare: + for i in 1 2 3; do \ + go test -bench=. ./internal/...; \ + done > benchmark_results + benchstat benchmark_results_baseline benchmark_results clean: rm -f micro diff --git a/internal/buffer/buffer_generated_test.go b/internal/buffer/buffer_generated_test.go index 3302fd35..4d771b58 100644 --- a/internal/buffer/buffer_generated_test.go +++ b/internal/buffer/buffer_generated_test.go @@ -1825,65 +1825,3 @@ func TestMultiInsert9(t *testing.T) { }, ) } - -func BenchmarkBuffer(b *testing.B) { - for i := 0; i < b.N; i++ { - TestAuto1(nil) - TestAuto2(nil) - TestAuto3(nil) - TestAuto4(nil) - TestBug19872UndoIsFunky(nil) - TestBug19872UndoIsFunky_2(nil) - TestInsertEmptyText(nil) - TestLastOpIsNoOp(nil) - TestInsertTextWithoutNewline1(nil) - TestInsertTextWithoutNewline2(nil) - TestInsertOneNewline(nil) - TestInsertTextWithOneNewline(nil) - TestInsertTextWithTwoNewlines(nil) - TestInsertTextWithManyNewlines(nil) - TestInsertMultipleNewlines(nil) - TestDeleteEmptyText(nil) - TestDeleteTextFromOneLine(nil) - TestDeleteTextFromOneLine2(nil) - TestDeleteAllTextFromALine(nil) - TestDeleteTextFromTwoLines(nil) - TestDeleteTextFromManyLines(nil) - TestDeleteEverything(nil) - TestTwoUnrelatedEdits(nil) - TestTwoEditsOnOneLine(nil) - TestManyEdits(nil) - TestManyEditsReversed(nil) - TestReplacingNewlines1(nil) - TestReplacingNewlines2(nil) - TestAdvanced1(nil) - TestAdvancedSimplified(nil) - TestIssue144(nil) - TestIssue2586ReplacingSelectedEndOfLineWithNewlineLocksUpTheDocument(nil) - TestIssue3980(nil) - TestTouchingEditsTwoInsertsAtTheSamePosition(nil) - TestTouchingEditsInsertAndReplaceTouching(nil) - TestTouchingEditsTwoTouchingReplaces(nil) - TestTouchingEditsTwoTouchingDeletes(nil) - TestTouchingEditsInsertAndReplace(nil) - TestTouchingEditsReplaceAndInsert(nil) - TestSingleDelete1(nil) - TestSingleDelete2(nil) - TestSingleDelete3(nil) - TestSingleDelete4(nil) - TestSingleDelete5(nil) - TestMultiDelete6(nil) - TestMultiDelete7(nil) - TestMultiDelete8(nil) - TestMultiDelete9(nil) - TestSingleInsert1(nil) - TestSingleInsert2(nil) - TestSingleInsert3(nil) - TestSingleInsert4(nil) - TestSingleInsert5(nil) - TestMultiInsert6(nil) - TestMultiInsert7(nil) - TestMultiInsert8(nil) - TestMultiInsert9(nil) - } -} diff --git a/internal/buffer/buffer_test.go b/internal/buffer/buffer_test.go index 15418fe3..20597662 100644 --- a/internal/buffer/buffer_test.go +++ b/internal/buffer/buffer_test.go @@ -1,12 +1,15 @@ package buffer import ( + "math/rand" "strings" "testing" + "unicode/utf8" - testifyAssert "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/assert" lua "github.com/yuin/gopher-lua" + "github.com/zyedidia/micro/internal/config" ulua "github.com/zyedidia/micro/internal/lua" ) @@ -16,34 +19,15 @@ type operation struct { text []string } -type asserter interface { - Equal(interface{}, interface{}, ...interface{}) bool - NotEqual(interface{}, interface{}, ...interface{}) bool -} - -type noOpAsserter struct { -} - -func (a *noOpAsserter) Equal(interface{}, interface{}, ...interface{}) bool { - return true -} - -func (a *noOpAsserter) NotEqual(interface{}, interface{}, ...interface{}) bool { - return true -} - func init() { ulua.L = lua.NewState() + config.InitGlobalSettings() + config.GlobalSettings["backup"] = false + config.GlobalSettings["fastdirty"] = true } func check(t *testing.T, before []string, operations []operation, after []string) { - var assert asserter - if t == nil { - // Benchmark mode; don't perform assertions - assert = &noOpAsserter{} - } else { - assert = testifyAssert.New(t) - } + assert := assert.New(t) b := NewBufferFromString(strings.Join(before, "\n"), "", BTDefault) @@ -111,3 +95,229 @@ func check(t *testing.T, before []string, operations []operation, after []string b.Close() } + +const maxLineLength = 200 + +var alphabet = []rune(" abcdeäم📚") + +func randomString(length int) string { + runes := make([]rune, length) + for i := range runes { + runes[i] = alphabet[rand.Intn(len(alphabet))] + } + return string(runes) +} + +func randomText(nLines int) string { + lines := make([]string, nLines) + for i := range lines { + lines[i] = randomString(rand.Intn(maxLineLength + 1)) + } + return strings.Join(lines, "\n") +} + +func benchCreateAndClose(testingB *testing.B, nLines int) { + rand.Seed(int64(nLines)) + + text := randomText(nLines) + + testingB.ResetTimer() + + for i := 0; i < testingB.N; i++ { + b := NewBufferFromString(text, "", BTDefault) + b.Close() + } +} + +func benchRead(testingB *testing.B, nLines int) { + rand.Seed(int64(nLines)) + + b := NewBufferFromString(randomText(nLines), "", BTDefault) + + testingB.ResetTimer() + + for i := 0; i < testingB.N; i++ { + b.Bytes() + for j := 0; j < b.LinesNum(); j++ { + b.Line(j) + b.LineBytes(j) + } + } + + testingB.StopTimer() + + b.Close() +} + +func benchEdit(testingB *testing.B, nLines, nCursors int) { + rand.Seed(int64(nLines + nCursors)) + + b := NewBufferFromString(randomText(nLines), "", BTDefault) + + regionSize := nLines / nCursors + + operations := make([]operation, nCursors) + for i := range operations { + startLine := (i * regionSize) + rand.Intn(regionSize-5) + startColumn := rand.Intn(utf8.RuneCountInString(b.Line(startLine)) + 1) + endLine := startLine + 1 + rand.Intn(5) + endColumn := rand.Intn(utf8.RuneCountInString(b.Line(endLine)) + 1) + + operations[i] = operation{ + start: Loc{startColumn, startLine}, + end: Loc{endColumn, endLine}, + text: []string{randomText(2 + rand.Intn(4))}, + } + } + + testingB.ResetTimer() + + for i := 0; i < testingB.N; i++ { + b.SetCursors([]*Cursor{}) + + var cursors []*Cursor + + for _, op := range operations { + cursor := NewCursor(b, op.start) + cursor.SetSelectionStart(op.start) + cursor.SetSelectionEnd(op.end) + b.AddCursor(cursor) + cursors = append(cursors, cursor) + } + + for j, op := range operations { + cursor := cursors[j] + b.SetCurCursor(cursor.Num) + cursor.DeleteSelection() + b.Insert(cursor.Loc, op.text[0]) + } + + for b.UndoStack.Peek() != nil { + b.UndoOneEvent() + } + } + + testingB.StopTimer() + + b.Close() +} + +func BenchmarkCreateAndClose10Lines(b *testing.B) { + benchCreateAndClose(b, 10) +} + +func BenchmarkCreateAndClose100Lines(b *testing.B) { + benchCreateAndClose(b, 100) +} + +func BenchmarkCreateAndClose1000Lines(b *testing.B) { + benchCreateAndClose(b, 1000) +} + +func BenchmarkCreateAndClose10000Lines(b *testing.B) { + benchCreateAndClose(b, 10000) +} + +func BenchmarkCreateAndClose100000Lines(b *testing.B) { + benchCreateAndClose(b, 100000) +} + +func BenchmarkCreateAndClose1000000Lines(b *testing.B) { + benchCreateAndClose(b, 1000000) +} + +func BenchmarkRead10Lines(b *testing.B) { + benchRead(b, 10) +} + +func BenchmarkRead100Lines(b *testing.B) { + benchRead(b, 100) +} + +func BenchmarkRead1000Lines(b *testing.B) { + benchRead(b, 1000) +} + +func BenchmarkRead10000Lines(b *testing.B) { + benchRead(b, 10000) +} + +func BenchmarkRead100000Lines(b *testing.B) { + benchRead(b, 100000) +} + +func BenchmarkRead1000000Lines(b *testing.B) { + benchRead(b, 1000000) +} + +func BenchmarkEdit10Lines1Cursor(b *testing.B) { + benchEdit(b, 10, 1) +} + +func BenchmarkEdit100Lines1Cursor(b *testing.B) { + benchEdit(b, 100, 1) +} + +func BenchmarkEdit100Lines10Cursors(b *testing.B) { + benchEdit(b, 100, 10) +} + +func BenchmarkEdit1000Lines1Cursor(b *testing.B) { + benchEdit(b, 1000, 1) +} + +func BenchmarkEdit1000Lines10Cursors(b *testing.B) { + benchEdit(b, 1000, 10) +} + +func BenchmarkEdit1000Lines100Cursors(b *testing.B) { + benchEdit(b, 1000, 100) +} + +func BenchmarkEdit10000Lines1Cursor(b *testing.B) { + benchEdit(b, 10000, 1) +} + +func BenchmarkEdit10000Lines10Cursors(b *testing.B) { + benchEdit(b, 10000, 10) +} + +func BenchmarkEdit10000Lines100Cursors(b *testing.B) { + benchEdit(b, 10000, 100) +} + +func BenchmarkEdit10000Lines1000Cursors(b *testing.B) { + benchEdit(b, 10000, 1000) +} + +func BenchmarkEdit100000Lines1Cursor(b *testing.B) { + benchEdit(b, 100000, 1) +} + +func BenchmarkEdit100000Lines10Cursors(b *testing.B) { + benchEdit(b, 100000, 10) +} + +func BenchmarkEdit100000Lines100Cursors(b *testing.B) { + benchEdit(b, 100000, 100) +} + +func BenchmarkEdit100000Lines1000Cursors(b *testing.B) { + benchEdit(b, 100000, 1000) +} + +func BenchmarkEdit1000000Lines1Cursor(b *testing.B) { + benchEdit(b, 1000000, 1) +} + +func BenchmarkEdit1000000Lines10Cursors(b *testing.B) { + benchEdit(b, 1000000, 10) +} + +func BenchmarkEdit1000000Lines100Cursors(b *testing.B) { + benchEdit(b, 1000000, 100) +} + +func BenchmarkEdit1000000Lines1000Cursors(b *testing.B) { + benchEdit(b, 1000000, 1000) +} diff --git a/tools/testgen.go b/tools/testgen.go index 6d53fa57..2465ae0a 100644 --- a/tools/testgen.go +++ b/tools/testgen.go @@ -233,8 +233,6 @@ func main() { re := regexp.MustCompile(`[^\w]`) usedNames := map[string]bool{} - var b strings.Builder - for _, test := range tests { name := strings.Title(strings.ToLower(test.description)) name = re.ReplaceAllLiteralString(name, "") @@ -253,15 +251,5 @@ func main() { usedNames[name] = true fmt.Println(testToGoTest(test, name)) - - b.WriteString("Test") - b.WriteString(name) - b.WriteString("(nil)\n") } - - fmt.Println("func BenchmarkBuffer(b *testing.B) {") - fmt.Println("for i := 0; i < b.N; i++ {") - fmt.Print(b.String()) - fmt.Println("}") - fmt.Println("}") }