LINUX.ORG.RU

Исследование производительности *printf и вывода в файл


0

0

Ввиду того, что я так и не получил вразумительного ответа тут: http://www.linux.org.ru/view-message.jsp?msgid=1561742 решил провести самостоятельное тестирование. Если есть возможность - протестируйте на своей платформе.

Сначала о платформе, на которой эти тесты проводились:
- CPU: AMD Athlon Thunderbird 850@977 (1956 bogomips);
- RAM: 256Mb PC133@115;
- HDD: 80Gb 7200rpm 8Mb WDC WD800BB-00JHA0 (fw: 05.01C05).
- OS: Slackware Linux 10.2+current;
- KERNEL: 2.6.17 (с www.kernel.org).

Список процессов (не ядерных) перед тестированием:
1215 ? Ss 0:00 /usr/sbin/syslogd
1218 ? Ss 0:00 /usr/sbin/klogd -c 3 -x
1300 ? Ss 0:00 /usr/sbin/gpm -m /dev/mouse -t imps2
1397 tty1 Ss 0:00 -bash
21639 tty1 S+ 0:00 \_ /usr/bin/mc -P /tmp/mc-root/mc.pwd.1397
21640 ? Ss 0:00 \_ cons.saver /dev/vc/1
21641 pts/0 Ss 0:00 \_ bash -rcfile .bashrc
22279 pts/0 R+ 0:00 \_ ps axf
1399 tty3 Ss+ 0:00 /sbin/agetty 38400 tty3 linux
21569 tty2 Ss 0:00 -bash
21589 tty2 S+ 0:00 \_ mcedit /tresult.txt
21590 ? Ss 0:00 \_ cons.saver /dev/vc/2

#include <limits.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


int main() {
FILE *test;
time_t t1, t2;
char tbuf[8192] = "\000";
int i = 0;

double d1 = 32768.0;
double d2 = 111111111111.0;
double d3 = 22222222222222222222222.0;

char *s1 = "s1";
char *s2 = "s2mid";
char *s3 = "s3 very-very long";

short int si1 = 1;
short int si2 = 256;
short int si3 = 32765;

int i1 = 1;
int i2 = 65536;
int i3 = 1122334455;

char c1 = '1';
char c2 = '[';
char c3 = '\n';


test = fopen("/testfile", "w");

t1 = time(NULL);
while (i++ < 8000001) {
/* 1: sprintf+fputs
sprintf(tbuf, "%c %hd %d <t1> %'.0f %c <text2> %s %d %s <middle text3> %hd %c %'.0f %d %s %'.0f %hd",
c1, si1, i1, d1, c2, s1, i2, s2, si2, c3, d2, i3, s3, d3, si3);
fputs(tbuf, test);*/

/* 2: sprintf+fwrite
sprintf(tbuf, "%c %hd %d <t1> %'.0f %c <text2> %s %d %s <middle text3> %hd %c %'.0f %d %s %'.0f %hd",
c1, si1, i1, d1, c2, s1, i2, s2, si2, c3, d2, i3, s3, d3, si3);
fwrite(tbuf, strlen(tbuf), 1, test);*/

/* 3: fprintf
fprintf(test, "%c %hd %d <t1> %'.0f %c <text2> %s %d %s <middle text3> %hd %c %'.0f %d %s %'.0f %hd",
c1, si1, i1, d1, c2, s1, i2, s2, si2, c3, d2, i3, s3, d3, si3);*/

/* 4: 15x fprintf
fprintf(test, "%c ", c1);
fprintf(test, "%hd ", si1);
fprintf(test, "%d ", i1);
fprintf(test, "<t1> %'.0f ", d1);
fprintf(test, "%c ", c2);
fprintf(test, "<text2> %s ", s1);
fprintf(test, "%d ", i2);
fprintf(test, "%s ", s2);
fprintf(test, "<middle text3> %hd ", si2);
fprintf(test, "%c ", c3);
fprintf(test, "%'.0f ", d2);
fprintf(test, "%d ", i3);
fprintf(test, "%s ", s3);
fprintf(test, "%'.0f ", d3);
fprintf(test, "%hd", si3);*/

/* 5: 15x sprintf+1x fwrite */
sprintf(tbuf, "%c ", c1);
sprintf(&tbuf[strlen(tbuf)], "%hd ", si1);
sprintf(&tbuf[strlen(tbuf)], "%d ", i1);
sprintf(&tbuf[strlen(tbuf)], "<t1> %'.0f ", d1);
sprintf(&tbuf[strlen(tbuf)], "%c ", c2);
sprintf(&tbuf[strlen(tbuf)], "<text2> %s ", s1);
sprintf(&tbuf[strlen(tbuf)], "%d ", i2);
sprintf(&tbuf[strlen(tbuf)], "%s ", s2);
sprintf(&tbuf[strlen(tbuf)], "<middle text3> %hd ", si2);
sprintf(&tbuf[strlen(tbuf)], "%c ", c3);
sprintf(&tbuf[strlen(tbuf)], "%'.0f ", d2);
sprintf(&tbuf[strlen(tbuf)], "%d ", i3);
sprintf(&tbuf[strlen(tbuf)], "%s ", s3);
sprintf(&tbuf[strlen(tbuf)], "%'.0f ", d3);
sprintf(&tbuf[strlen(tbuf)], "%hd", si3);
fwrite(tbuf, strlen(tbuf), 1, test);
}
t2 = time(NULL);
fprintf(stderr, "TIME ELAPSED: %d\n", (int)(t2 - t1));

fclose(test);

return 0;
}

