Sistem günlüğü neden dosya ES'sinden daha yavaş?


9

Syslog fonksiyonunun performansını ölçmek için basit bir test programı yazdım. Test sistemimin sonuçları: (Linux 2.6.32-5-amd64 ile Debian 6.0.2)

Test Vaka Çağrı Yükü Süresi Düşüncesi 
                      [] [MB] [s] [MB / s]    
-------------------- ---------- ---------- ---------- ----------
syslog 200000 10.00 7.81 1.28      
syslog% s 200000 10.00 9.94 1.01      
yazma / dev / null 200000 10.00 0.03 343.93    
printf% s 200000 10,00 0,13 76,29     

Test programı, her çağrı sırasında 50 bayt veri yazarak 200000 sistem çağrısı yaptı.

Syslog neden dosya ES'sinden on kat daha yavaş?

Bu testi yapmak için kullandığım program:

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

Muhtemelen, syslog çağrıları daha karmaşıktır, bir "mesaj ve yanıt" mekanizması ile daha fazla yüke sahiptir, birden fazla kullanıcı alanı işlemi arasında seyahat eder (bir cihaza veya konsola yazmanın aksine) ve mesaj başarıyla tamamlanana kadar geri dönmez kabul edilmiş.
afrazier

1
Richard'ın cevabına göre, fprintf () 'den sonra fflush (fp) eklerseniz sayılar benzer mi?
Eyl332

@ sep3332 İşleve O_SYNCbayrak ekledikten sonra open()ve fflush(fp)her fprintf()aramadan sonra sonuçlar [3.86, 3.63, 151.53, 23.00] MB/sbilgisayarımda olur (Lenovo T61, Debian testi). Şimdi daha iyi görünüyor, ancak kontrol edin /etc/rsyslog.conf, zaten syslog'lar için senkronize olmayan modda.
Xiè Jìléi

Yanıtlar:


11

Sistem günlüğü çağrıları her çağrı için bir AF_UNIX soketine bir send () gönderir. Syslogd veriyi atsa bile, önce onu okuması gerekir. Bütün bunlar zaman alır.

/ Dev / null öğesine yazma işlemleri de çağrı başına bir write () gönderir, ancak veriler atıldığından çekirdek tarafından çok hızlı bir şekilde işlenebilir.

Fprintf () çağrıları, aktarılan her 4096 bayt için yalnızca bir yazma () oluşturur, yani yaklaşık seksen printf çağrısından biri. Her biri sadece libc'nin tamponundan çekirdeğin tamponlarına veri aktarmayı içerir. Diske bağlılık (en azından karşılaştırıldığında) çok yavaş olacaktır, ancak herhangi bir açık senkronizasyon çağrısının yokluğunda daha sonra (belki de işlem sonlandıktan sonra bile) gerçekleşebilir.

Kısacası: syslog, / dev / null değerinden daha yavaş çünkü çok fazla iş yapıyor ve arabelleğe alma nedeniyle bir dosyaya printf'den daha yavaş.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.