syslog가 파일 IO보다 훨씬 느린 이유는 무엇입니까?


9

syslog 함수의 성능을 측정하는 간단한 테스트 프로그램을 작성했습니다. 이것은 내 테스트 시스템의 결과입니다 (Linux 2.6.32-5-amd64의 데비안 6.0.2)

테스트 케이스 호출 페이로드 지속 시간 생각 
                      [] [MB] [s] [MB / s]    
-------------------- ---------- ---------- ------------ ----------
syslog 200000 10.00 7.81 1.28      
syslog % 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     

테스트 프로그램은 각 호출 중에 50 바이트의 데이터를 쓰는 200000 개의 시스템 호출을 수행했습니다.

Syslog가 파일 IO보다 10 배 이상 느린 이유는 무엇입니까?

이것은 테스트를 수행하는 데 사용한 프로그램입니다.

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

아마도 syslog 호출은 "메시지 및 응답"메커니즘을 사용하여 더 복잡하고 오버 헤드가 더 많으며 (장치 또는 콘솔에 쓰는 것과 달리) 여러 사용자 공간 프로세스간에 이동하며, 메시지가 성공적으로 완료 될 때까지 반환되지 않습니다. 받아 들였다.
afrazier

1
Richard의 답변에 따르면 fprintf () 다음에 fflush (fp)를 추가하면 숫자가 비슷하게 보입니까?
sep332

@ sep3332 함수 에 O_SYNC플래그를 추가 open()하고 fflush(fp)fprintf()호출 후에 결과가 [3.86, 3.63, 151.53, 23.00] MB/s내 컴퓨터에 나타납니다 (Lenovo T61, 데비안 테스트). 지금은 나아 보였지만 check /etc/rsyslog.conf, 이미 syslogs의 비동기 모드에 있습니다.
Xiè Jìléi

답변:


11

syslog 호출은 호출 당 하나의 send ()를 AF_UNIX 소켓으로 발행합니다. syslogd가 데이터를 폐기하더라도 여전히 먼저 읽어야합니다. 이 모든 시간이 걸립니다.

/ dev / null에 대한 쓰기도 호출 당 하나의 write ()를 발행하지만 데이터가 삭제되므로 커널에서 매우 빠르게 처리 할 수 ​​있습니다.

fprintf () 호출은 전송 된 4096 바이트마다, 즉 약 80 개의 printf 호출마다 1 개의 write () 만 생성합니다. 각각은 libc의 버퍼에서 커널의 버퍼로 데이터를 전송하는 것만 포함합니다. 디스크에 대한 커밋은 (적어도 비교하면) 매우 느리지 만 명시적인 동기화 호출이 없으면 나중에 (아마도 프로세스가 종료 된 후에도) 발생할 수 있습니다.

간단히 말해 : syslog는 버퍼링으로 인해 파일에 대한 많은 작업을 수행하고 printf보다 파일을 느리게 수행하기 때문에 / dev / null보다 느립니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.