В следующих сообщениях отпишу по каждому алгоритму полученные результаты, m16/a256 - это параметры hdparm.

★★★★★

1x sprintf + 1x fputs

Размер исполняемого файла: 11948
1x sprintf+1x fputs m16/a256: 135, 139, 135
real 2m15.210s
user 2m4.284s
sys 0m8.934s

1x sprintf+1x fputs m16/a16: 136, 137, 136
real 2m15.622s
user 2m3.646s
sys 0m9.934s

saper ★★★★★
() автор топика

1x sprintf + 1x fwrite

Размер исполняемого файла: 12028
1x sprintf+1x fwrite m16/a256: 136, 136, 136
real 2m15.455s
user 2m3.955s
sys 0m9.444s

1x sprintf+1x fwrite m16/a16: 135, 135, 135
real 2m15.574s
user 2m4.337s
sys 0m9.027s

saper ★★★★★
() автор топика

1x fprintf

Размер исполняемого файла: 11796
1x fprintf m16/a256: 129, 129, 128
real 2m8.674s
user 1m56.729s
sys 0m9.706s

1x fprintf m16/a16: 128, 128, 129
real 2m7.762s
user 1m56.738s
sys 0m9.001s

saper ★★★★★
() автор топика

15x fprintf

Размер исполняемого файла: 11988
15x fprintf m16/a16: 152, 147, 147
real 2m27.240s
user 2m16.216s
sys 0m9.105s

15x fprintf m16/a256: 147, 147, 147
real 2m27.192s
user 2m16.038s
sys 0m9.225s

saper ★★★★★
() автор топика

15x sprintf + 1x fwrite

Размер исполняемого файла: 12988
15x sprintf+1x fwrite m16/a256: 175, 175, 176
real 2m55.090s
user 2m43.976s
sys 0m9.187s

15x sprintf+1x fwrite m16/a16: 175, 178, 176
real 2m55.581s
user 2m44.469s
sys 0m9.038s

saper ★★★★★
() автор топика

