File system benchmark
Я провел небольшое исследование и сравнил производительность четырех файловых систем, которые поддерживаются в ядре
практически всеми основными дистрибутивами.
Речь идет о ext4, btrfs, xfs, jfs .
Нам понадобятся отдельная партиция размером желательно порядка 10 гигов, а также стандартные утилиты для создания файловых систем:
mkfs.ext4
mkfs.btrfs
mkfs.xfs
mkfs.jfs
В разных дистрибутивах эти утилиты могут лежать в разных пакетах. Например, для того чтобы в центосе установить xfs,
нужно выполнить
yum install xfsprogs-devel
yum install kmod-xfs xfsdump xfsprogs dmapi
а для btrfs соответственно
yum install btrfs*
В Suse соответственно нужно выполнить команды:
zypper in xfsprogs
zypper in btrfsprogs
zypper in jfsutils
Первый тест
Первый тест будет совсем простой. Будет создана файловая структура, в которую будет положено 200 тысяч мелких файлов
каждый размером в один килобайт. На моем подопытном компьютере винчестер - сата-шный, оперативной памяти - 2 гига, процессор - пень три гигагерца.
Параметры файловой системы берутся по умолчанию. При этом во всех случаях размер блока равен 4 килобайтам.
Итак, начинаем с ext4. Форматируем партицию, предварительно ее отмонтировав:
mkfs.ext4 /dev/sda10
Вывод:
mke2fs 1.42.4 (12-June-2012)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
960992 inodes, 3839527 blocks
191976 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=3934257152
118 block groups
32768 blocks per group, 32768 fragments per group
8144 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
Проверим результат форматирования:
fdisk -l /dev/sda10
Disk /dev/sda10: 15.7 GB, 15726703104 bytes
255 heads, 63 sectors/track, 1911 cylinders, всего 30716217 секторов
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Код утилиты для первого теста, которая сгенерирует 200 тысяч файлов:
#include < stdio.h>
#include < stdlib.h>
#include < unistd.h>
#include < fcntl.h>
#include < sys/stat.h>
#include < sys/types.h>
#include < time.h>
#include < sys/time.h>
static void doit(char *name) {
static char stuff[1024];
int fd;
fd = creat(name, 0666);
if (fd < 0) {
perror(name);
exit(1);
}
write(fd, stuff, sizeof(stuff));
close(fd);
}
int timeval_subtract (result, x, y)
struct timeval *result, *x, *y;
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec)
{
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000)
{
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
return x->tv_sec < y->tv_sec;
}
int main(void) {
int i, j, k, l;
char buf[100];
struct timeval tv1, tv2, diff;
gettimeofday(&tv1, NULL);
for (i = 0; i < 10; i++) {
sprintf(buf, "%d", i);
mkdir(buf, 0777);
for (j = 0; j < 10; j++) {
sprintf(buf, "%d/%d", i, j);
mkdir(buf, 0777);
printf("%s\n", buf);
for (k = 0; k < 10; k++) {
sprintf(buf, "%d/%d/%d", i, j, k);
mkdir(buf, 0777);
for (l = 0; l < 200; l++) {
sprintf(buf, "%d/%d/%d/%d", i, j, k, l);
doit(buf);
}
}
}
}
gettimeofday(&tv2, NULL);
int result = timeval_subtract(&diff, &tv2, &tv1);
printf("seconds: %d", diff.tv_sec);
exit(0);
}
Монтируем партицию.
Копируем утилиту на тестируемую партицию и запускаем.
Результат у меня для ext4 получился - 17 секунд.
Переходим к btrfs. Форматируем партицию, предварительно ее отмонтировав:
mkfs.btrfs /dev/sda10
Вывод:
fs created label (null) on /dev/sda10
nodesize 4096 leafsize 4096 sectorsize 4096 size 14.65GB
Результат для btrfs похуже - 24 секунды.
Переходим к xfs. Форматируем партицию:
mkfs.xfs -f /dev/sda10
Вывод:
meta-data=/dev/sda10 isize=256 agcount=4, agsize=959882 blks
= sectsz=512 attr=2, projid32bit=0
data = bsize=4096 blocks=3839527, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
Результат для xfs совсем плохой - 74 секунды, при этом винт нещадно хрустит.
Переходим к jfs. Форматируем партицию, предварительно ее отмонтировав:
mkfs.jfs /dev/sda10
Запускаем тест и получаем совершенно неприличный результат - 131 секунду.
Второй тест
Для чистоты эксперимента, перед каждым последующим тестом мы снова форматируем партицию и начинаем с чистого листа.
В качестве второго теста мы используем Bonnie:
http://www.textuality.com/bonnie/
Его также можно скачать тут
Этот тест выполняет посимвольно и поблочно запись, чтение и поиск.
Снова форматируем под ext4. Компилируем Bonnie, копируем на тестируемую партицию.
Запускаем команду - при этом будет создан тестовый файл размером в 1 гигабайт:
Bonnie -s 1000
Вывод:
File './Bonnie.7870', size: 1048576000
Writing with putc()...done
Rewriting...done
Writing intelligently...done
Reading with getc()...done
Reading intelligently...done
Seeker 1...Seeker 2...Seeker 3...start 'em...done...done...done...
-------Sequential Output-------- ---Sequential Input-- --Random--
-Per Char- --Block--- -Rewrite-- -Per Char- --Block--- --Seeks---
Machine GB M/sec %CPU M/sec %CPU M/sec %CPU M/sec %CPU M/sec %CPU /sec %CPU
1 34.9 94.6 54.8 13.6 53.2 10.3 41.1 99.2 1807.9 99.8 90214 162.4
Теперь форматируем под btrfs. Запускаем тест:
Bonnie -s 1000
Вывод:
-------Sequential Output-------- ---Sequential Input-- --Random--
-Per Char- --Block--- -Rewrite-- -Per Char- --Block--- --Seeks---
Machine GB M/sec %CPU M/sec %CPU M/sec %CPU M/sec %CPU M/sec %CPU /sec %CPU
1 33.9 96.3 47.1 16.4 54.5 11.7 40.9 99.6 1516.9 99.5 69369 138.7
На чтение и на запись btrfs чуть похуже, чем ext4.
Теперь форматируем под xfs. Запускаем тест:
Bonnie -s 1000
Вывод:
-------Sequential Output-------- ---Sequential Input-- --Random--
-Per Char- --Block--- -Rewrite-- -Per Char- --Block--- --Seeks---
Machine GB M/sec %CPU M/sec %CPU M/sec %CPU M/sec %CPU M/sec %CPU /sec %CPU
1 37.7 98.2 53.2 10.2 54.0 9.1 41.2 99.0 1774.6 99.4 76499 137.7
xfs показывает почти такой же результат, что и ext4, т.е. здесь xfs уже опережает btrfs.
Теперь форматируем под jfs. Запускаем тест:
Bonnie -s 1000
-------Sequential Output-------- ---Sequential Input-- --Random--
-Per Char- --Block--- -Rewrite-- -Per Char- --Block--- --Seeks---
Machine GB M/sec %CPU M/sec %CPU M/sec %CPU M/sec %CPU M/sec %CPU /sec %CPU
1 32.1 92.4 53.8 15.7 25.3 5.2 42.2 99.7 1834.7 99.8 97489 175.5
jfs на запись показывает самые плохие результаты, а вот на чтение/поиск неожиданно опережает всех.
Третий тест
В качестве третьего теста мы используем ffsb:
http://sourceforge.net/projects/ffsb/
Его также можно скачать тут
В этом многопоточном тесте можно настроить различные параметры под различную конфигурацию:
число тестируемых файлов, минимальный и максимальный размер файла, число потоков.
Тест выполняет последовательное и произвольное чтение, запись, создание файла случайного размера,
добавление в файл. Для данного теста используется следующий конфиг:
[filesystem0]
location=/mnt/sda10
num_files=10000
num_dirs=1000
max_filesize=665536
min_filesize=4096
agefs=0
[threadgroup0]
num_threads=10
write_size=40960
write_blocksize=4096
create_weight=10
append_weight=10
delete_weight=1
[end0]
desired_util=0.02
create_blocksize=1024
age_blocksize=1024
reuse=0
[end0]
Копируем на тестируемую партицию 2 файла и запускаем:
ffsb ffsb.cfg
Получаем следующие результаты:
ext4 - 79 секунд
btrfs - 55 секунд
xfs - 75 секунд
jfs - 93 секунды
Неожиданно ext4 проигрывает всем. Но это особенности конфигурации именно для этого теста.
Если поиграть с настройкой конфига, я думаю, что можно получить прямо противоположный результат
|