Description
I have a quite a big Bash file with over 10k lines in my projects. I noticed Brush is significantly slower to load the files then Bash.
I created a file with 20k newlines:
: > /tmp/file
for ((i=0;i<20000;++i)); do echo >> /tmp/file; done
I then compared brush loading times and brush was significantly slower:
$ f() { L_time "$1" -c '. /tmp/file' 2>&1; }; f ./brush; f bash
real=0m0.011553s user=0m0.006508s system=0m0.006570s [./brush -c . /tmp/file]
real=0m0.002199s user=0m0.001902s system=0m0.000355s [bash -c . /tmp/file]
I tried to run this multiple times, but the numbers are consistent. Brush takes considerably more time to parse a simple empty 20k newline file.
Brush takes both in system and user time more time then Bash.
I then briefly looked into strace and this is what Bash does:
$ strace -T -e 'openat,read' bash --norc --noprofile -c '. /tmp/file' 2>&1
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000061>
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libtinfo.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000047>
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832 <0.000031>
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000048>
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \250\2\0\0\0\0\0"..., 832) = 832 <0.000047>
openat(AT_FDCWD, "/dev/tty", O_RDWR|O_NONBLOCK) = 3 <0.000051>
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 <0.000159>
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) <0.000039>
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_COLLATE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) <0.000042>
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_COLLATE", O_RDONLY|O_CLOEXEC) = 3 <0.000037>
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000037>
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000069>
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000055>
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000044>
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000044>
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000038>
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000045>
openat(AT_FDCWD, "/usr/share/locale-langpack/en_US.UTF-8/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000039>
openat(AT_FDCWD, "/usr/share/locale-langpack/en_US.utf8/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000042>
openat(AT_FDCWD, "/usr/share/locale-langpack/en_US/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000061>
openat(AT_FDCWD, "/usr/share/locale-langpack/en.UTF-8/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000043>
openat(AT_FDCWD, "/usr/share/locale-langpack/en.utf8/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000447>
openat(AT_FDCWD, "/usr/share/locale-langpack/en/LC_MESSAGES/bash.mo", O_RDONLY) = -1 ENOENT (No such file or directory) <0.000048>
openat(AT_FDCWD, "/tmp/file", O_RDONLY) = 3 <0.000047>
read(3, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"..., 20000) = 20000 <0.000052>
+++ exited with 0 +++
That is all. No fuss, no extras. Also the file is read with two syscalls into a big fat 20k buffer.
Brush in contrast reads cgroups? and also reads the file in multiple syscalls. Still could be better with mmap.
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000042>
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 <0.000049>
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832 <0.000051>
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000037>
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832 <0.000035>
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000040>
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \250\2\0\0\0\0\0"..., 832) = 832 <0.000029>
openat(AT_FDCWD, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 3 <0.000068>
read(3, "5eb485394000-5eb4854f8000 r--p 0"..., 1024) = 1024 <0.000046>
read(3, "fc4a12000-794fc4a14000 rw-p 0021"..., 1024) = 1024 <0.000039>
read(3, "7 /usr/lib"..., 1024) = 1024 <0.000030>
read(3, "000 00:00 0 "..., 1024) = 205 <0.000036>
openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY|O_CLOEXEC) = 3 <0.000053>
read(3, "0::/user.slice/user-1000.slice/u"..., 128) = 128 <0.000039>
read(3, "", 32) = 0 <0.000032>
openat(AT_FDCWD, "/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/app-tmux.slice/tmux-spawn-84c0032d-6433-402f-baf5-2f2e86accec7.scope/cpu.max", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) <0.000033>
openat(AT_FDCWD, "/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/app-tmux.slice/cpu.max", O_RDONLY|O_CLOEXEC) = 3 <0.000040>
read(3, "max 100000\n", 32) = 11 <0.000031>
read(3, "", 9) = 0 <0.000028>
openat(AT_FDCWD, "/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/cpu.max", O_RDONLY|O_CLOEXEC) = 3 <0.000038>
read(3, "max 100000\n", 32) = 11 <0.000036>
read(3, "", 9) = 0 <0.000032>
openat(AT_FDCWD, "/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/cpu.max", O_RDONLY|O_CLOEXEC) = 3 <0.000045>
read(3, "max 100000\n", 32) = 11 <0.000038>
read(3, "", 9) = 0 <0.000032>
openat(AT_FDCWD, "/sys/fs/cgroup/user.slice/user-1000.slice/cpu.max", O_RDONLY|O_CLOEXEC) = 3 <0.000599>
read(3, "max 100000\n", 32) = 11 <0.000044>
read(3, "", 9) = 0 <0.000031>
openat(AT_FDCWD, "/sys/fs/cgroup/user.slice/cpu.max", O_RDONLY|O_CLOEXEC) = 3 <0.000063>
read(3, "max 100000\n", 32) = 11 <0.000037>
read(3, "", 9) = 0 <0.000030>
openat(AT_FDCWD, "/sys/fs/cgroup/cpu.max", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) <0.000038>
openat(AT_FDCWD, "/tmp/file", O_RDONLY|O_CLOEXEC) = 9 <0.000067>
read(9, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"..., 8192) = 8192 <0.000068>
read(9, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"..., 8192) = 8192 <0.000047>
read(9, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"..., 8192) = 3616 <0.000074>
read(9, "", 8192) = 0 <0.000060>
+++ exited with 0 +++
I do not think shell needs to read cgroups?
Thank you. This is a great project.
Description
I have a quite a big Bash file with over 10k lines in my projects. I noticed Brush is significantly slower to load the files then Bash.
I created a file with 20k newlines:
I then compared brush loading times and brush was significantly slower:
I tried to run this multiple times, but the numbers are consistent. Brush takes considerably more time to parse a simple empty 20k newline file.
Brush takes both in system and user time more time then Bash.
I then briefly looked into strace and this is what Bash does:
That is all. No fuss, no extras. Also the file is read with two syscalls into a big fat 20k buffer.
Brush in contrast reads cgroups? and also reads the file in multiple syscalls. Still could be better with mmap.
I do not think shell needs to read cgroups?
Thank you. This is a great project.