Bài viết được sự cho phép của tác giả Nguyễn Việt Hưng
Đơn giản, nhanh, chậm, xinh, cao, thấp, giỏi, xịn… đều là những khái niệm mang tính chất tương đối. Có cái hơn khi so sánh ở góc độ này, nhưng lại kém khi so sánh ở góc độ khác. Trong ngành lập trình, mọi thứ đều là sự đánh đổi (trade off), không có giải pháp nào thỏa mãn tất cả mọi nhu cầu (silver bullet) – hoặc có nhưng chưa ai tìm ra.
Không cần bàn cãi, ai cũng đồng ý code Python dễ đọc, viết hơn C, hay… đơn giản hơn. Nhưng cái đơn giản đó, là đơn giản với con người, với lập trình viên, còn với máy tính thì hoàn toàn ngược lại.
Ta sẽ thử nghiệm chương trình đơn giản nhất trái đất: hello world viết bằng C và Python rồi so sánh dùng strace
– một công cụ debug “cao cấp” thường dùng bởi các SysAdmin.
strace
$ whatis strace
strace (1) - trace system calls and signals
Bài viết thực hiện trên Ubuntu 18.04, cc
– C compiler có lẽ là có sẵn. Hoặc nếu không có, hãy cài bằng sudo apt-get install -y build-essential strace
C Programming language
4 dòng code C
#include <stdio.h>
int main(void) {
puts("Hello world!");
}
Compile rồi chạy – yeah, cực đơn giản, không cần gì khác cả, cũng không cần làm việc đơn giản này trở thành rắc rôi.
$ cc hello.c -o hello # compile, sinh ra file hello
$ ./hello # chạy file hello
Hello world!
Giờ chạy với strace
để xem chương trình siêu đơn giản này gọi những system call nào, -C
sẽ hiển thị bảng thống kê, -S calls
sẽ sắp xếp thống kê này theo cột calls
, giảm dần.
$ strace -CScalls ./hello
execve("./hello", ["./hello"], 0x7fff1e9af718 /* 68 vars */) = 0
brk(NULL) = 0x56174aa4e000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106420, ...}) = 0
mmap(NULL, 106420, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f867f8fc000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "177ELF2113 3 >