为什么syslog比文件IO慢得多?


9

我编写了一个简单的测试程序来测量syslog函数的性能。这是我的测试系统的结果:(带有Linux 2.6.32-5-amd64的Debian 6.0.2)

测试用例调用有效负载持续时间 
                      [] [MB] [s] [MB / s]    
-------------------- ---------- ---------- ---------- ----------
系统日志200000 10.00 7.81 1.28      
系统日志%s 200000 10.00 9.94 1.01      
写/ dev / null 200000 10.00 0.03 343.93    
printf%s 200000 10.00 0.13 76.29     

测试程序进行了200000次系统调用,每次调用期间写入50字节数据。

为什么Syslog比文件IO慢十倍?

这是我用来执行测试的程序:

#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 ();
}

据推测,系统日志调用更为复杂,具有“消息和响应”机制,具有更多的开销,在多个用户空间进程之间移动(与写入设备或控制台不同),并且只有在消息成功发送后才会返回公认。
afrazier 2011年

1
根据Richard的回答,如果在fprintf()之后添加fflush(fp),数字看起来是否相似?
2012年

@ sep3332在函数中添加O_SYNC标志之后,每次调用之后,结果将存储在我的计算机中(Lenovo T61,Debian测试)。现在似乎更好,但是,检查,它已经处于syslog的非同步模式。open()fflush(fp)fprintf()[3.86, 3.63, 151.53, 23.00] MB/s/etc/rsyslog.conf
谢耶利(YièJìléi)

Answers:


11

每次调用时,syslog调用都向AF_UNIX套接字发出一个send()。即使syslogd丢弃了数据,也仍然必须先读取它。这一切都需要时间。

对/ dev / null的写入也会在每次调用时发出一个write(),但是由于数据被丢弃,因此内核可以非常快速地对其进行处理。

fprintf()调用仅每传输4096个字节生成一个write(),即大约每80个printf调用生成一个write()。每个都只涉及将数据从libc的缓冲区传输到内核的缓冲区。提交磁盘(至少相比而言)会非常慢,但是在没有任何显式同步调用的情况下,稍后可能会发生(甚至在进程终止之后)。

简而言之:syslog比/ dev / null慢,因为它要执行很多工作,而由于缓冲,它比printf慢。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.