Pgit: Tôi đã nhập hạt nhân Linux vào PostgreSQL
Backend·Hacker News·0 lượt xem

Pgit: Tôi đã nhập hạt nhân Linux vào PostgreSQL

Pgit: I Imported the Linux Kernel into PostgreSQL

AI Summary

SKIP

Tôi đã nhập toàn bộ lịch sử git nhân Linux vào bộ lưu trữ PostgreSQL của pgit. 1.428.882 cam kết, 24,4 triệu phiên bản tệp, 20 năm phát triển. Đây là hạt nhân trông như thế nào khi bạn có thể hỏi.

TL;DR: Đã nhập toàn bộ lịch sử hạt nhân Linux vào pgit. 1.428.882 commit, 24,4 triệu phiên bản tệp, 20 năm phát triển, được lưu trữ trong PostgreSQL với tính năng nén delta. Dữ liệu thực tế: 2,7 GB (git gc --aggressive đạt 1,95 GB). Quá trình nhập mất 2 giờ trên một máy chủ chuyên dụng. Sau đó, tôi bắt đầu đặt các câu hỏi. 7 từ chửi thề trong 1,4 triệu tin nhắn commit (tất cả đều từ 2 người). 665 bản sửa lỗi trỏ đến một commit duy nhất. Một hệ thống tệp mất 13 năm để hợp nhất. Đây là cách hạt nhân Linux trông như thế nào dưới dạng cơ sở dữ liệu SQL.


Quá trình nhập

Bài viết này được xây dựng dựa trên pgit: Điều gì sẽ xảy ra nếu lịch sử Git của bạn là cơ sở dữ liệu SQL?. Nếu bạn chưa đọc nó, hãy bắt đầu từ đó. Phiên bản ngắn gọn: pgit là một CLI giống như Git, nơi mọi thứ nằm trong PostgreSQL thay vì hệ thống tệp. Nó sử dụng pg-xpatch để nén delta trong suốt và làm cho toàn bộ lịch sử commit của bạn có thể truy vấn bằng SQL. Sau khi bài viết về pgit lên trang đầu HN và được TLDR, console.dev và dailydev đưa tin, tôi đã "nhá hàng" rằng mình đang nhập hạt nhân Linux. Đây là những gì đã xảy ra.

Hạt nhân Linux là một trong những kho lưu trữ được phát triển tích cực lớn nhất trên thế giới. 1,4 triệu commit trải dài trong 20 năm, 171.000 tệp, 38.000 người đóng góp. Theo những gì tôi tìm hiểu được, chỉ một số ít hệ thống quản lý phiên bản (VCS) ngoài git từng thực hiện thành công việc nhập toàn bộ lịch sử của hạt nhân. Fossil (dựa trên SQLite, bởi nhóm SQLite) chưa bao giờ làm được. Darcs và Monotone đã thử nhưng gặp vấn đề nghiêm trọng về hiệu suất. Mercurial có thể làm được điều đó. Hãy sửa cho tôi nếu tôi có bất kỳ sai sót nào ở đây.

pgit đã xử lý được nó.

Chỉ sốGiá trị
Số lượng commit1,428,882
Phiên bản tệp (file refs)24,384,844
Blob duy nhất3,089,589
Đường dẫn duy nhất171,525
Nhóm đường dẫn (chuỗi delta)137,600
Thời gian nhập2 giờ 0 phút 48 giây

Quá trình nhập chạy trên máy chủ chuyên dụng Hetzner tại Phần Lan: AMD EPYC 7401P (24 nhân / 48 luồng), 512 GB DDR4 ECC RAM, 2×1.92 TB SSD trong RAID 0. Với bộ nhớ đệm nội dung xpatch 350 GB, toàn bộ kho lưu trữ đã giải mã đều nằm gọn trong bộ nhớ.

Thiết lập máy chủ đầy đủ, git baseline và cấu hình pgit

Máy chủ

Hetzner Dedicated "Server Auction" từ trung tâm dữ liệu Phần Lan (HEL1):

Thành phầnThông số
CPUAMD EPYC 7401P (24 nhân / 48 luồng)
RAM16×32 GB DDR4 ECC reg. (tổng 512 GB)
Lưu trữ2×Micron SSD SATA 1.92 TB Datacenter (RAID 0)
NIC1 Gbit Intel I350
Chi phí~€272/tháng

Cài đặt hệ điều hành

installimage của Hetzner với Ubuntu 24.04 LTS. Hai thay đổi so với cấu hình mặc định: RAID 0 (SWRAIDLEVEL 0) để có lưu lượng tối đa (không cần dự phòng cho công việc phân tích tạm thời) và bố cục phân vùng đơn giản:

PART /boot ext3 1024M
PART swap swap 4G
PART / ext4 all

Điều này cung cấp khoảng 3,5 TB dung lượng lưu trữ khả dụng trên hai ổ SSD 1,92 TB.

Tinh chỉnh hệ điều hành

