在前面多語言測試中,遇到一個難以置信的問題,rust的輸出到文件比c語言還快,這是不合情理的,通過對兩者輸出語句的比較,發現了不同。
rust程序在輸出到stdout前有這么一句
let mut writer = BufWriter::with_capacity(64 * 1024, stdout.lock());
而c語言是直接輸出。
將上述語句發給DeepSeek,它給出了等價的C語言實現。
#define BUFFER_SIZE (64 * 1024) // 64KB 緩沖區// 設置 stdout 緩沖char buffer[BUFFER_SIZE];if (setvbuf(stdout, buffer, _IOFBF, sizeof(buffer)) != 0) {perror("setvbuf failed");return EXIT_FAILURE;}// 原輸出語句// 刷新緩沖區if (fflush(stdout) != 0) {perror("fflush failed");return EXIT_FAILURE;}
加入上述語句的c代碼編譯運行情況如下:
gcc sort_lines_buf.c -o csortbuf -O3
time ./csortbuf varchar.txt >vvc.txtreal 0m1.367s
user 0m0.431s
sys 0m0.086s
time ./csortbuf varchar.txt >/dev/nullreal 0m0.792s
user 0m0.406s
sys 0m0.063s
而加入緩沖前
time ./c_sort varchar.txt >vvc.txtreal 0m3.568s
user 0m0.439s
sys 0m0.226s
time ./c_sort varchar.txt >/dev/nullreal 0m0.758s
user 0m0.335s
sys 0m0.080s
可見,緩沖后輸出到文件的時間縮短到原來的1/3,而不輸出文件的保持不變。
需要指出,這個緩沖區并非越大越好,它受限于棧容量,如果改成從堆分配和文件大小一樣的內存做緩沖區,反而比不緩沖更慢。
完整帶緩沖輸出c代碼摘錄如下。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>#define MAX_LINES 1000000 // 最多100萬行
#define BUFFER_SIZE (64 * 1024) // 64KB 緩沖區
int compare_offsets(const void *a, const void *b) {return strcmp(*(const char **)a, *(const char **)b);
}int main(int argc, char *argv[]) {if (argc != 2) {fprintf(stderr, "Usage: %s <filename>\n", argv[0]);return 1;}// 打開文件并獲取大小int fd = open(argv[1], O_RDONLY);if (fd == -1) {perror("open");return 1;}struct stat st;if (fstat(fd, &st) == -1) {perror("fstat");close(fd);return 1;}size_t file_size = st.st_size;// 分配緩沖區并讀取文件char *buf = malloc(file_size + 1);if (!buf) {perror("malloc");close(fd);return 1;}if (read(fd, buf, file_size) != file_size) {perror("read");free(buf);close(fd);return 1;}close(fd);buf[file_size] = '\0'; // 確保以null結尾// 記錄每行起始地址char *lines[MAX_LINES];size_t line_count = 0;lines[line_count++] = buf; // 第一行開始// 遍歷緩沖區,記錄每行起始地址并將\n替換為\0for (char *p = buf; *p && line_count < MAX_LINES; p++) {if (*p == '\n') {*p = '\0';if (*(p + 1)) { // 如果不是文件末尾lines[line_count++] = p + 1;}}}// 對行指針數組進行排序qsort(lines, line_count, sizeof(char *), compare_offsets);// 設置 stdout 緩沖char buffer[BUFFER_SIZE];if (setvbuf(stdout, buffer, _IOFBF, sizeof(buffer)) != 0) {perror("setvbuf failed");return EXIT_FAILURE;}// 寫入數據for (int i = 0; i < line_count; i++) {if (printf("%s\n", lines[i]) < 0) {perror("printf failed");return EXIT_FAILURE;}}// 刷新緩沖區if (fflush(stdout) != 0) {perror("fflush failed");return EXIT_FAILURE;}free(buf);return 0;
}