diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..16d3c4d --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +.cache diff --git a/.gitignore b/.gitignore index 64336d3..d00b45e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ node_modules/ .bundle vendor/bundle .cache +.byebug_history diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..81109c5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +ARG RUBY_VERSION=2.6.10 +FROM ruby:$RUBY_VERSION + +ARG TMUX_VERSION=2.9 + +COPY . /app +WORKDIR /app + +# Run CI scripts +RUN CI_TMUX_VERSION=$TMUX_VERSION /app/spec/install-tmux-versions.sh +RUN /app/spec/use-tmux.sh $TMUX_VERSION + +# Install linux-perf +RUN apt-get update && apt-get install -y linux-perf-5.10 + +# Mock action stub globally +RUN ln -s /app/spec/action-stub.sh /usr/local/bin/action-stub + +# Install ruby stuff +RUN gem install bundler +RUN bundle install + +# Expose byebug remote debugging port +EXPOSE 1048 + +CMD ["bundle", "exec", "rspec"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e4fbc40 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +default: + docker build . -t fingers + +shell: default + docker run -it --rm fingers /bin/bash + +perf: default + docker run --security-opt seccomp=./docker-perf.json -it --rm fingers /bin/bash +#latest: + #docker build . -t fingers:ruby-latest-tmux-latest --build_arg TMUX_VERSION=3.3-rc --build-arg RUBY_VERSION=latest diff --git a/docker-perf.json b/docker-perf.json new file mode 100644 index 0000000..bda8064 --- /dev/null +++ b/docker-perf.json @@ -0,0 +1,768 @@ +{ + "defaultAction": "SCMP_ACT_ERRNO", + "defaultErrnoRet": 1, + "archMap": [ + { + "architecture": "SCMP_ARCH_X86_64", + "subArchitectures": [ + "SCMP_ARCH_X86", + "SCMP_ARCH_X32" + ] + }, + { + "architecture": "SCMP_ARCH_AARCH64", + "subArchitectures": [ + "SCMP_ARCH_ARM" + ] + }, + { + "architecture": "SCMP_ARCH_MIPS64", + "subArchitectures": [ + "SCMP_ARCH_MIPS", + "SCMP_ARCH_MIPS64N32" + ] + }, + { + "architecture": "SCMP_ARCH_MIPS64N32", + "subArchitectures": [ + "SCMP_ARCH_MIPS", + "SCMP_ARCH_MIPS64" + ] + }, + { + "architecture": "SCMP_ARCH_MIPSEL64", + "subArchitectures": [ + "SCMP_ARCH_MIPSEL", + "SCMP_ARCH_MIPSEL64N32" + ] + }, + { + "architecture": "SCMP_ARCH_MIPSEL64N32", + "subArchitectures": [ + "SCMP_ARCH_MIPSEL", + "SCMP_ARCH_MIPSEL64" + ] + }, + { + "architecture": "SCMP_ARCH_S390X", + "subArchitectures": [ + "SCMP_ARCH_S390" + ] + } + ], + "syscalls": [ + { + "names": [ + "accept", + "accept4", + "access", + "adjtimex", + "alarm", + "bind", + "brk", + "capget", + "capset", + "chdir", + "chmod", + "chown", + "chown32", + "clock_adjtime", + "clock_adjtime64", + "clock_getres", + "clock_getres_time64", + "clock_gettime", + "clock_gettime64", + "clock_nanosleep", + "clock_nanosleep_time64", + "close", + "close_range", + "connect", + "copy_file_range", + "creat", + "dup", + "dup2", + "dup3", + "epoll_create", + "epoll_create1", + "epoll_ctl", + "epoll_ctl_old", + "epoll_pwait", + "epoll_pwait2", + "epoll_wait", + "epoll_wait_old", + "eventfd", + "eventfd2", + "execve", + "execveat", + "exit", + "exit_group", + "faccessat", + "faccessat2", + "fadvise64", + "fadvise64_64", + "fallocate", + "fanotify_mark", + "fchdir", + "fchmod", + "fchmodat", + "fchown", + "fchown32", + "fchownat", + "fcntl", + "fcntl64", + "fdatasync", + "fgetxattr", + "flistxattr", + "flock", + "fork", + "fremovexattr", + "fsetxattr", + "fstat", + "fstat64", + "fstatat64", + "fstatfs", + "fstatfs64", + "fsync", + "ftruncate", + "ftruncate64", + "futex", + "futex_time64", + "futimesat", + "getcpu", + "getcwd", + "getdents", + "getdents64", + "getegid", + "getegid32", + "geteuid", + "geteuid32", + "getgid", + "getgid32", + "getgroups", + "getgroups32", + "getitimer", + "getpeername", + "getpgid", + "getpgrp", + "getpid", + "getppid", + "getpriority", + "getrandom", + "getresgid", + "getresgid32", + "getresuid", + "getresuid32", + "getrlimit", + "get_robust_list", + "getrusage", + "getsid", + "getsockname", + "getsockopt", + "get_thread_area", + "gettid", + "gettimeofday", + "getuid", + "getuid32", + "getxattr", + "inotify_add_watch", + "inotify_init", + "inotify_init1", + "inotify_rm_watch", + "io_cancel", + "ioctl", + "io_destroy", + "io_getevents", + "io_pgetevents", + "io_pgetevents_time64", + "ioprio_get", + "ioprio_set", + "io_setup", + "io_submit", + "io_uring_enter", + "io_uring_register", + "io_uring_setup", + "ipc", + "kill", + "lchown", + "lchown32", + "lgetxattr", + "link", + "linkat", + "listen", + "listxattr", + "llistxattr", + "_llseek", + "lremovexattr", + "lseek", + "lsetxattr", + "lstat", + "lstat64", + "madvise", + "membarrier", + "memfd_create", + "mincore", + "mkdir", + "mkdirat", + "mknod", + "mknodat", + "mlock", + "mlock2", + "mlockall", + "mmap", + "mmap2", + "mprotect", + "mq_getsetattr", + "mq_notify", + "mq_open", + "mq_timedreceive", + "mq_timedreceive_time64", + "mq_timedsend", + "mq_timedsend_time64", + "mq_unlink", + "mremap", + "msgctl", + "msgget", + "msgrcv", + "msgsnd", + "msync", + "munlock", + "munlockall", + "munmap", + "nanosleep", + "newfstatat", + "_newselect", + "open", + "openat", + "openat2", + "pause", + "perf_event_open", + "pidfd_open", + "pidfd_send_signal", + "pipe", + "pipe2", + "poll", + "ppoll", + "ppoll_time64", + "prctl", + "pread64", + "preadv", + "preadv2", + "prlimit64", + "pselect6", + "pselect6_time64", + "pwrite64", + "pwritev", + "pwritev2", + "read", + "readahead", + "readlink", + "readlinkat", + "readv", + "recv", + "recvfrom", + "recvmmsg", + "recvmmsg_time64", + "recvmsg", + "remap_file_pages", + "removexattr", + "rename", + "renameat", + "renameat2", + "restart_syscall", + "rmdir", + "rseq", + "rt_sigaction", + "rt_sigpending", + "rt_sigprocmask", + "rt_sigqueueinfo", + "rt_sigreturn", + "rt_sigsuspend", + "rt_sigtimedwait", + "rt_sigtimedwait_time64", + "rt_tgsigqueueinfo", + "sched_getaffinity", + "sched_getattr", + "sched_getparam", + "sched_get_priority_max", + "sched_get_priority_min", + "sched_getscheduler", + "sched_rr_get_interval", + "sched_rr_get_interval_time64", + "sched_setaffinity", + "sched_setattr", + "sched_setparam", + "sched_setscheduler", + "sched_yield", + "seccomp", + "select", + "semctl", + "semget", + "semop", + "semtimedop", + "semtimedop_time64", + "send", + "sendfile", + "sendfile64", + "sendmmsg", + "sendmsg", + "sendto", + "setfsgid", + "setfsgid32", + "setfsuid", + "setfsuid32", + "setgid", + "setgid32", + "setgroups", + "setgroups32", + "setitimer", + "setpgid", + "setpriority", + "setregid", + "setregid32", + "setresgid", + "setresgid32", + "setresuid", + "setresuid32", + "setreuid", + "setreuid32", + "setrlimit", + "set_robust_list", + "setsid", + "setsockopt", + "set_thread_area", + "set_tid_address", + "setuid", + "setuid32", + "setxattr", + "shmat", + "shmctl", + "shmdt", + "shmget", + "shutdown", + "sigaltstack", + "signalfd", + "signalfd4", + "sigprocmask", + "sigreturn", + "socket", + "socketcall", + "socketpair", + "splice", + "stat", + "stat64", + "statfs", + "statfs64", + "statx", + "symlink", + "symlinkat", + "sync", + "sync_file_range", + "syncfs", + "sysinfo", + "tee", + "tgkill", + "time", + "timer_create", + "timer_delete", + "timer_getoverrun", + "timer_gettime", + "timer_gettime64", + "timer_settime", + "timer_settime64", + "timerfd_create", + "timerfd_gettime", + "timerfd_gettime64", + "timerfd_settime", + "timerfd_settime64", + "times", + "tkill", + "truncate", + "truncate64", + "ugetrlimit", + "umask", + "uname", + "unlink", + "unlinkat", + "utime", + "utimensat", + "utimensat_time64", + "utimes", + "vfork", + "vmsplice", + "wait4", + "waitid", + "waitpid", + "write", + "writev" + ], + "action": "SCMP_ACT_ALLOW" + }, + { + "names": [ + "process_vm_readv", + "process_vm_writev", + "ptrace" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "minKernel": "4.8" + } + }, + { + "names": [ + "personality" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "index": 0, + "value": 0, + "op": "SCMP_CMP_EQ" + } + ] + }, + { + "names": [ + "personality" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "index": 0, + "value": 8, + "op": "SCMP_CMP_EQ" + } + ] + }, + { + "names": [ + "personality" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "index": 0, + "value": 131072, + "op": "SCMP_CMP_EQ" + } + ] + }, + { + "names": [ + "personality" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "index": 0, + "value": 131080, + "op": "SCMP_CMP_EQ" + } + ] + }, + { + "names": [ + "personality" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "index": 0, + "value": 4294967295, + "op": "SCMP_CMP_EQ" + } + ] + }, + { + "names": [ + "sync_file_range2", + "swapcontext" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "arches": [ + "ppc64le" + ] + } + }, + { + "names": [ + "arm_fadvise64_64", + "arm_sync_file_range", + "sync_file_range2", + "breakpoint", + "cacheflush", + "set_tls" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "arches": [ + "arm", + "arm64" + ] + } + }, + { + "names": [ + "arch_prctl" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "arches": [ + "amd64", + "x32" + ] + } + }, + { + "names": [ + "modify_ldt" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "arches": [ + "amd64", + "x32", + "x86" + ] + } + }, + { + "names": [ + "s390_pci_mmio_read", + "s390_pci_mmio_write", + "s390_runtime_instr" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "arches": [ + "s390", + "s390x" + ] + } + }, + { + "names": [ + "open_by_handle_at" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_DAC_READ_SEARCH" + ] + } + }, + { + "names": [ + "bpf", + "clone", + "clone3", + "fanotify_init", + "fsconfig", + "fsmount", + "fsopen", + "fspick", + "lookup_dcookie", + "mount", + "move_mount", + "name_to_handle_at", + "open_tree", + "quotactl", + "setdomainname", + "sethostname", + "setns", + "syslog", + "umount", + "umount2", + "unshare" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_SYS_ADMIN" + ] + } + }, + { + "names": [ + "clone" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "index": 0, + "value": 2114060288, + "op": "SCMP_CMP_MASKED_EQ" + } + ], + "excludes": { + "caps": [ + "CAP_SYS_ADMIN" + ], + "arches": [ + "s390", + "s390x" + ] + } + }, + { + "names": [ + "clone" + ], + "action": "SCMP_ACT_ALLOW", + "args": [ + { + "index": 1, + "value": 2114060288, + "op": "SCMP_CMP_MASKED_EQ" + } + ], + "comment": "s390 parameter ordering for clone is different", + "includes": { + "arches": [ + "s390", + "s390x" + ] + }, + "excludes": { + "caps": [ + "CAP_SYS_ADMIN" + ] + } + }, + { + "names": [ + "clone3" + ], + "action": "SCMP_ACT_ERRNO", + "errnoRet": 38, + "excludes": { + "caps": [ + "CAP_SYS_ADMIN" + ] + } + }, + { + "names": [ + "reboot" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_SYS_BOOT" + ] + } + }, + { + "names": [ + "chroot" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_SYS_CHROOT" + ] + } + }, + { + "names": [ + "delete_module", + "init_module", + "finit_module" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_SYS_MODULE" + ] + } + }, + { + "names": [ + "acct" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_SYS_PACCT" + ] + } + }, + { + "names": [ + "kcmp", + "pidfd_getfd", + "process_madvise", + "process_vm_readv", + "process_vm_writev", + "ptrace" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_SYS_PTRACE" + ] + } + }, + { + "names": [ + "iopl", + "ioperm" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_SYS_RAWIO" + ] + } + }, + { + "names": [ + "settimeofday", + "stime", + "clock_settime" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_SYS_TIME" + ] + } + }, + { + "names": [ + "vhangup" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_SYS_TTY_CONFIG" + ] + } + }, + { + "names": [ + "get_mempolicy", + "mbind", + "set_mempolicy" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_SYS_NICE" + ] + } + }, + { + "names": [ + "syslog" + ], + "action": "SCMP_ACT_ALLOW", + "includes": { + "caps": [ + "CAP_SYSLOG" + ] + } + } + ] +} diff --git a/docs/migrating-to-2.md b/docs/migrating-to-2.md new file mode 100644 index 0000000..ad7a1ab --- /dev/null +++ b/docs/migrating-to-2.md @@ -0,0 +1 @@ +# Migrating to tmux-fingers 2.0 diff --git a/lib/fingers.rb b/lib/fingers.rb index b1dcf74..336be8d 100644 --- a/lib/fingers.rb +++ b/lib/fingers.rb @@ -30,6 +30,7 @@ require 'fingers/commands/check_version' require 'fingers/commands/load_config' require 'fingers/commands/send_input' require 'fingers/commands/start' +require 'fingers/commands/trace_start' require 'fingers/action_runner' require 'fingers/hinter' diff --git a/lib/fingers/cli.rb b/lib/fingers/cli.rb index 40b7610..4055a40 100755 --- a/lib/fingers/cli.rb +++ b/lib/fingers/cli.rb @@ -19,6 +19,8 @@ module Fingers Fingers::Commands::SendInput when 'load_config' Fingers::Commands::LoadConfig + when 'trace_start' + Fingers::Commands::TraceStart else raise "Unknown command #{ARGV[0]}" end diff --git a/lib/fingers/commands/load_config.rb b/lib/fingers/commands/load_config.rb index 8bb7b86..c10defb 100644 --- a/lib/fingers/commands/load_config.rb +++ b/lib/fingers/commands/load_config.rb @@ -97,7 +97,8 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base input_mode = 'fingers-mode' ruby_bin = "#{RbConfig.ruby} --disable-gems" - `tmux bind-key #{Fingers.config.key} run-shell -b "#{ruby_bin} #{cli} start '#{input_mode}' '\#{pane_id}' >>#{Fingers::Dirs::LOG_PATH} 2>&1"` + `tmux bind-key #{Fingers.config.key} run-shell -b "#{ruby_bin} #{cli} start '#{input_mode}' '\#{pane_id}' self >>#{Fingers::Dirs::LOG_PATH} 2>&1"` + `tmux bind-key F run-shell -b "#{ruby_bin} #{cli} start '#{input_mode}' '\#{pane_id}' other >>#{Fingers::Dirs::LOG_PATH} 2>&1"` setup_fingers_mode_bindings if input_mode == 'fingers-mode' end diff --git a/lib/fingers/commands/start.rb b/lib/fingers/commands/start.rb index b7f373d..900243f 100644 --- a/lib/fingers/commands/start.rb +++ b/lib/fingers/commands/start.rb @@ -23,9 +23,11 @@ class Fingers::Commands::Start < Fingers::Commands::Base ) def run - _, _input_mode, original_pane_id = args + _, _input_mode, from_pane_id, target = args - @original_pane_id = original_pane_id + Fingers.logger.debug("from_pane_id: #{from_pane_id}") + @from_pane_id = from_pane_id + @target = target create_window! track_options_to_restore! @@ -37,15 +39,15 @@ class Fingers::Commands::Start < Fingers::Commands::Base private - attr_reader :original_pane_id + attr_reader :from_pane_id, :target def create_window! fingers_window tmux.resize_window( fingers_window.window_id, - original_pane.pane_width.to_i, - original_pane.pane_height.to_i + target_pane.pane_width.to_i, + target_pane.pane_height.to_i ) end @@ -53,8 +55,8 @@ class Fingers::Commands::Start < Fingers::Commands::Base @fingers_window ||= tmux.create_window('[fingers]', 'cat', 80, 24) end - def original_pane - @original_pane ||= tmux.pane_by_id(@original_pane_id) + def target_pane + @target_pane ||= compute_target_pane end def pane_printer @@ -63,8 +65,8 @@ class Fingers::Commands::Start < Fingers::Commands::Base def hinter @hinter ||= Fingers::Hinter.new( - input: tmux.capture_pane(original_pane.pane_id).chomp, - width: original_pane.pane_width.to_i, + input: tmux.capture_pane(target_pane.pane_id).chomp, + width: target_pane.pane_width.to_i, state: state, output: pane_printer ) @@ -75,7 +77,7 @@ class Fingers::Commands::Start < Fingers::Commands::Base hinter: hinter, state: state, output: pane_printer, - original_pane: original_pane + original_pane: target_pane ) end @@ -99,7 +101,7 @@ class Fingers::Commands::Start < Fingers::Commands::Base def show_hints view.render - tmux.swap_panes(fingers_pane_id, original_pane_id) + tmux.swap_panes(fingers_pane_id, target_pane.pane_id) tmux.zoom_pane(fingers_pane_id) if pane_was_zoomed? end @@ -116,6 +118,8 @@ class Fingers::Commands::Start < Fingers::Commands::Base Fingers.benchmark_stamp('ready-for-input:end') Fingers.trace_for_tests_do_not_remove_or_the_whole_fabric_of_reality_will_tear_apart_with_unforeseen_consequences('fingers-ready') + return if Fingers.config.trace_perf == '1' + input_socket.on_input do |input| view.process_input(input) @@ -143,20 +147,32 @@ class Fingers::Commands::Start < Fingers::Commands::Base end def pane_was_zoomed? - original_pane.window_zoomed_flag == '1' + target_pane.window_zoomed_flag == '1' end def teardown tmux.set_key_table 'root' - tmux.swap_panes(fingers_pane_id, original_pane_id) + tmux.swap_panes(fingers_pane_id, target_pane.pane_id) tmux.kill_pane(fingers_pane_id) - tmux.zoom_pane(original_pane_id) if pane_was_zoomed? + tmux.zoom_pane(target_pane.pane_id) if pane_was_zoomed? restore_options view.run_action if state.result Fingers.trace_for_tests_do_not_remove_or_the_whole_fabric_of_reality_will_tear_apart_with_unforeseen_consequences('fingers-finish') end + + def compute_target_pane + from_pane = tmux.pane_by_id(from_pane_id) + return from_pane if target == "self" + + sibling_panes = tmux.panes_by_window_id(from_pane.window_id) + + # TODO display message or pick pane + return from_pane if sibling_panes.length > 2 + + sibling_panes.find { |pane| pane.pane_id != from_pane.pane_id } + end end diff --git a/lib/fingers/commands/trace_start.rb b/lib/fingers/commands/trace_start.rb new file mode 100644 index 0000000..e067b30 --- /dev/null +++ b/lib/fingers/commands/trace_start.rb @@ -0,0 +1,6 @@ +class Fingers::Commands::TraceStart < Fingers::Commands::Base + def run + Fingers.benchmark_stamp('boot:start') + Fingers.benchmark_stamp('ready-for-input:start') + end +end diff --git a/lib/fingers/config.rb b/lib/fingers/config.rb index fc92448..4c0501c 100644 --- a/lib/fingers/config.rb +++ b/lib/fingers/config.rb @@ -15,6 +15,7 @@ module Fingers :selected_hint_format, :selected_highlight_format, :highlight_format, + :trace_perf ) do def initialize( key = 'F', @@ -29,7 +30,8 @@ module Fingers hint_format = Tmux.instance.parse_format('fg=yellow,bold'), selected_hint_format = Tmux.instance.parse_format('fg=green,bold'), selected_highlight_format = Tmux.instance.parse_format('fg=green,nobold,dim'), - highlight_format = Tmux.instance.parse_format('fg=yellow,nobold,dim') + highlight_format = Tmux.instance.parse_format('fg=yellow,nobold,dim'), + trace_perf = '0' ) super end diff --git a/lib/tmux.rb b/lib/tmux.rb index e0bf861..ca3ef88 100644 --- a/lib/tmux.rb +++ b/lib/tmux.rb @@ -76,6 +76,10 @@ class Tmux windows.find { |window| window['window_id'] == id } end + def panes_by_window_id(window_id) + panes.select { |pane| pane['window_id'] == window_id } + end + def pane_exec(pane_id, cmd) send_keys(pane_id, " #{cmd}") send_keys(pane_id, 'Enter') @@ -184,7 +188,7 @@ class Tmux def tmux flags = [] - flags.push('-L', socket) if socket + flags.push('-L', socket_flag_value) if socket_flag_value return "tmux #{flags.join(' ')}" unless flags.empty? @@ -201,4 +205,9 @@ class Tmux yield fields end end + + def socket_flag_value + return ENV['FINGERS_TMUX_SOCKET'] if ENV['FINGERS_TMUX_SOCKET'] + socket + end end diff --git a/spec/acceptance/performance_spec.rb b/spec/acceptance/performance_spec.rb index 4e7fd6d..86f9c5f 100644 --- a/spec/acceptance/performance_spec.rb +++ b/spec/acceptance/performance_spec.rb @@ -1,53 +1,29 @@ require 'spec_helper' require_relative '../tmuxomatic_setup.rb' -require_relative '../../lib/fingers/dirs.rb' - -def measure_benchmarks - benchmark_pattern = /benchmark:(?.*):(?start|end) (?.*)/ - f = File.open(Fingers::Dirs::LOG_PATH) - step_stack = [] - ellapsed_times_by_step = {} - f.read.split("\n").each do |line| - match = line.match(benchmark_pattern) - next unless match - - step = match.named_captures['step'] - phase = match.named_captures['phase'] - ms = match.named_captures['ms'].to_f * 1000 - - if phase == 'start' - step_stack.push([step, ms]) - elsif phase == 'end' - _, start_ms = step_stack.pop - - ellapsed_ms = ms - start_ms - - ellapsed_times_by_step[step] = [] unless ellapsed_times_by_step[step] - ellapsed_times_by_step[step].push(ellapsed_ms) - end - end - - ellapsed_times_by_step.each do |step, ellapsed_times| - avg = ellapsed_times.sum(0.0) / ellapsed_times.size - puts "#{step} avg #{avg}ms" - end -end +require 'benchmark' describe 'performance', performance: true do include_context 'tmuxomatic setup' + let(:config_name) { 'benchmark' } + let(:tmuxomatic_window_width) { 1000 } + let(:tmuxomatic_window_height) { 1000 } it 'runs smooooooth' do - `cat /dev/null > #{Fingers::Dirs::LOG_PATH}` - 10.times do |i| - puts "* Running #{i} time" - exec('COLUMNS=$COLUMNS LINES=$LINES ruby spec/fill_screen.rb') - sleep 1 - invoke_fingers(trace_benchmark: true) - sleep 1 - send_keys('q') - sleep 4 - end + exec('COLUMNS=$COLUMNS LINES=$LINES ruby spec/fill_screen.rb') - measure_benchmarks + pane_id = tmuxomatic.panes.first.pane_id + + ruby = RbConfig.ruby + + byebug + + #puts "Measuring fingers execution" + #fingers_measurement = Benchmark.measure do + #`FINGERS_TMUX_SOCKET=tmuxomatic_inner #{ruby} -e "puts :hello"` + ##`FINGERS_TMUX_SOCKET=tmuxomatic_inner #{ruby} --disable-gems bin/fingers start fingers-mode '#{pane_id}'` + #end + + #puts fingers_measurement + #puts "measure: #{fingers_measurement.real * 1000.0} ms" end end diff --git a/spec/conf/benchmark.conf b/spec/conf/benchmark.conf index aecd907..a7ac57e 100644 --- a/spec/conf/benchmark.conf +++ b/spec/conf/benchmark.conf @@ -1,3 +1,4 @@ set -g prefix C-a +set -g @fingers-trace-perf '1' set -g default-terminal 'screen-256color' run 'tmux-fingers.tmux' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ac8d9fc..23d1116 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -57,7 +57,7 @@ RSpec.configure do |config| # # is tagged with `:focus`, all examples get run. RSpec also provides # # aliases for `it`, `describe`, and `context` that include `:focus` # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_excluding :performance + #config.filter_run_excluding :performance # # # Allows RSpec to persist some state between runs in order to support # # the `--only-failures` and `--next-failure` CLI options. We recommend diff --git a/spec/tmuxomatic_setup.rb b/spec/tmuxomatic_setup.rb index 666be4b..4a599f9 100644 --- a/spec/tmuxomatic_setup.rb +++ b/spec/tmuxomatic_setup.rb @@ -15,6 +15,8 @@ shared_context 'tmuxomatic setup', a: :b do let(:config_name) { 'basic' } let(:prefix) { 'C-a' } let(:fingers_key) { 'F' } + let(:tmuxomatic_window_width) { 80 } + let(:tmuxomatic_window_height) { 24 } let(:tmuxomatic_pane_id) { tmuxomatic.panes.first['pane_id'] } let(:tmuxomatic_window_id) { tmuxomatic.panes.first['window_id'] } @@ -28,13 +30,9 @@ shared_context 'tmuxomatic setup', a: :b do def send_keys(keys, trace_benchmark: false) fork do tmuxomatic.send_keys(tmuxomatic_pane_id, keys) - if trace_benchmark - Fingers.benchmark_stamp('boot:start') - Fingers.benchmark_stamp('ready-for-input:start') - end end # TODO: detect when key is received, is it even possible? - zzz 0.2 + zzz 1.0 end def exec(cmd, wait: true) @@ -51,10 +49,13 @@ shared_context 'tmuxomatic setup', a: :b do return unless wait Timeout.timeout(10) do - sleep 0.1 while count_in_log_file(trace) <= trace_count_before + noop while count_in_log_file(trace) <= trace_count_before end end + def noop + end + def wait_for_fingers_teardown Timeout.timeout(10) do sleep 0.2 while tmuxomatic.capture_pane(tmuxomatic_pane_id).include?('[fingers]') @@ -120,10 +121,10 @@ shared_context 'tmuxomatic setup', a: :b do ) tmuxomatic - tmuxomatic.new_session('tmuxomatic', "PATH=\"#{fingers_root}:#{fingers_stubs_path}:$PATH\" TMUX='' tmux -L tmuxomatic_inner -f #{conf_path}", 80, 24) + tmuxomatic.new_session('tmuxomatic', "PATH=\"#{fingers_root}:#{fingers_stubs_path}:$PATH\" TMUX='' tmux -L tmuxomatic_inner -f #{conf_path}", tmuxomatic_window_width, tmuxomatic_window_height) tmuxomatic.set_global_option('prefix', 'None') tmuxomatic.set_global_option('status', 'off') - tmuxomatic.resize_window(tmuxomatic_window_id, 80, 24) + tmuxomatic.resize_window(tmuxomatic_window_id, tmuxomatic_window_width, tmuxomatic_window_height) `touch #{Fingers::Dirs::LOG_PATH}`