Sau khi khởi động vào image đã cài đặt:

# --- Các gói phần mềm ---
apt update && apt upgrade -y
apt install -y \
  tmux btop htop iotop \
  cpufrequtils numactl \
  git curl wget unzip \
  build-essential \
  ufw \
  linux-tools-common linux-tools-$(uname -r)
# --- CPU governor → performance (tất cả 48 luồng) ---
for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
    echo performance > "$cpu"
done
cat > /etc/default/cpufrequtils << 'EOF'
GOVERNOR="performance"
EOF
systemctl enable cpufrequtils
systemctl restart cpufrequtils
# --- Tắt các biện pháp giảm thiểu Kernel ---
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="consoleblank=0"/GRUB_CMDLINE_LINUX_DEFAULT="consoleblank=0 mitigations=off"/' /etc/default/grub.d/hetzner.cfg
update-grub
# --- sysctl ---
cat >> /etc/sysctl.conf << 'EOF'
vm.swappiness = 1
vm.dirty_ratio = 5
vm.dirty_background_ratio = 2
kernel.numa_balancing = 1
EOF
sysctl -p
# --- Vô hiệu hóa Transparent Huge Pages ---
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
cat > /etc/systemd/system/disable-thp.service << 'EOF'
[Unit]
Description=Disable Transparent Huge Pages
DefaultDependencies=no
After=sysinit.target local-fs.target
Before=basic.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled && echo never > /sys/kernel/mm/transparent_hugepage/defrag'
[Install]
WantedBy=basic.target
EOF
systemctl daemon-reload
systemctl enable disable-thp
# --- noatime ---
sed -i 's|relatime|noatime|g' /etc/fstab
mount -o remount,noatime /
# --- Tường lửa ---
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw --force enable
# --- Go 1.26.0 ---
wget https://go.dev/dl/go1.26.0.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.26.0.linux-amd64.tar.gz
rm go1.26.0.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' >> ~/.bashrc
source ~/.bashrc
# --- Docker ---
apt install -y docker.io
systemctl enable docker
systemctl start docker
# --- Khởi động lại để áp dụng các thay đổi ---
reboot

Container pg-xpatch

Đã tải xuống image Docker pg-xpatch mới nhất chuẩn:

docker pull ghcr.io/imgajeed76/pg-xpatch:latest

Phiên bản pgit

pgit v4 với một vài thay đổi cục bộ chưa được phát hành tại thời điểm nhập. Đến khi bạn đọc bài viết này, chúng đã được đưa vào phiên bản mới nhất, vì vậy mọi thứ ở đây đều có thể tái tạo bằng lệnh go install thông thường. Thay đổi chính là bản sửa lỗi sắp xếp seq, thay thế việc hack dấu thời gian đơn điệu bằng cột seq INTEGER NOT NULL rõ ràng để sắp xếp commit. Điều này giúp việc giải nén chuỗi delta nhanh hơn đáng kể khi quét tuần tự. Danh sách thay đổi đầy đủ:

  • db/schema.go — Đã thêm cột seq INTEGER NOT NULL, order_by => 'seq' trong xpatch.configure()
  • db/commits.go — Đã thêm trường Seq vào struct, cập nhật tất cả các lệnh INSERT/COPY
  • cli/import.go — Điền vào Seq (đánh số từ 1), xóa bỏ hack dấu thời gian đơn điệu
  • repo/commit.gopgit commit tính toán MAX(seq)+1, bao gồm seq trong INSERT
  • cli/analyze.go — Cờ --timeout (thay thế giới hạn cứng 5 phút), ORDER BY seq ASC trong các truy vấn
  • cli/local.go — Hiển thị image container thực tế thay vì DefaultImage cố định
  • container/runtime.go — Hàm GetContainerImage() mới
  • Dọn dẹp tài liệu/văn bản trong README, sql.go, commits.go, ulid.go, config/reflect.go

Cấu hình pgit

# --- PostgreSQL core ---
pgit config --global container.shared_buffers 64GB
pgit config --global container.effective_cache_size 400GB
pgit config --global container.work_mem 256MB
pgit config --global container.wal_buffers 512MB
pgit config --global container.max_wal_size 32GB
pgit config --global container.checkpoint_timeout 60min
pgit config --global container.max_connections 50
pgit config --global container.port 5433
pgit config --global container.shm_size 450g
# --- Parallelism (24c/48t EPYC 7401P) ---
pgit config --global container.max_worker_processes 28
pgit config --global container.max_parallel_workers 24
pgit config --global container.max_parallel_per_gather 12
# --- xpatch content cache (350 GB) ---
pgit config --global container.xpatch_cache_size_mb 358400            # 350 GB
pgit config --global container.xpatch_cache_max_entries 41000000      # 31.5M cần thiết + 30%
pgit config --global container.xpatch_cache_max_entry_kb 16384        # 16 MB max cho mỗi mục
pgit config --global container.xpatch_cache_slot_size_kb 4            # mặc định, phù hợp với nhiều kích thước
pgit config --global container.xpatch_cache_partitions 24             # một cho mỗi lõi
# --- xpatch sub-caches ---
pgit config --global container.xpatch_group_cache_size_mb 256         # 85K nhóm cần 4 MB (62×)
pgit config --global container.xpatch_tid_cache_size_mb 4096          # 25.8M hàng cần 1.1 GB (3.7×)
pgit config --global container.xpatch_seq_tid_cache_size_mb 4096      # 25.8M hàng cần 1.5 GB (2.7×)
# --- xpatch insert / encoding ---
pgit config --global container.xpatch_insert_cache_slots 256          # 24 worker × nhóm đồng thời
pgit config --global container.xpatch_encode_threads 2                # ×24 worker = 48 HW threads
pgit config --global container.xpatch_warm_cache_workers 24           # một cho mỗi lõi
# --- Import ---
pgit config --global import.workers 24

