пятница, 13 июня 2014 г.

Эксперемент с дисковым кешем в Linux

Эффекты диского кеша во время выделения памяти в приложениях


Дисковый кеш не мешает приложениям в получении памяти, которой им необходимы. Вот небольшая программа на языке С (munch.c) которая выделяет столько памяти, сколько сможет или до определенного лимита:
$ cat munch.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char** argv) {
    int max = -1;
    int mb = 0;
    char* buffer;

    if(argc > 1)
        max = atoi(argv[1]);

    while((buffer=malloc(1024*1024)) != NULL && mb != max) {
        memset(buffer, 0, 1024*1024);
        mb++;
        printf("Allocated %d MB\n", mb);
    }
   
    return 0;
}


Когда память заканчивается - это не круто, но OOM-killer должен убить только этот процесс и надеюсь остальные процессы он не затронет.



Отключим для начала swap, что бы приложение не начало съедать его.
$ sudo swapoff -a

Проверим состояние памяти:
$ free -m
                     total       used       free     shared    buffers     cached
Память:       7866       7720     146          0        619          2443
-/+ буферы/кэш:        4657     3209
Swap:           0              0            0

Скомпилируем нашу программу:
$ gcc munch.c -o munch

И запустим:
$ ./munch
Allocated 1 MB
...
Allocated 3139 MB
Убито

$ free -m
                     total       used       free     shared    buffers     cached
Память:       7866       4980      2886          0         14        965
-/+ буферы/кэш:        4000      3866
Swap:            0             0            0

Не смотря на то, что было свободно свободно 146 Мб памяти - это не помешало приложению съесть 3139 Мб. После чего ООМ-killer убил процесс и освободил память.

В логе видим такое:
Jun 13 16:02:40 wimbo-hp kernel: [185540.658308] munch invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0

Включим swap:
$  swapon -a

Проверим состояние памяти:
$ free -m
                     total       used       free     shared    buffers     cached
Память:       7866       4793      3073          0          3         812
-/+ буферы/кэш:        3977      3889
Swap:          7627        251       7376

Запустим программу, что бы она выделила себе 3300 Мб:
$ ./munch 3300
Allocated 1 MB
...
Allocated 3300 MB

И снова проверим состояние памяти:
$ free -m
                     total        used       free     shared    buffers     cached
Память:       7866       4499       3367          0          0         536
-/+ буферы/кэш:        3962       3904
Swap:         7627         263        7364

munch съел 3300 Мб памяти, которая была взята из свободной и кешированной не используя swap.  Кроме того, мы можем забить дисковый кеш снова и это не заставит ОС использовать swap (верно при  /proc/sys/vm/swappiness = 0). Если мы в одном терминале запустим команду find . -type f -exec cat {} + > /dev/null, а в другом будем смотреть вывод free -m, то мы заметим, как растет показатель cached и снижается показатель free.


Чистка дискового кеша

Для эксперемента очень удобно, что мы можем сбросить дисковый кеш. Для этого необходимо в файл /proc/sys/vm/drop_caches записать значение 3:
# free -m
                    total       used       free     shared    buffers     cached
Память:       7866      4726       3139          0          9         767
-/+ буферы/кэш:       3949       3917
Swap:          7627       263        7364

Сбросим дисковый кеш:
# echo 3 > /proc/sys/vm/drop_caches 

И снова проверим состояние памяти:
# free -m
                     total       used       free     shared    buffers     cached
Память:       7866      4469       3397          0          0         523
-/+ буферы/кэш:       3945       3921
Swap:          7627       263        7364

Эффективность кеша диска во время работы приложений

Давайте напишем две программы на Python и на Java. У обоих этих языков довольно большой рантайм за счет того, что они подгружают все библиотеки и енвайрамент (ВМ). Это отличный вариант, что бы продемонстрировать магию дискового кеша.

# cat hello.py 
print "Hello World! Love, Python"

# cat hello.java 
class Hello { 
    public static void main(String[] args) throws Exception {
        System.out.println("Hello World! Regards, Java");
    }
}

Скомпилируем программу на Java:
$ javac hello.java 

Вот такие простые программы:
$ python hello.py 
Hello World! Love, Python

$ java Hello 
Hello World! Regards, Java

Сбросим дисковый кеш:
# echo 3 > /proc/sys/vm/drop_caches 

И посмотрим время выполнения данных программ без кеша:
# time python hello.py 
Hello World! Love, Python

real 0m1.343s
user 0m0.008s
sys 0m0.024s

# time java Hello
Hello World! Regards, Java

real 0m0.660s
user 0m0.068s
sys 0m0.028s

Довольно долго не находите для таких простых программ?

Запустим повторно:
# time python hello.py 
Hello World! Love, Python

real 0m0.021s
user 0m0.016s
sys 0m0.004s

# time java Hello
Hello World! Regards, Java

real 0m0.077s
user 0m0.056s
sys 0m0.016s

Ух ты! Python выполнился в 64 раза быстрее, а Java в 8.5 раз быстрее.

Эффект дискового кеша на чтение файла

Давайте создадим небольшой файл и посмотрим, как дисковый кеш влияет на его скорость чтения. Я создал файл размером 500 Мб.

Сбросим дисковый кеш:
# echo 3 > /proc/sys/vm/drop_caches 

И посмотрим состояние памяти:
# free -m
                     total        used       free     shared    buffers     cached
Память:       7866       4448       3418          0          1         638
-/+ буферы/кэш:        3808       4057
Swap:          7627        183        7444

Создадим файл с нулями размером 500 Мб:
# dd if=/dev/zero of=bigfile bs=1M count=500
500+0 записей получено
500+0 записей отправлено
скопировано 524288000 байт (524 MB), 1,35606 c, 387 MB/c

# ls -lh bigfile 
-rw-r--r-- 1 root root 500M Июн 13 18:22 bigfile

Теперь проверим еще раз состояние памяти:
# free -m
                    total       used       free     shared    buffers     cached
Память:       7866      5229       2637          0          7        1415
-/+ буферы/кэш:       3806       4060
Swap:          7627       183        7444

При создании файла, его содержимое пишется в дисковый кеш (кеш память увеличилась больше, чем на 500 Мб за счет того, что я выполняю все действия на ноутбуке, где запущено еще куча другого софта).

Давайте прочитаем его и посмотрим за сколько мы это сделаем:
# time cat bigfile > /dev/null

real 0m0.119s
user 0m0.004s
sys 0m0.096s

Не плохо, 500 Мб за 0,11 секунды. Давайте очистим кеш:
# echo 3 > /proc/sys/vm/drop_caches 

И повторим чтение:
# time cat bigfile > /dev/null

real 0m6.008s
user 0m0.004s
sys 0m0.324s

Ух ты, видим, что при чтении файла, который не находится время, потратилось в 50 раз больше времени.


Это вольный перевод статьи: http://www.linuxatemyram.com/play.html

Комментариев нет:

Отправить комментарий