Having seen Dan Luu’s tweet of the table “Time to load 3 GB file, insert character at start and exit” here, I want to see how vi does file I/O and also very briefly demonstrate strace.
First we need a large (ASCII) file. It does not need to be ASCII but it looks better like that in vi. So to generate a large ASCII file (thanks to this stackoverflow post):
$ base64 /dev/urandom | head -c 1000000000 > a
a is a 1GB file. ls output is:
-rw-rw-r-- 1 mete mete 1000000000 Aug 9 12:42 a
Now it is time to strace.
strace -etrace=open,close,write,read -o log vi a
This traces open, close, write and read system calls during the vi session, outputting the log to file named
In the vi session, I deleted the first character in the file.
The generated log file is very big, even if it contains only 4 system calls. ls output is:
-rw-rw-r-- 1 mete mete 8557348 Aug 9 12:48 log
Now, I open the log file and search for the name of the file “a” since it is going to be argument to open system calls. There are only 3 open calls like this:
open("a", O_RDONLY) = 3
The first is followed immediately by a close:
close(3) = 0
Then it is opened again and file is read:
read(3, "XqP2mbHhDltEMmkbl5wyJ/DumdU4l222"..., 8192) = 8192 read(3, "T/lS0yRhinZhJmpVsnBUn+xKQmCETVVv"..., 65536) = 65536
This repeats 15259 times and ends with:
read(3, "4N16OycPhT8yavc\nVYnACYDA9ez2IVpW"..., 65536) = 43520 read(3, "", 65536) = 0
Then it is closed.
The last open is followed by write calls:
write(3, "qP2mbHhDltEMmkbl5wyJ/DumdU4l222A"..., 8192) = 8192
repeating 122070 times and finishes with:
write(3, "6w/uUEf9a6N//vIHV3\n79x458WIdmCKN"..., 2560) = 2560
So basically, vi reads the file in 64K blocks, and then writes it out in 8K blocks.
strace is a great utility to examine system calls.
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.