Cơ sở lý luận cấu hình

Tham sốGiá trịLý do
shared_buffers64 GBTập dữ liệu ~20 GB trên đĩa, dự phòng 3×, toàn bộ DB nằm vừa trong buffer pool
effective_cache_size400 GBGợi ý cho trình lập kế hoạch: shared_buffers + OS page cache + xpatch caches
work_mem256 MBBộ nhớ mỗi thao tác cho sorts/hash joins; 50 kết nối × 256 MB = 12.8 GB trong trường hợp xấu nhất
wal_buffers512 MBHấp thụ các đợt ghi tăng đột biến trong quá trình import hàng loạt
max_wal_size32 GBTrì hoãn các checkpoint trong quá trình ghi nặng
checkpoint_timeout60 minGiảm thiểu I/O stalls từ các checkpoint bắt buộc
shm_size450 GB64 GB shared_buffers + 350 GB cache + 8 GB sub-caches + ~2 GB nội bộ ≈ 425 GB, làm tròn lên
xpatch_cache_size_mb350 GBDung lượng giải mã ước tính ~55 GB, dự phòng 84% đảm bảo mọi thứ vừa vặn
xpatch_cache_max_entries41M1.4M commits × 5 cột delta + 24.4M phiên bản tệp = 31.5M trong trường hợp xấu nhất, +30% đệm
xpatch_encode_threads2×24 worker = 48 luồng mã hóa, khớp chính xác với 48 HW threads
import.workers24Một cho mỗi lõi vật lý

Các chỉ số cơ sở của Git

Trước khi import, chúng tôi đã clone kernel và đo lường kho lưu trữ git gốc:

