mirror of
https://github.com/kovidgoyal/kitty.git
synced 2024-09-20 02:57:19 +03:00
Start work on simple benchmark tool
This commit is contained in:
parent
8dbea2a046
commit
934f2ede0b
149
tools/cmd/benchmark/main.go
Normal file
149
tools/cmd/benchmark/main.go
Normal 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
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user