Tại sao syslog chậm hơn nhiều so với tệp IO?


9

Tôi đã viết một chương trình thử nghiệm đơn giản để đo hiệu suất của chức năng nhật ký hệ thống. Đây là kết quả của hệ thống thử nghiệm của tôi: (Debian 6.0.2 với Linux 2.6.32-5-amd64)

Trường hợp thử nghiệm Gọi thời gian tải trọng 
                      [] [MB] [s] [MB / s]    
-------------------- ---------- ---------- ---------- ----------
syslog 200000 10,00 7,81 1,28      
syslog% s 200000 10,00 9,94 1,01      
viết / dev / null 200000 10,00 0,03 343,93    
inf% s 200000 10,00 0,13 76,29     

Chương trình thử nghiệm đã thực hiện 200000 cuộc gọi hệ thống ghi 50 byte dữ liệu trong mỗi cuộc gọi.

Tại sao Syslog chậm hơn mười lần so với tệp IO?

Đây là chương trình tôi đã sử dụng để thực hiện bài kiểm tra:

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <syslog.h>
#include <unistd.h>

const int  iter  = 200000;
const char msg[] = "123456789 123456789 123456789 123456789 123456789";

struct timeval t0;
struct timeval t1;

void start ()
{
    gettimeofday (&t0, (void*)0);
}

void stop ()
{
    gettimeofday (&t1, (void*)0);
}

void report (char *action)
{
    double dt = (double)t1.tv_sec - (double)t0.tv_sec +
        1e-6 * ((double)t1.tv_usec - (double)t0.tv_usec);
    double mb = 1e-6 * sizeof (msg) * iter;

    if (action == NULL)
        printf ("Test Case             Calls       Payload     Duration    Thoughput \n"
                "                      []          [MB]        [s]         [MB/s]    \n"
                "--------------------  ----------  ----------  ----------  ----------\n");
    else {
        if (strlen (action) > 20) action[20] = 0;
        printf ("%-20s  %-10d  %-10.2f  %-10.2f  %-10.2f\n",
                action, iter, mb, dt, mb / dt);
    }
}

void test_syslog ()
{
    int i;

    openlog ("test_syslog", LOG_PID | LOG_NDELAY, LOG_LOCAL0);
    start ();
    for (i = 0; i < iter; i++)
        syslog (LOG_DEBUG, msg);
    stop ();
    closelog ();
    report ("syslog");
}

void test_syslog_format ()
{
    int i;

    openlog ("test_syslog", LOG_PID | LOG_NDELAY, LOG_LOCAL0);
    start ();
    for (i = 0; i < iter; i++)
        syslog (LOG_DEBUG, "%s", msg);
    stop ();
    closelog ();
    report ("syslog %s");
}

void test_write_devnull ()
{
    int i, fd;

    fd = open ("/dev/null", O_WRONLY);
    start ();
    for (i = 0; i < iter; i++)
        write (fd, msg, sizeof(msg));
    stop ();
    close (fd);
    report ("write /dev/null");
}

void test_printf ()
{
    int i;
    FILE *fp;

    fp = fopen ("/tmp/test_printf", "w");
    start ();
    for (i = 0; i < iter; i++)
        fprintf (fp, "%s", msg);
    stop ();
    fclose (fp);
    report ("printf %s");
}

int main (int argc, char **argv)
{
    report (NULL);
    test_syslog ();
    test_syslog_format ();
    test_write_devnull ();
    test_printf ();
}

Có lẽ, các cuộc gọi nhật ký hệ thống phức tạp hơn, với cơ chế "thông báo và phản hồi", có nhiều chi phí hơn, di chuyển giữa nhiều quy trình không gian người dùng (không giống như ghi vào thiết bị hoặc bảng điều khiển) và sẽ không quay lại cho đến khi tin nhắn thành công Đã được chấp nhận.
afrazier

1
Theo câu trả lời của Richard, các con số có giống nhau không nếu bạn thêm fflush (fp) sau fprintf ()?
sep32

@ sep3332 Sau khi thêm O_SYNCcờ vào open()chức năng và fflush(fp)sau mỗi fprintf()cuộc gọi, kết quả sẽ xuất hiện [3.86, 3.63, 151.53, 23.00] MB/strong máy tính của tôi (Lenovo T61, kiểm tra Debian). Bây giờ có vẻ tốt hơn nhưng, hãy kiểm tra /etc/rsyslog.conf, nó đã ở chế độ không đồng bộ hóa cho nhật ký hệ thống.
Xiè Jìléi

Câu trả lời:


11

Syslog gọi cả hai vấn đề một gửi () đến ổ cắm AF_UNIX cho mỗi cuộc gọi. Ngay cả khi syslogd loại bỏ dữ liệu, nó vẫn sẽ phải đọc nó trước. Tất cả điều này cần có thời gian.

Việc ghi vào / dev / null cũng phát hành một write () cho mỗi cuộc gọi nhưng vì dữ liệu bị loại bỏ nên nó có thể được xử lý rất nhanh bởi kernel.

Các lệnh gọi fprintf () chỉ tạo ra một write () cho mỗi 4096 byte được truyền, tức là cứ khoảng tám mươi cuộc gọi printf. Mỗi phần chỉ liên quan đến việc chuyển dữ liệu từ bộ đệm của libc sang bộ đệm của kernel. Cam kết với đĩa sẽ (ít nhất là so sánh) rất chậm, nhưng trong trường hợp không có bất kỳ cuộc gọi đồng bộ hóa rõ ràng nào có thể xảy ra sau đó (có lẽ ngay cả sau khi quá trình kết thúc).

Nói tóm lại: syslog chậm hơn / dev / null vì nó hoạt động rất nhiều và chậm hơn printf vào một tệp vì bộ đệm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.