Размер итогового testfile во всех тестах получался одинаковым ~1Гб (1'072'000'134 байт). В четвертом тесте (результаты приведены для исправленного кода) забыл поставить пробелы после символов форматирования в каждом fprintf, при этом получил итоговый файл размером 960'xxx'xxx'xxx (x забыл записать), а время выданное программой составило: 134, 133, 132.

Везде приведены результаты для 3-х испытаний, в сильных отклонениях склонен винить другие процессы (syslogd).

Мои выводы такие:
1. Если нужно выводить длинные строки с форматированием нескольких переменных и выводом в файл, то нужно использовать fprintf.
2. Если то же самое как в п.1, но вывести в один момент времени можно только одну переменную (в силу организации/запутанности чужого кода) все равно выгодно использовать fprintf.

saper ★★★★★
() автор топика

Скрипт, который вызывался одной строкой 3 раза подряд:
#!/bin/sh

gcc -Wall -march=athlon-tbird -O20 -ffast-math -fomit-frame-pointer -maccumulate-outgoing-args test.c -o test
strip test
rm -f /testfile
sync
sync
sleep 15
time ./test
ls -l /testfile
ls -l /test

saper ★★★★★
() автор топика
Ответ на: комментарий от saper

>К чему вы это написали?

Измерить "скорость работы fprintf" этим тестом это бред.

Ты своим тестом измеряеш непонятно что и непонятно зачем.

В нём взаимодействует столько систем что результаты будут зависеть от всего включая фвзы луны. В основном будет влиять диск, свободный обём памяти под дисковый кеш и настройки vm.

Хочешь померять скорость именно _операции_ fprintf ?

1) test = fopen("/dev/null", "w");

2) вставляем/убираем в цикле сброс всех буферов fflush(NULL);

Результаты должен отличаться минимально

sS ★★★★★
()
Ответ на: комментарий от sS

> Измерить "скорость работы fprintf" этим тестом это бред.

А для меня - нет.

> Ты своим тестом измеряеш непонятно что и непонятно зачем.

Я измеряю скорость программы, построенной с использованием тех или иных алгоритмов форматирования и вывода в файл. Сырая скорость fprintf мне не нужна, тесты делались, чтобы улучшить существующее приложение.

> Результаты должен отличаться минимально.

Если так, то зачем надменно писать столько оскорбительных фраз?

saper ★★★★★
() автор топика
Ответ на: комментарий от saper

>> Измерить "скорость работы fprintf" этим тестом это бред.

>А для меня - нет.

Ну хозяин-барин, как говорится ;)

>Я измеряю скорость программы, построенной с использованием тех или иных алгоритмов форматирования и вывода в файл. Сырая скорость fprintf мне не нужна,

Ты измеряешь непонятно что. Это напоминает диссертацию "О влиянии лунного света на рост телеграфных столбов". Или ты этого не понимаешь ?

>> Результаты должен отличаться минимально.

>Если так, то зачем надменно писать столько оскорбительных фраз?

Извини если обидел тебя лично чем то, но я обычно то что вижу то и говорю.

Попробуй вставить fflush() в свой тест (без /dev/null) и убедись в том что его время возрастёт раза этак в полтора. И если поиграть с параметрами диска то результаты будут еще смешнее.

Или ты действительно не понимаешь что пытаешся поймать +-0.1% для одной системы когда другая даёт тебе +-10% ?

Ну как говорится CCЗБ.

PS: Ничего личного ;)

sS ★★★★★
()
Ответ на: комментарий от sS

> Попробуй вставить fflush() в свой тест (без /dev/null) и убедись в том что его время возрастёт раза этак в полтора. И если поиграть с параметрами диска то результаты будут еще смешнее.

Если я так сделаю, то это не совсем будет похоже на мое приложение. IMHO особого смысла нет fflush-ить, когда в поток вывелось всего 2-3 байта, тем более относительные результаты будут такими же (а вот абсолютные - да, раза в полтора больше).

saper ★★★★★
() автор топика
Ответ на: комментарий от saper

В чём смысл теста? Определить как бестрее на _данной_конкретной_ машине загнать на диск гигабайт всякого форматированного хлама ? :-) Тест совершенно ничего не показывает. Если хочешь проверить, что быстрее работает fprintf или sprintf + write или что-то там ещё, то воспользуйся советом выше c /dev/null. Сама по себе запись на диск только вносит большую (культурно говоря) погрешность в твой тест.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.