Start work on simple benchmark tool

This commit is contained in:
Kovid Goyal 2023-11-09 20:27:19 +05:30
parent 8dbea2a046
commit 934f2ede0b
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 159 additions and 8 deletions

149
tools/cmd/benchmark/main.go Normal file
View File

@ -0,0 +1,149 @@
// License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
package benchmark
import (
"bytes"
"fmt"
"math/rand"
"strings"
"sync"
"time"
"kitty/tools/cli"
"kitty/tools/tty"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print
const reset = "\x1b]\x1b\\\x1bc"
type benchmark_options struct {
alternate_screen bool
repeat_count int
}
func default_benchmark_options() benchmark_options {
return benchmark_options{alternate_screen: true, repeat_count: 10}
}
func benchmark_data(data string, opts benchmark_options) (duration time.Duration, err error) {
term, err := tty.OpenControllingTerm(tty.SetRaw)
if err != nil {
return 0, err
}
defer term.RestoreAndClose()
state := loop.TerminalStateOptions{Alternate_screen: opts.alternate_screen}
if _, err = term.WriteString(state.SetStateEscapeCodes()); err != nil {
return 0, err
}
defer func() { _, _ = term.WriteString(state.ResetStateEscapeCodes() + reset) }()
lock := sync.Mutex{}
const count = 3
go func() {
lock.Lock()
defer lock.Unlock()
buf := make([]byte, 8192)
var data []byte
q := []byte(strings.Repeat("\x1b[0n", count))
for !bytes.Contains(data, q) {
n, err := term.Read(buf)
if err != nil {
break
}
data = append(data, buf[:n]...)
}
}()
start := time.Now()
repeat_count := opts.repeat_count
for ; repeat_count > 0; repeat_count-- {
if _, err = term.WriteString(data); err != nil {
return 0, err
}
}
if _, err = term.WriteString(strings.Repeat("\x1b[5n", count)); err != nil {
return 0, err
}
lock.Lock()
duration = time.Since(start) / time.Duration(opts.repeat_count)
lock.Unlock()
return duration, nil
}
func random_string_of_bytes(n int, alphabet string) string {
var src = rand.NewSource(time.Now().UnixNano())
const (
letterIdxBits = 7 // 7 bits to represent a letter index
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
)
b := make([]byte, n)
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = src.Int63(), letterIdxMax
}
if idx := int(cache & letterIdxMask); idx < len(alphabet) {
b[i] = alphabet[idx]
i--
}
cache >>= letterIdxBits
remain--
}
return utils.UnsafeBytesToString(b)
}
type result struct {
desc string
data_sz int
duration time.Duration
}
func simple_ascii() (r result, err error) {
data := random_string_of_bytes(1024*1024+13, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \n\t\r `~!@#$%^&*()_+-=[]{}\\|;:'\",<.>/?")
duration, err := benchmark_data(data, default_benchmark_options())
if err != nil {
return result{}, err
}
return result{"Simple ascii characters", len(data), duration}, nil
}
func present_result(r result) {
rate := float64(r.data_sz) / float64(r.duration)
rate *= 1e3
fmt.Println("\t"+r.desc+":", r.duration, fmt.Sprintf("%.2f", rate), "GiB/s")
}
func main() (err error) {
var results []result
var r result
if r, err = simple_ascii(); err != nil {
return err
}
results = append(results, r)
fmt.Println(reset + "Results:")
for _, r := range results {
present_result(r)
}
return
}
func EntryPoint(root *cli.Command) {
sc := root.AddSubCommand(&cli.Command{
Name: "__benchmark__",
ShortDescription: "Run various benchmarks",
Hidden: true,
Run: func(cmd *cli.Command, args []string) (ret int, err error) {
if err = main(); err != nil {
ret = 1
}
return
},
})
_ = sc
}

View File

@ -18,6 +18,7 @@ import (
"kitty/kittens/unicode_input"
"kitty/tools/cli"
"kitty/tools/cmd/at"
"kitty/tools/cmd/benchmark"
"kitty/tools/cmd/edit_in_kitty"
"kitty/tools/cmd/mouse_demo"
"kitty/tools/cmd/pytest"
@ -121,4 +122,5 @@ func KittyToolEntryPoints(root *cli.Command) {
return
},
})
benchmark.EntryPoint(root)
}

View File

@ -129,12 +129,12 @@ func (self *Loop) RemoveTimer(id IdType) bool {
}
func (self *Loop) NoAlternateScreen() *Loop {
self.terminal_options.alternate_screen = false
self.terminal_options.Alternate_screen = false
return self
}
func NoAlternateScreen(self *Loop) {
self.terminal_options.alternate_screen = false
self.terminal_options.Alternate_screen = false
}
func (self *Loop) OnlyDisambiguateKeys() *Loop {
@ -268,7 +268,7 @@ func (self *Loop) Run() (err error) {
}
fmt.Fprintf(os.Stderr, "%s\r\n\t%s:%d\r\n", frame.Function, frame.File, frame.Line)
}
if self.terminal_options.alternate_screen {
if self.terminal_options.Alternate_screen {
term, err := tty.OpenControllingTerm(tty.SetRaw)
if err == nil {
defer term.RestoreAndClose()

View File

@ -22,7 +22,7 @@ var SIGNULL unix.Signal
func new_loop() *Loop {
l := Loop{controlling_term: nil}
l.terminal_options.alternate_screen = true
l.terminal_options.Alternate_screen = true
l.terminal_options.restore_colors = true
l.terminal_options.kitty_keyboard_mode = DISAMBIGUATE_KEYS | REPORT_ALTERNATE_KEYS | REPORT_ALL_KEYS_AS_ESCAPE_CODES | REPORT_TEXT_WITH_KEYS
l.escape_code_parser.HandleCSI = l.handle_csi

View File

@ -94,7 +94,7 @@ const (
)
type TerminalStateOptions struct {
alternate_screen, restore_colors bool
Alternate_screen, restore_colors bool
mouse_tracking MouseTracking
kitty_keyboard_mode KeyboardStateBits
}
@ -114,7 +114,7 @@ func reset_modes(sb *strings.Builder, modes ...Mode) {
func (self *TerminalStateOptions) SetStateEscapeCodes() string {
var sb strings.Builder
sb.Grow(256)
if self.alternate_screen {
if self.Alternate_screen {
sb.WriteString(SAVE_CURSOR)
}
sb.WriteString(SAVE_PRIVATE_MODE_VALUES)
@ -126,7 +126,7 @@ func (self *TerminalStateOptions) SetStateEscapeCodes() string {
IRM, DECKM, DECSCNM, BRACKETED_PASTE, FOCUS_TRACKING,
MOUSE_BUTTON_TRACKING, MOUSE_MOTION_TRACKING, MOUSE_MOVE_TRACKING, MOUSE_UTF8_MODE, MOUSE_SGR_MODE)
set_modes(&sb, DECARM, DECAWM, DECTCEM)
if self.alternate_screen {
if self.Alternate_screen {
set_modes(&sb, ALTERNATE_SCREEN)
sb.WriteString(CLEAR_SCREEN)
}
@ -153,7 +153,7 @@ func (self *TerminalStateOptions) ResetStateEscapeCodes() string {
var sb strings.Builder
sb.Grow(64)
sb.WriteString("\033[<u")
if self.alternate_screen {
if self.Alternate_screen {
sb.WriteString(ALTERNATE_SCREEN.EscapeCodeToReset())
} else {
sb.WriteString(SAVE_CURSOR)