syslogがファイルIOよりもはるかに遅いのはなぜですか?


9

Syslog機能のパフォーマンスを測定するための簡単なテストプログラムを作成しました。これは私のテストシステムの結果です:(Debian 6.0.2 with Linux 2.6.32-5-amd64)

テストケースがペイロード期間の思想を呼び出す 
                      [] [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、Debianテスト)。現在はより良いように見えますが、確認してください/etc/rsyslog.conf、syslogの非同期モードになっています。
謝Jìléi

回答:


11

syslog呼び出しは両方とも、呼び出しごとに1つのsend()をAF_UNIXソケットに発行します。syslogdがデータを破棄しても、最初にそれを読み取る必要があります。これにはすべて時間がかかります。

/ dev / nullへの書き込みも、呼び出しごとに1つのwrite()を発行しますが、データは破棄されるため、カーネルで非常に高速に処理できます。

fprintf()呼び出しは、転送される4096バイトごとに1つのwrite()のみを生成します。それぞれ、libcのバッファーからカーネルのバッファーにデータを転送するだけです。ディスクへのコミットは(少なくとも比較すると)非常に遅くなりますが、明示的な同期呼び出しがない場合、後で(おそらくプロセスが終了した後でも)発生する可能性があります。

要約すると、syslogは多くの作業を行っているため/ dev / nullよりも遅く、バッファリングのためにファイルへのprintfよりも遅くなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.