cd /root
git clone --single-branch --branch master https://github.com/torvalds/linux.git
cd /root/linux
git rev-list --count HEAD                                              # 1,428,882
git gc --quiet && du -sb .git/objects/pack/*.pack                      # 6,213,222,259 (5.79 GB)
git cat-file --batch-all-objects --batch-check='%(objecttype) %(objectsize)' \
  | awk '{sum += $2} END {printf "%.2f GB\n", sum/1024/1024/1024}'     # 144.43 GB
time git fast-export --reencode=yes --show-original-ids master \
  > /root/linux.fastexport                                             # 17m18s, 126 GB
time git gc --aggressive --quiet && du -sb .git/objects/pack/*.pack    # 24m46s, 2,093,181,079 (1.95 GB)
Chỉ sốGiá trị
Commits1,428,882
Dung lượng đối tượng thô chưa nén144.43 GB
Packfile sau git gc5.79 GB
Packfile sau git gc --aggressive1.95 GB
Thời gian git gc --aggressive24m 46s (338m CPU)
Dung lượng Fast-export126 GB
Thời gian Fast-export17m 18s

Quy trình import

Đã khởi động container pg-xpatch bằng pgit local start (kiểm tra khởi động bị timeout vì việc cấp phát 450 GB bộ nhớ chia sẻ mất chút thời gian, nhưng sau đó nó vẫn khởi động). Đã đợi cơ sở dữ liệu sẵn sàng bằng docker logs pgit-local -f.

cd /root/linux-analysis
pgit init
time pgit import /root/linux --branch master --fastexport /root/linux.fastexport
Giai đoạnThời gian
Import Commit39m 57s
Xây dựng đồ thị commit13s (độ sâu tối đa 75,641)
Tính toán nhóm đường dẫn9.6s (137,600 nhóm từ 171,525 đường dẫn)
Import Blob1h 17m
Xây dựng lại chỉ mục38s
Tổng cộng2h 0m 48s (thực tế), 336m 50s CPU, 21m 12s sys

Nén

Dung lượngTỷ lệ
Các đối tượng thô chưa nén144.43 GB1.0x
pgit (trên đĩa)6.6 GB21.9x
git gc (thông thường)5.79 GB24.9x
pgit (dữ liệu thực tế)2.7 GB53.5x
git gc --aggressive1.95 GB74.1x

git gc --aggressive giành chiến thắng. 1.95 GB so với 2.7 GB dữ liệu thực tế của pgit. Nhỏ hơn khoảng 38%.

Điều này hoàn toàn dễ hiểu. Linux kernel về cơ bản là kịch bản lý tưởng của git cho việc nén delta giữa các đối tượng: tái sử dụng mã nguồn khổng lồ giữa các kiến trúc, các tiêu đề giấy phép SPDX được sao chép trong hơn 70,000 tệp, và 70% tất cả các tệp là .c/.h với các mẫu chung trên các phân hệ hoàn toàn không liên quan. Định dạng packfile của git có thể nén delta bất kỳ đối tượng nào so với bất kỳ đối tượng nào khác trong toàn bộ kho lưu trữ, bất kể đường dẫn tệp. pgit nén trong các chuỗi delta ở cấp độ tệp.

Những gì pgit đạt được: nén 114.4x chỉ tính riêng nội dung văn bản. xpatch đã nén 123 GB văn bản nguồn thành 1.1 GB. 1.6 GB còn lại là siêu dữ liệu (tệp nào nằm trong commit nào, ánh xạ đường dẫn, refs). Chỉ có 52 blob nhị phân tồn tại trong toàn bộ lịch sử kernel. Nó gần như hoàn toàn là văn bản.

Nhưng sự so sánh không thực sự nằm ở byte. git gc --aggressive mất 25 phút và cho bạn một packfile. pgit mất 2 giờ và cho bạn một cơ sở dữ liệu SQL. Câu hỏi là bạn có thể làm gì sau đó.

Phân tích chi tiết trên đĩa
Thành phầnDung lượng
Commits (xpatch)600.6 MB
Nội dung văn bản (xpatch)1.3 GB
Nội dung nhị phân (xpatch)2.0 MB
Tham chiếu tệp (heap)2.1 GB
Đường dẫn (heap)13.2 MB
Khác (refs, metadata, sync)40.0 KB
Chỉ mục (Indexes)2.7 GB
Tổng trên đĩa6.6 GB
LớpDung lượng
xpatch (commits + text + binary)1.5 GB
Bảng thông thường (file_refs, paths, refs, metadata)1.2 GB
Dữ liệu thực tế2.7 GB
PostgreSQL overhead + chỉ mục3.9 GB

Lưu ý: Bảng thứ hai đã loại bỏ overhead của PostgreSQL khỏi từng thành phần, do đó các hàng sẽ không cộng lại khớp với bảng tổng dung lượng trên đĩa ở trên.

171.525 đường dẫn được gộp thành 137.600 nhóm delta (phát hiện đổi tên/sao chép). Khử trùng lặp blob 7.9x: 24.4 triệu tham chiếu tệp chỉ trỏ đến 3.1 triệu phiên bản nội dung duy nhất.

1.4 triệu commit đã tiết lộ những gì

Mọi nội dung dưới đây đều được truy vấn trực tiếp từ PostgreSQL. Hầu hết các truy vấn hoàn thành trong dưới 10 giây. Không có materialized view, không tiền xử lý, không kịch bản nào phân tích cú pháp đầu ra của git log. Chỉ đơn thuần là SQL trên các bảng được nén delta.

38.506 tác giả. 36% không bao giờ quay lại.

Nhân (kernel) có 38.506 tác giả duy nhất (theo email) nhưng chỉ có 1.540 người thực hiện commit (committer) duy nhất. Trong quy trình gửi thư của kernel, bạn viết một bản vá và người bảo trì sẽ hợp nhất nó. Vì vậy, 38.506 người đã viết mã, nhưng chỉ 1.540 người có quyền hợp nhất. Tỷ lệ 25:1.

Gần 14.000 trong số các tác giả đó đã đóng góp đúng một bản vá và không bao giờ quay lại.

90% commit tác động đến 5 tệp trở xuống

Số tệp tác độngCommit% tổng số
1 tệp875.54161.3%
2-5 tệp414.01829.0%
6-10 tệp70.9515.0%
11-50 tệp49.7003.5%
51+ tệp18.5231.3%

Quy tắc "mỗi commit một thay đổi logic" của kernel vẫn được giữ vững. Commit đơn lẻ lớn nhất đã tác động đến 53.003 tệp, nhưng cả 5 commit lớn nhất đều hóa ra là các commit hợp nhất từ những người bảo trì phân hệ. Không phải các thay đổi API quy mô lớn. Chỉ là công việc hạ tầng.

Sự liên kết tệp: những phụ thuộc ẩn

pgit analyze coupling tính toán những tệp nào luôn thay đổi cùng nhau. Đây là kiểu phân tích rất khó thực hiện với git (phân tích cú pháp đầu ra của git log, xây dựng ma trận thay đổi đồng thời, lọc nhiễu) nhưng lại vô cùng đơn giản khi lịch sử của bạn là một cơ sở dữ liệu SQL. Trên 1.4 triệu commit, nó hoàn thành trong 48 giây.

Tệp ATệp BSố lần thay đổi cùng nhau
i915/intel_drv.hi915/intel_display.c1.117
net/core/dev.cinclude/linux/netdevice.h1.087
i915/i915_gem.ci915/i915_drv.h1.072
arch/x86/kvm/x86.carch/x86/include/asm/kvm_host.h1.066
include/uapi/linux/bpf.htools/include/uapi/linux/bpf.h742
net/ipv4/tcp_ipv4.cnet/ipv6/tcp_ipv6.c739

Driver GPU Intel i915 chiếm vị trí đầu bảng: intel_drv.hintel_display.c đã được thay đổi cùng nhau 1.117 lần. Driver i915 xuất hiện 8 lần trong top 30 cặp tệp liên kết chặt chẽ nhất.

Mục thú vị nhất: include/uapi/linux/bpf.htools/include/uapi/linux/bpf.h với 742 lần thay đổi cùng nhau. Mỗi thay đổi tiêu đề BPF của kernel đòi hỏi phải sao chép thủ công sang thư mục công cụ. Và tcp_ipv4.c với tcp_ipv6.c là 739: sửa một lỗi TCP trong IPv4 hầu như luôn đồng nghĩa với việc áp dụng cùng một bản sửa lỗi đó trong IPv6.

Toàn bộ 15 cặp liên kết hàng đầu
HạngTệp ATệp BSố lần thay đổi cùng nhau
1i915/intel_drv.hi915/intel_display.c1.117
2net/core/dev.cinclude/linux/netdevice.h1.087
3i915/i915_gem.ci915/i915_drv.h1.072
4arch/x86/kvm/x86.carch/x86/include/asm/kvm_host.h1.066
5i915/intel_display.ci915/i915_drv.h892
6include/net/cfg80211.hnet/wireless/nl80211.c783
7mlx5/core/en_main.cmlx5/core/en.h778
8fs/btrfs/inode.cfs/btrfs/ctree.h776
9fs/btrfs/ctree.hfs/btrfs/extent-tree.c769
10fs/btrfs/disk-io.cfs/btrfs/ctree.h757
11include/uapi/linux/bpf.htools/include/uapi/linux/bpf.h742
12net/ipv4/tcp_ipv4.cnet/ipv6/tcp_ipv6.c739
13i915/i915_drv.ci915/i915_drv.h739
14sound/soc/codecs/Makefilesound/soc/codecs/Kconfig674
15net/mac80211/ieee80211_i.hnet/mac80211/mlme.c670

Btrfs có 7 mục trong top 30, tất cả đều tỏa ra từ ctree.h. Tệp tiêu đề đó là trung tâm liên kết của toàn bộ hệ thống tệp Btrfs.

Ba người hợp nhất 22.5% tổng số commit

Người hợp nhất (Committer)Bản vá đã hợp nhấtTự viếtTỷ lệ hợp nhất
David S. Miller113.45615.6177.3x
Greg Kroah-Hartman105.7337.07315.0x
Linus Torvalds102.32245.1252.3x

David S. Miller (mạng) là điểm hợp nhất bận rộn nhất: 7.9% tổng số commit của kernel chảy qua ông. Greg Kroah-Hartman tự viết 7 nghìn bản vá nhưng đã hợp nhất 106 nghìn. 15:1. John W. Linville thậm chí còn chênh lệch hơn: 18.9 nghìn bản hợp nhất, 1.1 nghìn bản tự viết. 16.5:1.

Bảng đầy đủ các committer (top 10)
Người hợp nhấtBản vá đã hợp nhấtTự viếtTỷ lệ hợp nhất
David S. Miller113.45615.6177.3x
Greg Kroah-Hartman105.7337.07315.0x
Linus Torvalds102.32245.1252.3x
Mark Brown49.6748.7595.7x
Mauro Carvalho Chehab39.8696.5716.1x
Alex Deucher37.0534.2018.8x
Ingo Molnar27.8705.6484.9x
Jakub Kicinski24.5095.0364.9x
Jens Axboe19.9853.7585.3x
John W. Linville18.8821.14616.5x

Ai chi trả cho kernel

Tổ chứcCommitTác giảCommit/Tác giả
Intel83,1871,70449
Red Hat72,695658110
kernel.org69,451227306
Linaro43,524263166
AMD42,2701,01742
SUSE35,711222161
Google29,27680936
Huawei24,15654045
Amazon1,68812114

Intel đứng thứ 1 về khối lượng (83K commit, 1.704 kỹ sư). Red Hat đứng thứ 2 nhưng có đội ngũ năng suất nhất: 110 commit mỗi kỹ sư. Các người duy trì kernel.org (227 người) đạt trung bình 306 commit mỗi người. Đây chính là nhóm nhân sự tinh nhuệ.

Amazon nổi bật ở cuối bảng: 14 commit mỗi người. Họ tập trung vào ảo hóa Xen/KVM cho AWS, thay vì các công việc rộng hơn trên kernel. (Lưu ý: IBM chỉ hiển thị 53 commit vì kỹ sư của họ sử dụng @linux.ibm.com@linux.vnet.ibm.com, khiến họ rơi vào nhóm "Khác". Tương tự, nhiều kỹ sư Huawei sử dụng @hisilicon.com.)

Các cá nhân đóng góp (địa chỉ Gmail, đại diện cho những người làm việc như một sở thích) đã đạt đỉnh 12% tổng số commit vào năm 2010. Đến năm 2025, con số này giảm xuống còn 8%. Số lượng tuyệt đối vẫn ổn định (~7K/năm), nhưng kernel ngày càng mang tính doanh nghiệp hơn theo thời gian.

Xu hướng Gmail so với doanh nghiệp qua thời gian
NămCommit từ GmailTổng sốTỷ lệ Gmail %
200545216,6962%
20085,60448,84711%
20106,09149,81912% (đỉnh)
20148,60275,65911%
20187,39380,3309%
20227,43886,8108%
20257,16085,1638%

Commit "nhiều lỗi nhất" trong lịch sử Linux

Kernel có một quy ước: thẻ Fixes: trong tin nhắn commit tham chiếu đến chính xác commit đã gây ra lỗi. Đến năm 2026, hơn 1 trong 4 commit sử dụng nó (tăng từ gần như bằng 0 trước năm 2013).

Commit nào có nhiều tham chiếu Fixes: nhất? 1da177e4c3f4. Bản import git đầu tiên của Linus Torvalds. Ngày 16 tháng 4 năm 2005. 665 bản sửa lỗi trỏ về commit này.

Thực tế nó không hẳn là lỗi. Khi một lỗi đã tồn tại "mãi mãi" và không có commit cụ thể nào để đổ lỗi, các nhà phát triển trích dẫn 1da177e4c3f4 như một cách viết tắt cho "cái này đã luôn bị hỏng".

Commit được sửa nhiều thứ hai: dd08ebf6c352, việc giới thiệu driver GPU Xe của Intel. 196 bản sửa lỗi trong khoảng 2 năm. Một bản sửa lỗi mỗi 4 ngày kể từ khi driver này được tích hợp.

Commit lịch sự, code đầy giận dữ

Có 7 từ chửi thề (f-bomb) trong 1,4 triệu tin nhắn commit. Tất cả đều đến từ chính xác 2 người: Al Viro (5) và Linus Torvalds (2).

Nhưng mã nguồn lại kể một câu chuyện khác. pgit search "fuck" --path "*.c" --path "*.h" đã tìm thấy 8 kết quả khớp trong codebase hiện tại. Chạy cùng tìm kiếm đó với --all (mọi phiên bản của mọi tệp trong 20 năm lịch sử) đã tìm thấy hơn 50 kết quả trong 44 giây. Các điểm đáng chú ý:

  • "Am I fucking pedantic or what?" (Tiêu đề driver SCSI, vẫn còn trong code ngày nay)
  • "Ugly, ugly fucker." (Tiêu đề netfilter, hiện diện từ commit đầu tiên, đã sống sót qua 20 năm đánh giá code)
  • "fucking gcc" (Tiêu đề B-tree của XFS, xuất hiện hai lần)
  • "If you fuck with this, update ret_from_syscall code too" (Kiến trúc SPARC)
Thống kê đầy đủ từ ngữ tục tĩu trong tin nhắn commit

Các con số này chỉ tính từ tin nhắn commit, không phải mã nguồn. Sử dụng regex ranh giới từ của PostgreSQL (\y) để tránh kết quả dương tính giả ("ass" trùng với "class", "hell" trùng với "shell"):

TừSố lượngGhi chú
workaround8,435Không phải tục tĩu, nhưng cho thấy nỗi đau: 8,435 lần ai đó không thể sửa được vấn đề thực sự
hack2,438Sự tự đánh giá trung thực của kernel
ugly2,161
stupid533
crap268
damn81
shit29
fuck7

Và trong mã nguồn, một số "viên ngọc" quý:

TệpBình luận
sound/oss/forte.c"FIXME HACK FROM HELL!"
arch/powerpc/sysdev/todc.c"XXXX BAD HACK -> FIX" (×4, và nó đã được sao chép sang arch/ppc/syslib/todc_time.c mà không được sửa)
drivers/staging/dgap/ (5 tệp)NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!

Triple revert

Chỉ có 3 commit trong toàn bộ lịch sử Linux là triple revert (một lệnh revert của một lệnh revert của một lệnh revert).

Greg KH về Lustre (hệ thống tệp HPC): "Chúng ta có thể làm việc này bao nhiêu lần nữa đây..."

Linus về một cờ quản lý bộ nhớ: "Đây là một lệnh revert của một lệnh revert của một lệnh revert." Driver GPU i915 đã sử dụng một cờ không nên dùng, và việc gỡ rối nó mất ba chu kỳ revert.

Cả ba đều nằm trong phần quản lý bộ nhớ hoặc staging. Các phân hệ nơi những thay đổi có tác động sâu rộng, khó dự đoán.

Kent Overstreet: 13 năm, một hệ thống tệp

Commit kernel đầu tiên của Kent Overstreet là vào năm 2011: bcache, một lớp bộ nhớ đệm block. Đến năm 2013 nó đã có mặt trong mainline với 213 commit. Sau đó anh ấy im hơi lặng tiếng. 4 đến 34 commit mỗi năm từ 2014 đến 2017, viết lại toàn bộ mọi thứ bên ngoài cây kernel thành một hệ thống tệp hoàn chỉnh.

Năm 2023, bcachefs được hợp nhất vào mainline (kernel 6.7). 904 commit trong năm đó. 1.194 vào năm tiếp theo. Anh ấy viết code vào ngày đầu năm mới trong 3 năm khác nhau, từ 1 giờ sáng đến 4 giờ sáng. 27% commit của anh ấy là vào cuối tuần. Khi việc hợp nhất gây tranh cãi, anh ấy vẫn tiếp tục.

Thêm nhiều câu chuyện về kernel

Các chiến binh cuối tuần:

Tác giảCommit cuối tuầnTổng sốTỷ lệ cuối tuần %
Jonathan Cameron1,1762,29551.2%
Christophe JAILLET1,0612,08650.9%
Kent Overstreet1,4155,21727.1%
Hans de Goede1,3944,62730.1%
Linus Torvalds10,72945,27423.7%

Jonathan Cameron và Christophe JAILLET thực hiện hơn một nửa công việc kernel của họ vào cuối tuần. Họ là những người đóng góp không chuyên, duy trì các driver trong thời gian rảnh rỗi.

Những người tận tụy với một tệp duy nhất:

Toàn bộ sự nghiệp kernel của Connor McAdams (89 commit) là một driver card âm thanh Creative Labs duy nhất (patch_ca0132.c). Lydia Wang (63 commit) dành trọn tâm huyết cho codec âm thanh VIA. Hai người riêng biệt, Pavel Rojtberg và Cameron Gutman, đã độc lập dành sự đóng góp kernel của họ chỉ cho driver bộ điều khiển Xbox (xpad.c).

Hành trình sự nghiệp:

James Bottomley (người duy trì SCSI) đã commit từ 19 tên miền email khác nhau trong 20 năm. Git log của anh ấy CHÍNH LÀ sơ yếu lý lịch của anh ấy: SteelEye → HP → Parallels → Odin → và nhiều hơn nữa. Linus có 12 tên miền. David S. Miller có 11.

Commit vào ngày Giáng sinh:

Kernel chưa bao giờ có một ngày Giáng sinh nào với số lượng commit bằng 0 trong suốt 21 năm qua. Năm 2008 ghi nhận 157 commit vào ngày 25 tháng 12 (trong đợt cao điểm hợp nhất x86). Ngay cả trong ngày Giáng sinh yên tĩnh nhất (năm 2005, với 1 commit), vẫn có ai đó đang làm việc.

Ngày bận rộn nhất:

Ngày 18 tháng 11 năm 2022: 662 commit. Một cá nhân (Uwe Kleine-König) đã thực hiện 583 trong số đó trong một đợt chuyển đổi kiểu trả về platform_driver hàng loạt. Ngày bận rộn thứ hai là 30 tháng 1 năm 2008 (640 commit): ba lập trình viên duy trì hơn 600 commit/ngày trong ba ngày liên tiếp trong quá trình hợp nhất x86.

Khoảng cách về văn hóa ghi chú commit (commit message):

Jeff Garzik trung bình viết 161 byte cho mỗi thông điệp commit. Filipe Manana (Btrfs) trung bình viết 1.950 byte. Một khoảng cách gấp 12 lần. Toàn bộ hệ thống con quản lý bộ nhớ (mm/) thường có xu hướng viết dài dòng: 3 người đóng góp hàng đầu đều nằm trong top 5 người viết thông điệp dài nhất. Khi các lỗi của bạn tinh vi và gây hậu quả nghiêm trọng, bạn buộc phải giải thích chi tiết.

Driver GPU là "thỏi nam châm" thu hút các lệnh hoàn tác (revert):

drm/amd/display (191 lượt revert) + drm/amdgpu (127) + drm/i915 (147) = 516 lượt revert liên quan đến GPU, chiếm gần 10% tổng số lượt revert trong toàn bộ kernel. Mã nguồn hiển thị (display code) có các tương tác phần cứng phức tạp, các máy trạng thái quản lý điện năng và các API userspace nhạy cảm với hồi quy (regression).

Hiệu suất truy vấn

Tất cả những nội dung trên đã được truy vấn trên một cơ sở dữ liệu có 1,4 triệu commit. Dưới đây là thời gian thực hiện:

Truy vấnThời gian
Thống kê + thông tin nén2.1s
Churn (24.4 triệu file refs)2.3s
Hotspots1.8s
Coupling (tính toán bằng Go)48.3s
Authors (quét toàn bộ commit)34.3s
Hoạt động (hàng năm)9.4s
Ngày trong tuần / giờ trong ngày4.2-4.4s
Tìm kiếm toàn văn (file hiện tại)25s
Tìm kiếm toàn văn (toàn bộ lịch sử)44s

Không có materialized view. Không tiền xử lý. Chỉ đơn giản là SQL trên PostgreSQL với phương pháp nén delta pg-xpatch.

Tất cả các lệnh SQL được sử dụng trong phân tích này
# Storage & compression (2.1s)
pgit stats --xpatch
# Churn (2.3s)
pgit analyze churn --limit 30
# Hotspots (1.8s)
pgit analyze hotspots --depth 1 --limit 25
# Authors (34.3s)
pgit analyze authors --limit 30 --timeout 60m
# Activity (9.4s)
pgit analyze activity --period year --limit 25 --timeout 60m
# Coupling (48.3s)
pgit analyze coupling --limit 30 --timeout 60m
# Merge hierarchy (4.6s)
pgit sql "SELECT committer_name, COUNT(*) as merged,
  SUM(CASE WHEN author_name = committer_name THEN 1 ELSE 0 END) as self_authored
  FROM pgit_commits GROUP BY committer_name ORDER BY merged DESC LIMIT 15"
# Corporate contributions (5.4s)
pgit sql "SELECT
  CASE
    WHEN author_email LIKE '%%@intel.com' THEN 'Intel'
    WHEN author_email LIKE '%%@redhat.com' THEN 'Red Hat'
    WHEN author_email LIKE '%%@kernel.org' THEN 'kernel.org'
    -- ... (full domain mapping)
  END as org,
  COUNT(*) as commits, COUNT(DISTINCT author_email) as authors
  FROM pgit_commits GROUP BY org ORDER BY commits DESC"
# Fixes: tag evolution (4.5s)
pgit sql "SELECT EXTRACT(YEAR FROM authored_at)::int as year,
  SUM(CASE WHEN message ~* 'Fixes:\s+[0-9a-f]{12}' THEN 1 ELSE 0 END) as fixes_commits,
  COUNT(*) as total
  FROM pgit_commits GROUP BY year ORDER BY year"
# Most-fixed commits (4.9s)
pgit sql "SELECT SUBSTRING(message FROM 'Fixes:\s+([0-9a-f]{12})') as broken_commit,
  COUNT(*) as times_fixed
  FROM pgit_commits
  WHERE message ~* 'Fixes:\s+[0-9a-f]{12}'
  GROUP BY broken_commit ORDER BY times_fixed DESC LIMIT 10"
# Profanity with word boundaries (~5s)
pgit sql "WITH words(word) AS (VALUES ('fuck'),('shit'),('damn'),('stupid'),('crap'),('ugly'),('hack'),('workaround'))
  SELECT w.word, COUNT(*) as cnt
  FROM pgit_commits c, words w
  WHERE c.message ~* ('\y' || w.word || '\y')
  GROUP BY w.word ORDER BY cnt DESC"
# Source code search
pgit search "fuck" --path "*.c" --path "*.h"
pgit search "fuck" --path "*.c" --path "*.h" --all
# Triple reverts (5.7s)
pgit sql "SELECT author_name, authored_at::date, LEFT(message, 200)
  FROM pgit_commits
  WHERE message ILIKE 'Revert \"Revert \"Revert%%'"
# Kent Overstreet trajectory (4.1s)
pgit sql "SELECT EXTRACT(YEAR FROM authored_at)::int as year, COUNT(*)
  FROM pgit_commits WHERE author_name = 'Kent Overstreet'
  GROUP BY year ORDER BY year"
# Weekend warriors (1m 41s)
pgit sql "SELECT author_name, COUNT(*) as weekend_commits,
  (SELECT COUNT(*) FROM pgit_commits c2 WHERE c2.author_name = c.author_name) as total
  FROM pgit_commits c WHERE EXTRACT(DOW FROM authored_at) IN (0, 6)
  GROUP BY author_name ORDER BY weekend_commits DESC LIMIT 15"

Liên kết

pgit có thể xử lý Linux kernel. Đó là câu hỏi mà tôi muốn trả lời. Nó đã nhập, nén và giúp cho 20 năm lịch sử có thể truy vấn được trong vài giây.

Kể từ bài đăng về pgit, ripgit đã được xây dựng dựa trên xpatch: một git remote tự host được hỗ trợ bởi Cloudflare Durable Objects với bộ lưu trữ SQLite và nén delta. Thật tuyệt vời khi thấy hệ sinh thái đang phát triển.

go install github.com/imgajeed76/pgit/v4/cmd/pgit@latest

Tác giả: ImGajeed76

#discussion