Автор Тема: Динамичен kernel tunning?  (Прочетена 4146 пъти)

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Динамичен kernel tunning?
« -: Oct 31, 2006, 18:50 »
От известно време насам се чудя дали това е добра идея?

За какво точно говоря? Представете си следната програмка:

1) През равни интервали от време в продължение на известен брой цикли събира информация за работата на системата (loadavg, buffers/cache, swap/mem usage, sockets/fds, etc).

2) Прост алгоритъм който вади средно аритметично, средно отклонение, максимално отклонение, амплитуда (разликата между най-високата и най-ниската стойност в периода)

3) На база някакви критерии в зависимост от горните стойности променя различни kernel tunnables така че да се осигури по-добър responsiveness, по-рационално I/O спрямо наличната памет,  по-малко разхищение на памет (не ни трябват раздути буфери и структури когато не ги ползваме), ако щете донякъде защита от добре известни локални DoS (като например форкбомби, отваряне на голям брой сокети или файлове за малко време и т.н).

Що се отнася до тунинговането на производителността според мен има смисъл в зависимост от ситуацията човек динамично да променя неща като vfs_cache_pressure, swappiness, readahead буфери за блоковите устройства и т.н.

4) goto 1


Всъщност написах една кратка "първоначална" версия на програмка, която реализира нещо подобно. Естествено, доста далеч е от целта, най-малкото доста неща трябва да се допроверят и тестват, особено тези свързани с точка 3.

Мисълта ми е: според вас има ли смисъл от динамично тунинговане на тези параметри или ако човек работи през цялото време с дефолтните или някакви собствени, цялостната картинка ще е по-добра?

Знам че тестването на практическата файда от нещо такова е доста сложна занимавка от друга страна, иначе тестовете щях да си ги направя сам и нямаше да питам за чужди мнения '<img'> От друга страна знам, че за да промениш някои параметри така че нещата да се наредят най-добре изисква да си баба Ванга и да знаеш какво ще се случи на машината известно време напред. Примерно хубаво е да имаш много dentry/inode кеш на машината принципно, но ако от това се възползва единствено updatedb едва ли ще го викаш през 5 минути  за да си индексираш файловите системи '<img'>

П.П. за момента иначе съм донякъде горд с това дето го сътворих...когато изкуствено предизвикам ситуация в която се налага машината да суоп-ва, откривам някакъв смисъл от цялата работа. Иначе не се усеща никаква разлика '<img'>
Активен

"Knowledge is power" - France is Bacon

ZEN

  • Напреднали
  • *****
  • Публикации: 159
    • Профил
    • WWW
Динамичен kernel tunning?
« Отговор #1 -: Nov 01, 2006, 11:52 »
Приветствам тази идея... от години си играя да оптимизирам /според възможностите си, които не са кой знае какви/... затова ще се радвам /предполагам и други/ да публикуваш някакви резултати... или решения.
Успех
Активен

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Динамичен kernel tunning?
« Отговор #2 -: Nov 02, 2006, 11:25 »
Такам...досега какъв напредък имам:

1) vfs_cache_pressure се регулира динамично според тенденциите на нарастване на buffers/cached (не е много правилно, но примерно при updatedb или du -hs / сработва успешно в посока inode/dentry cache. При големи обеми резервирана памет за периода става обратното -> pagecache)

2) dirty cache expire/writeback се регулира динамично в зависимост от това колко памет е заета и колко се е освободила при записването й върху диска, така че да се избягва от една страна прекалено честото генериране на I/O и прекалено много заетата памет от друга

3) Параметрите на IO scheduler-a се тунинговат в зависимост от това колко писане/четене има за периода (работи засега само с anticipatory scheduling алгоритъма)

4) Регулиране на swappiness в случай че сме навлезли в суоп-а и в зависимост от тенденцията loadavg да расте/намалява - така се повишава responsiveness-a на системата

5) page-cluster се променя динамично в зависимост от това колко се суоп-ва: това с цел да се подобри swap I/O performance-a

6) Ако продължително време няма почти никакъв swapin/swapout, има свободна рам и въпреки всичко в суопа стоят разни работи, целият swap се flush-ва (swapoff -a;swapon -a). Това е защото VM мениджмънта на линукс на моменти е малко тъп и ако има нещо в суоп-а и въпреки че има свободна РАМ има тенденцията да продължава да тъпче глупости в суоп-а

7) file-max, threads-max се регулират в зависимост от отворените файлови дескриптори / броят на процесите. Това с цел да се смекчат последствията от forkbomb-и или някаква бъгавиня дето отваря изведнъж много файлове. От това няма кой знае какъв смисъл като се замисля, отделно дето понякога създава проблеми - вероятно ще го разкарам.

8) Големината на буферите за мрежови операции (rmem_max/default, wmem_max/default) се коригират в зависимост от нарастването/намаляването на входящият/изходящият трафик. За съжаление понякога и тук има слаби моменти.

9) Големината на read-ahead буферите за блоковите устройства се коригират в зависимост от тенденцията за нарастване на операциите на четене от тях (леко грубо и недодялано).

Какво мисля да реализирам още?

1) Тунинговане на TCP параметри - много бих искал, въпреки че ще е огромна работа
2) Коригиране на netdev_max_backlog за да не се дропят пакети в дадени ситуации - това няма да е много сложно
3) Дали не може да се направи нещо свързано със балансирането на interrupts? Обаче там нещата стават доста сложни и трябва бая да се помисли върху логиката. Най-малкото значение има и архитектурата, и броя процесори и т.н
4) Разни ACPI занимавки - с тях пък така или иначе не съм особено запознат и трябва да почета доста преди това
5) Дали не може да се вземат предвид разни данни от lmsensors, cpufreq? Смисълът от нещо такова обаче е доста противоречив. Съмнително е също дали мога да го реализирам като хората '<img'>

В най-скоро време ще кача кода на глупостта, която съм сътворил, в момента е доста грозен и неподреден и без коментари и ме е срам '<img'> Не е кой знае какво иначе - около 1000 реда на C, байнърито е доста леко - към 30кб, верно malloc-ва повечко памет, но не  кой знае колко много. Освен това бавно и неусетно  някъде leak-ва (не тече кой знае колко силно де '<img'> ) и още не съм го хванал къде.

Та това е progress report-a засега '<img'>
Активен

"Knowledge is power" - France is Bacon

ZEN

  • Напреднали
  • *****
  • Публикации: 159
    • Профил
    • WWW
Динамичен kernel tunning?
« Отговор #3 -: Nov 02, 2006, 16:44 »
Продължавай в същия дух със сигурност ще съм ти първия бета тестер'<img'>
Активен

senser

  • Напреднали
  • *****
  • Публикации: 1328
    • Профил
Динамичен kernel tunning?
« Отговор #4 -: Nov 02, 2006, 19:13 »
интересно ми е къде може да се намери/прочете подробна информация за параметрите, които подлежат на тунинговане
и може да се разпредели работата по отделните компоненти и алгоритми - доста работа си е за сам човек '<img'>

иначе поздравления за начинанието ':ok:'
Активен

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Динамичен kernel tunning?
« Отговор #5 -: Nov 02, 2006, 21:00 »
/usr/src/`uname -r`/Documentation

Относително сносна документация, но на моменти има мъгляви твърдения и се налага да прегледаш и конкретния код и да се опиташ да разкриеш замисъла. Има разни уики-та с полезни насоки, както и lwn.net, kerneltrap.net. Ако ти възникне по-конкретен въпрос, google намира доста уеб-архиви на LKML, където обаче нерядко говорят и глупости '<img'> И измежду другото попадаш на доста забавни спорове между типове като Ханс Райзер или Йорг Шилинг и разните там архигурута - kernel devs:)

А, да, и на един хърватски сайт се опитват да документират /proc tunnables. http://linux.inet.hr/proc_filesystem.html . Определено не може да се каже че е много пълна документацията, но това което има е  събрано удобно на едно място където лесно се търси.

2.6 променливите принципно са доста по-зле документирани от тия от 2.4, ама сега нещата и без това са се усложнили немалко...procfs започва да става някаква промита история, има и /sys, много хора пък си дефинират ioctls или други механизми и си пишат userspace библиотеки (cpufreq примерно са тръгнали в тази насока).

Така че няма някакво удобно място наедно, налага се повече собствен research в някои случаи '<img'>
Активен

"Knowledge is power" - France is Bacon

zeridon

  • Killmode enabled
  • Administrator
  • Напреднали
  • *****
  • Публикации: 1398
  • Distribution: Debian/Ubuntu
  • Window Manager: console/Gnome
  • BOfH
    • Профил
    • WWW
Динамичен kernel tunning?
« Отговор #6 -: Nov 03, 2006, 12:29 »
Като цяло и аз съм за бета тестер и то най вече в областта на I/O i Mem usage. Понеже това най яко ми къса нервите.
Активен

Внмимавай имам клещи за кабел
http://www.netsecad.com/
http://theregister.co.uk/odds/bofh/

kennedy

  • Напреднали
  • *****
  • Публикации: 2151
  • Николай Колев
    • Профил
Динамичен kernel tunning?
« Отговор #7 -: Nov 03, 2006, 12:37 »
Сякаш в миналото съм срещал подобен проект ...
Активен

"за всичко иде час" Еклесиаст 3:1
всеки пост - отговор на въпрос
-----------------
24.12.2003 "MS Free"

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Динамичен kernel tunning?
« Отговор #8 -: Nov 03, 2006, 15:36 »
Ето ви примерния сорс (грозен, бъглив, недодялан) засега:

Цитат

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <sys/time.h>
#include <sys/resource.h>

// Defines, Data structures, global vars
#define MAX_DATA 100
#define SLEEP_TIME 2
#define AFTER 3

#define TODO_VFS_CACHE_INC 1
#define TODO_VFS_CACHE_DEC 2
#define TODO_DIRTY_INC 3
#define TODO_DIRTY_DEC 4
#define TODO_REBALANCE_READ 5
#define TODO_REBALANCE_WRITE 6
#define TODO_READAHEAD_UP 7
#define TODO_READAHEAD_DOWN 8
#define TODO_SWAPPINESS_UP 9
#define TODO_SWAPPINESS_DOWN 10
#define TODO_SWAPPINESS_ONE 11
#define TODO_PAGECLUSTER_UP 12
#define TODO_PAGECLUSTER_NORM 13
#define TODO_FLUSH_SWAP 14
#define TODO_CHECK_FILENR 15
#define TODO_RECVBUF_UP 16
#define TODO_RECVBUF_DOWN 17
#define TODO_SENDBUF_UP 18
#define TODO_SENDBUF_DOWN 19



// system-data struct
struct tcinfo
{
    int id;
    float loadavg;
    int memused;
    int memmax;
    int memuse;
    int buffers;
    int cached;
    int swapcached;
    int swapused;
    int swapmax;
    int swapuse;
    int dirty;
    int writeback;
    int uswap;
    int ioread;
    int iowrite;
    int recv;
    int send;
};

// statistics struct
struct tcstat
{
    float loadavg[3];
    int memused[3];
    int memmax[3];
    int memuse[4];
    int buffers[4];
    int cached[3];
    int swapcached[3];
    int swapused[3];
    int swapmax[3];
    int swapuse[3];
    int dirty[3];
    int writeback[3];
    int uswap[3];
    long ioread[3];
    long iowrite[3];
    int recv[4];
    int send[4];
};

// vars
struct tcinfo cia[MAX_DATA];
struct tcstat cst;
int cindex;
// read over write marker
int sched=0;
// Read-ahead, marker
int read_ahb=1;
char *ulog="/var/log/tune.log";

// recover after X passes
int vfsd_after=0;
int vfsu_after=0;
int recu_after=0;
int recd_after=0;
int senu_after=0;
int send_after=0;

// Log into file
void logme(char *data)
{
    FILE *fd;
    fd=fopen(ulog,"a+");
    fputs(data,fd);
    fclose(fd);
}
// Get system data
void getdata(int time)
{
    FILE *fd;
    char *buf;
    char *buf1;
    char *buf2;
    char *buf3;
    char *buf4;
    int t1,t2;
    long tt1,tt2;
    float l;


    for (cindex=1;cindex<=time;cindex++)
        {
        cia[cindex].id=cindex;
// Parse networking stats
        buf=malloc(300);
        fd=fopen("/proc/net/snmp","r");
        fgets(buf,300,fd);
        fgets(buf,300,fd);
        fclose(fd);
        buf1=strtok_r(buf," ",&buf4);
        for (t1=1;t1<=9;t1++) buf1=strtok_r(NULL," ",&buf4);
        l=strtod(buf1,NULL);
        cia[cindex].recv=l;
        buf1=strtok_r(NULL," ",&buf4);
        l=strtod(buf1,NULL);
        cia[cindex].send=l;
        free(buf);



// Parse loadavg data
        buf=malloc(100);
        fd=fopen("/proc/loadavg","r");
        fgets(buf,100,fd);
        buf1=strtok(buf," ");
        l=strtod(buf1,NULL);
        cia[cindex].loadavg=l;
        free(buf);
// Parse meminfo stats
        buf=malloc(300);
//memleakshit
        buf4=buf;
        fd=fopen("/proc/meminfo","r");
        fgets(buf,300,fd);
        buf1=strtok_r(buf,":",&buf2);
        buf1=strtok_r(NULL,":",&buf2);
        t1=strtod(buf1,NULL);
        fgets(buf,300,fd);
        buf1=strtok_r(buf,":",&buf2);
        buf1=strtok_r(NULL,":",&buf2);
        t2=strtod(buf1,NULL);
        cia[cindex].memused=((t1-t2)*100/t1);
        cia[cindex].memuse=t2;
        cia[cindex].memmax=t1;
// Buffers
        fgets(buf,300,fd);
        buf1=strtok_r(buf,":",&buf2);
        buf1=strtok_r(NULL,":",&buf2);
        cia[cindex].buffers=strtod(buf1,NULL);

// Cached
        fgets(buf,300,fd);
        buf1=strtok_r(buf,":",&buf2);
        buf1=strtok_r(NULL,":",&buf2);
        cia[cindex].cached=strtod(buf1,NULL);

// SwapCached
        fgets(buf,300,fd);
        buf1=strtok_r(buf,":",&buf2);
        buf1=strtok_r(NULL,":",&buf2);
        cia[cindex].swapcached=strtod(buf1,NULL);
// Jumpto..
        for (t1=1;t1<=6;t1++) fgets(buf,300,fd);
// Parse swapinfo
        fgets(buf,300,fd);
        buf1=strtok_r(buf,":",&buf2);
        buf1=strtok_r(NULL,":",&buf2);
        t1=strtod(buf1,NULL);
        fgets(buf,300,fd);
        buf1=strtok_r(buf,":",&buf2);
        buf1=strtok_r(NULL,":",&buf2);
        t2=strtod(buf1,NULL);
        cia[cindex].swapused=((t1-t2)*100/t1);
        cia[cindex].swapuse=t2;
        cia[cindex].swapmax=t1;
// Dirty, writeback
        fgets(buf,300,fd);
        buf1=strtok_r(buf,":",&buf2);
        buf1=strtok_r(NULL,":",&buf2);
        cia[cindex].dirty=strtod(buf1,NULL);
        fgets(buf,300,fd);
        buf1=strtok_r(buf,":",&buf2);
        buf1=strtok_r(NULL,":",&buf2);
        cia[cindex].writeback=strtod(buf1,NULL);
// Close it, free it..
        fclose(fd);
        free(buf);
// Get I/O stats, the dumbest way '<img'>
        fd=fopen("/proc/diskstats","r");
        tt1=0;tt2=0;
        while (feof(fd)==0)
            {
                buf=malloc(200);
                if (fgets(buf,200,fd)!=NULL)
                {
                    buf1=strtok_r(buf," ",&buf2);
                    buf1=strtok_r(NULL," ",&buf2);
                    buf1=strtok_r(NULL," ",&buf2);
                    buf1=strtok_r(NULL," ",&buf2);
                    tt1=tt1+(strtol(buf1,NULL,0)/100);
                    buf1=strtok_r(NULL," ",&buf2);
                    buf1=strtok_r(NULL," ",&buf2);
                    buf1=strtok_r(NULL," ",&buf2);
                    tt2=tt2+(strtol(buf1,NULL,0)/100);
                }
                free(buf);

            }
        fclose(fd);
        cia[cindex].ioread=tt1;
        cia[cindex].iowrite=tt2;

// Sleep...
        sleep(SLEEP_TIME);
        }
}


// Analyze data: some stats analysis
void analyze_data()
{
    int a,b;
    int mean,mxdev,mndev;
    float mmean,mmxdev,mmndev;

// Network stats prepare
    cst.send[4]=cst.send[3];
    cst.recv[4]=cst.recv[3];
    mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].recv;
            if (mxdev<abs(cia[a].recv-cia[a-1].recv))
mxdev=abs(cia[a].recv-cia[a-1].recv);
            mndev=mndev+cia[a].recv-cia[a-1].recv;
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("recv:  Average:%d kb  Max_deviation:%dkb Mean_deviation:%dkb\n",mean,mxdev,m
ndev);
    cst.recv[1]=mean;cst.recv[2]=mxdev;cst.recv[3]=mndev;

    mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].send;
            if (mxdev<abs(cia[a].send-cia[a-1].send))
mxdev=abs(cia[a].send-cia[a-1].send);
            mndev=mndev+abs(cia[a].send-cia[a-1].send);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("send:  Average:%d kb  Max_deviation:%dkb  Mean_deviation:%dkb\n",mean,mxdev,m
ndev);
    cst.send[1]=mean;cst.send[2]=mxdev;cst.send[3]=mndev;



// Loadavg stats parse
    mmean=0;mmxdev=0;mmndev=0;
    for (a=2;a!=cindex;a++)
        {
            mmean=mmean+cia[a].loadavg;
            if (mmxdev<fabsf(cia[a].loadavg-cia[a-1].loadavg))
mmxdev=fabsf(cia[a].loadavg-cia[a-1].loadavg);
            mmndev=mmndev+fabsf(cia[a].loadavg-cia[a-1].loadavg);
        }
    mmean=mmean/(cindex-2);
    mmndev=mmndev/(cindex-2);
//    printf("loadavg:  Average:%.2f percent  Max_deviation:%.2f  Mean_deviation:%.2f\n",mm
ean,mmxdev,mmndev);
    cst.loadavg[1]=mmean;cst.loadavg[2]=mmxdev;cst.loadavg[3]=mmndev;

// Memory Usage stats
    mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].memused;
            if (mxdev<abs(cia[a].memused-cia[a-1].memused))
mxdev=abs(cia[a].memused-cia[a-1].memused);
            mndev=mndev+abs(cia[a].memused-cia[a-1].memused);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("Memusage:  Average:%d percent  Max_deviation:%d  Mean_deviation:%d\n",mean,mx
dev,mndev);
    cst.memused[1]=mean;cst.memused[2]=mxdev;cst.memused[3]=mndev;

// Memory use stats
    mean=0;mxdev=0;mndev=0;
    cst.memuse[4]=cst.memuse[3];
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].memuse;
            if (mxdev<abs(cia[a].memuse-cia[a-1].memuse))
mxdev=abs(cia[a].memuse-cia[a-1].memuse);
            mndev=mndev+(cia[a].memuse-cia[a-1].memuse);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("Memuse:  Average:%d kb  Max_deviation:%dkb  Mean_deviation:%dkb\n",mean,mxdev
,mndev);
    cst.memuse[1]=mean;cst.memuse[2]=mxdev;cst.memuse[3]=mndev;


// Buffers stats
    cst.buffers[4]=cst.buffers[3];
    mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].buffers;
            if (mxdev<abs(cia[a].buffers-cia[a-1].buffers))
mxdev=abs(cia[a].buffers-cia[a-1].buffers);
            mndev=mndev+(cia[a].buffers-cia[a-1].buffers);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("buffers:  Average:%d kb  Max_deviation:%dkb  Mean_deviation:%dkb\n",mean,mxde
v,mndev);
    cst.buffers[1]=mean;cst.buffers[2]=mxdev;cst.buffers[3]=mndev;


// Cached stats
    mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].cached;
            if (mxdev<abs(cia[a].cached-cia[a-1].cached))
mxdev=abs(cia[a].cached-cia[a-1].cached);
            mndev=mndev+abs(cia[a].cached-cia[a-1].cached);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("cached:  Average:%d kb  Max_deviation:%dkb  Mean_deviation:%dkb\n",mean,mxdev
,mndev);
    cst.cached[1]=mean;cst.cached[2]=mxdev;cst.cached[3]=mndev;


// swapcached stats
    mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].swapcached;
            if (mxdev<abs(cia[a].swapcached-cia[a-1].swapcached))
mxdev=abs(cia[a].swapcached-cia[a-1].swapcached);
            mndev=mndev+abs(cia[a].swapcached-cia[a-1].swapcached);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("swapcached:  Average:%d kb  Max_deviation:%dkb  Mean_deviation:%dkb\n",mean,m
xdev,mndev);

cst.swapcached[1]=mean;cst.swapcached[2]=mxdev;cst.swapcached[3]=mndev;


// Swap Usage stats
   mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].swapused;
            if (mxdev<abs(cia[a].swapused-cia[a-1].swapused))
mxdev=abs(cia[a].swapused-cia[a-1].swapused);
            mndev=mndev+abs(cia[a].swapused-cia[a-1].swapused);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("swapusage:  Average:%d percent  Max_deviation:%d  Mean_deviation:%d\n",mean,m
xdev,mndev);
    cst.swapused[1]=mean;cst.swapused[2]=mxdev;cst.swapused[3]=mndev;


// swap use stats
    mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].swapuse;
            if (mxdev<abs(cia[a].swapuse-cia[a-1].swapuse))
mxdev=abs(cia[a].swapuse-cia[a-1].swapuse);
            mndev=mndev+abs(cia[a].swapuse-cia[a-1].swapuse);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("swapuse:  Average:%d kb  Max_deviation:%dkb  Mean_deviation:%dkb\n",mean,mxdev,mndev);
    cst.swapuse[1]=mean;cst.swapuse[2]=mxdev;cst.swapuse[3]=mndev;


// dirty stats
    mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].dirty;
            if (mxdev<abs(cia[a].dirty-cia[a-1].dirty))
mxdev=abs(cia[a].dirty-cia[a-1].dirty);
            mndev=mndev+abs(cia[a].dirty-cia[a-1].dirty);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("dirty:  Average:%d kb  Max_deviation:%dkb  Mean_deviation:%dkb\n",mean,mxdev,
mndev);
    cst.dirty[1]=mean;cst.dirty[2]=mxdev;cst.dirty[3]=mndev;


// writeback stats
    mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].writeback;
            if (mxdev<abs(cia[a].writeback-cia[a-1].writeback))
mxdev=abs(cia[a].writeback-cia[a-1].writeback);
            mndev=mndev+abs(cia[a].writeback-cia[a-1].writeback);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("writeback:  Average:%d kb  Max_deviation:%dkb  Mean_deviation:%dkb\n",mean,mx
dev,mndev);

cst.writeback[1]=mean;cst.writeback[2]=mxdev;cst.writeback[3]=mndev;

// ioread stats
    mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
        {
            mean=mean+cia[a].ioread;
            if (mxdev<abs(cia[a].ioread-cia[a-1].ioread))
mxdev=abs(cia[a].ioread-cia[a-1].ioread);
            mndev=mndev+abs(cia[a].ioread-cia[a-1].ioread);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("ioread:  Average:%d kb  Max_deviation:%dkb  Mean_deviation:%dkb\n",mean,mxdev
,mndev);
    cst.ioread[1]=mean;cst.ioread[2]=mxdev;cst.ioread[3]=mndev;

// iowrite stats
    mean=0;mxdev=0;mndev=0;
    for (a=2;a!=cindex;a++)
       {
            mean=mean+cia[a].iowrite;
            if (mxdev<abs(cia[a].iowrite-cia[a-1].iowrite))
mxdev=abs(cia[a].iowrite-cia[a-1].iowrite);
            mndev=mndev+abs(cia[a].iowrite-cia[a-1].iowrite);
        }
    mean=mean/(cindex-2);
    mndev=mndev/cindex;
//    printf("iowrite:  Average:%d kb  Max_deviation:%dkb  Mean_deviation:%dkb\n",mean,mxde
v,mndev);
cst.iowrite[1]=mean;cst.iowrite[2]=mxdev;cst.iowrite[3]=mndev;

}


// The funny part: react accordingly
void makescript(int TODO)
{
    char *str=malloc(100);
    FILE *fd;
    char *buff=malloc(100);
    int value;

// Re-balance IO scheduller
    void rebalance()
        {
        if (sched>0) {
                sprintf(str,"sh -c \"`ls /sys/block/*/queue/iosched/read_expire|awk '{print
 \"echo %d > \"$1}'`\"",(sched)*125*2);
                system(str);
                sprintf(str,"sh -c \"`ls /sys/block/*/queue/iosched/read_batch_expire|awk '
{print \"echo %d > \"$1}'`\"",(sched)*125);
                system(str);
                sprintf(str,"sh -c \"`ls /sys/block/*/queue/iosched/write_expire|awk '{prin
t \"echo %d > \"$1}'`\"",(sched)*125);
                system(str);
                sprintf(str,"sh -c \"`ls /sys/block/*/queue/iosched/write_batch_expire|awk
'{print \"echo %d > \"$1}'`\"",(sched)*125*4);
                system(str);
                }
        else if (sched<0)       {
                sprintf(str,"sh -c \"`ls /sys/block/*/queue/iosched/read_expire|awk '{print
 \"echo %d > \"$1}'`\"",((0-sched)+1)*125);
                system(str);
                sprintf(str,"sh -c \"`ls /sys/block/*/queue/iosched/read_batch_expire|awk '
{print \"echo %d > \"$1}'`\"",((0-sched)+1)*125*4);
                system(str);
                sprintf(str,"sh -c \"`ls /sys/block/*/queue/iosched/write_expire|awk '{prin
t \"echo %d > \"$1}'`\"",(1-sched)*125*4);
                system(str);
                sprintf(str,"sh -c \"`ls /sys/block/*/queue/iosched/write_batch_expire|awk
'{print \"echo %d > \"$1}'`\"",(1-sched)*125);
                system(str);
        }
    }

// Resize readahead buffer
    void resizerabuffer()
        {
                sprintf(str,"sh -c \"`ls /sys/block/*/queue/read_ahead_kb|awk '{print \"ech
o %d > \"$1}'`\"",(read_ahb)*128);
                system(str);
        }

// Set maximum FDs
    void filenr()
    {
        char *buf1;
        int i,j;

//      buff=malloc(300);
        fd=fopen("/proc/sys/fs/file-nr","r");
        fgets(buff,300,fd);
        fclose(fd);
        buf1=strtok(buff," ");
        i=strtod(buf1,NULL);
        fd=fopen("/proc/sys/fs/file-max","r");
        fgets(buff,300,fd);
        fclose(fd);
        j=strtod(buff,NULL);
        if ((j-i) < 10000)
            {
            j=j+10000;
            logme("Tune FS: Raise maximum file handles...\n");
            sprintf(buff,"echo %d > /proc/sys/fs/file-max",j);
            system(buff);
            }

        if ((j-i) > 20000)
            {
            j=j-10000;
            logme("Tune FS: Don't need so much available file handles...\n");
            sprintf(buff,"echo %d > /proc/sys/fs/file-max",j);
            system(buff);
            }

        }


    switch (TODO)
    {

// Increase vfs_cache_pressure
    case TODO_VFS_CACHE_INC:
        {
        logme("Tune VM: Increase VFS cache pressure -> pagecache..\n");
        fd=fopen("/proc/sys/vm/vfs_cache_pressure","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        value=value+10;
        sprintf(str,"echo %d > /proc/sys/vm/vfs_cache_pressure",value);
        system(str);
        if ((vfsu_after==0)&&(vfsd_after!=1)) vfsu_after=AFTER;

        } break;

//decrease vfs_cache_pressure
    case TODO_VFS_CACHE_DEC:
        {
        logme("Tune VM: Decrease VFS cache pressure -> inode/dentry cache...\n");
        fd=fopen("/proc/sys/vm/vfs_cache_pressure","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        value=value-10;
        sprintf(str,"echo %d > /proc/sys/vm/vfs_cache_pressure",value);
        system(str);
        if ((vfsd_after==0) && (vfsu_after!=1)) vfsd_after=AFTER;
        } break;

// Increase dirty expire time
    case TODO_DIRTY_INC:
        {
        logme("Tune VM: Increase dirty cache expire time..\n");
       fd=fopen("/proc/sys/vm/dirty_expire_centisecs","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        value=value+500;
        sprintf(str,"echo %i > /proc/sys/vm/dirty_expire_centisecs",value);
        system(str);
        fd=fopen("/proc/sys/vm/dirty_writeback_centisecs","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        value=value+500;
        sprintf(str,"echo %i > /proc/sys/vm/dirty_writeback_centisecs",value);
        system(str);
        } break;

//  Decrease dirty expire time
    case TODO_DIRTY_DEC:
        {
        fd=fopen("/proc/sys/vm/dirty_expire_centisecs","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        if (value>=1000)        {value=value-500;logme("Tune VM: Decrease dirty cache expir
e time..\n");}
        sprintf(str,"echo %i > /proc/sys/vm/dirty_expire_centisecs",value);
        system(str);
       fd=fopen("/proc/sys/vm/dirty_writeback_centisecs","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        if (value>=500) {value=value-500;}
        sprintf(str,"echo %i > /proc/sys/vm/dirty_writeback_centisecs",value);
        system(str);
        } break;

// Rebalance iosched - we have more reads
    case TODO_REBALANCE_READ:
        {
        if (sched>-2)
         {sched=sched-1;
         logme("Tune IOsched: Peak reads,rebalancing..\n");
         rebalance();
         }
        } break;

// Rebalance iosched - we have more writes
    case TODO_REBALANCE_WRITE:
        {
        if (sched<2) {
            sched=sched+1;
            logme("Tune IOsched: Peak writes,rebalancing..\n");
            rebalance();
            }
        } break;

// Increase swappiness
    case TODO_SWAPPINESS_UP:
        {
        fd=fopen("/proc/sys/vm/swappiness","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        if (value<=90)
        {logme("Tune VM: Increase swappiness, don't need better responsiveness now..\n");va
lue=value+10;}
        sprintf(str,"echo %i > /proc/sys/vm/swappiness",value);
        system(str);
        } break;

// Decrease swappiness
    case TODO_SWAPPINESS_DOWN:
        {
        fd=fopen("/proc/sys/vm/swappiness","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        if (value>=30)
        {logme("Tune VM: Decrease swappiness, we want better responsiveness now...\n");valu
e=value-30;}
        else if ((value>10)&&(value<30)) {logme("Tune VM: Decrease swappiness, we want better responsiveness now...\n");value=10;}
        sprintf(str,"echo %i > /proc/sys/vm/swappiness",value);
        system(str);
        } break;

// (Almost) no swappiness
    case TODO_SWAPPINESS_ONE:
        {
        value=10;
        logme("Tune VM: Set swappiness at minimum, we don't need swapping now...\n");
        sprintf(str,"echo %i > /proc/sys/vm/swappiness",value);
        system(str);
        } break;

// Increase page-cluster
    case TODO_PAGECLUSTER_UP:
        {
        fd=fopen("/proc/sys/vm/page-cluster","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        logme("Tune VM: Increase page-cluster for better swap I/O performance..\n");value=v
alue+1;
        sprintf(str,"echo %i > /proc/sys/vm/page-cluster",value);
        system(str);
        } break;
// Normalize page-cluster
    case TODO_PAGECLUSTER_NORM:
        {
        fd=fopen("/proc/sys/vm/page-cluster","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        if (value!=3)
            {
            logme("Tune VM: Return page-cluster to its normal value..\n");value=3;
                sprintf(str,"echo %i > /proc/sys/vm/page-cluster",value);
                system(str);
            }
        } break;

// Bye-bye swap...
    case TODO_FLUSH_SWAP:
        {
            logme("Tune VM: It's a good time to flush all your swap...\n");value=3;
            sprintf(str,"swapoff -a;swapon -a",value);
            system(str);
        } break;


// Increase readahead buffers
    case TODO_READAHEAD_UP:
        {
            if (read_ahb<20)
            {
            logme("Tune IO: Increase read-ahead buffers size...\n");
            read_ahb=read_ahb+1;
            resizerabuffer();
            }
        } break;

// Decrease readahead buffers
    case TODO_READAHEAD_DOWN:
        {
            if (read_ahb>1)
            {
            logme("Tune IO: Decrease read-ahead buffers size...\n");
            read_ahb=read_ahb-1;
            resizerabuffer();
            }
        } break;

// Check file-nr against file-max
    case TODO_CHECK_FILENR:
        {
        filenr();
        } break;

// Increase receive network buffers size..
    case TODO_RECVBUF_UP:
        {
        fd=fopen("/proc/sys/net/core/rmem_max","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        logme("Tune NET: Increase receive network buffers size..\n");value=value+20000;
        sprintf(str,"echo %i > /proc/sys/net/core/rmem_max",value);
        system(str);
        fd=fopen("/proc/sys/net/core/rmem_default","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        value=value+20000;
        sprintf(str,"echo %i > /proc/sys/net/core/rmem_default",value);
        system(str);
        if ((recu_after==0)&&(recd_after!=1)) recu_after=AFTER;

        } break;

// Decrease receive network buffers..
    case TODO_RECVBUF_DOWN:
        {
        fd=fopen("/proc/sys/net/core/rmem_max","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        logme("Tune NET: Decrease receive network buffers size..\n");value=value-20000;

       sprintf(str,"echo %i > /proc/sys/net/core/rmem_max",value);
        system(str);
        fd=fopen("/proc/sys/net/core/rmem_default","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        value=value-20000;
        sprintf(str,"echo %i > /proc/sys/net/core/rmem_default",value);
        system(str);
        if ((recd_after==0)&&(recu_after!=1)) recd_after=AFTER;
        } break;

// Increase send network buffers size..
    case TODO_SENDBUF_UP:
        {
        fd=fopen("/proc/sys/net/core/wmem_max","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        logme("Tune NET: Increase send network buffers size..\n");value=value+20000;
        sprintf(str,"echo %i > /proc/sys/net/core/wmem_max",value);
        system(str);
        fd=fopen("/proc/sys/net/core/wmem_default","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        value=value+20000;
        sprintf(str,"echo %i > /proc/sys/net/core/wmem_default",value);
        system(str);
        if ((senu_after==0)&&(send_after!=1)) senu_after=AFTER;
        } break;

// Decrease receive network buffers..
    case TODO_SENDBUF_DOWN:
        {
        fd=fopen("/proc/sys/net/core/wmem_max","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        logme("Tune NET: Decrease send network buffers size..\n");value=value-20000;
        sprintf(str,"echo %i > /proc/sys/net/core/wmem_max",value);
        system(str);
        fd=fopen("/proc/sys/net/core/wmem_default","r");
        fgets(buff,100,fd);
        value=strtod(buff,NULL);
        fclose(fd);
        value=value-20000;
        sprintf(str,"echo %i > /proc/sys/net/core/wmem_default",value);
        system(str);
        if ((send_after==0)&&(senu_after!=1)) send_after=AFTER;

        } break;
    }
    free(buff);free(str);
}


// Teh Delphi Oracle:
void givemyadvice()
{

/* Must not:
- Rely on absolute ratios (value_X more than X), only relative (value_X
more than N*value_Y)
- Keep it eventually unbalanced
*/
    if ( (cst.buffers[3]>cst.buffers[4]+1) && ((cst.buffers[3]+cst.buffers[4])>0) && (cst.memuse[4]>cst.memuse[3]) ){makescript(TODO_VFS_CACHE_INC);}
    else if ((cst.buffers[3]<cst.buffers[4]+1)  && ((cst.buffers[3]+cst.buffers[4])<0) && (cst.memuse[4]<cst.memuse[3]) ) {makescript(TODO_VFS_CACHE_DEC);}
    if (3*cst.dirty[2]<cst.dirty[1]) {makescript(TODO_DIRTY_DEC);}
    if (cst.dirty[1]<cst.dirty[2]) {makescript(TODO_DIRTY_INC);}
    if (cst.ioread[2]>cst.iowrite[2]) {makescript(TODO_REBALANCE_READ);}
    else if (cst.iowrite[2]>3*cst.ioread[2]) {makescript(TODO_REBALANCE_WRITE);}
    if (cst.swapuse[1]==0) {makescript(TODO_SWAPPINESS_ONE);}
    if ((cst.loadavg[2]>0.05)&& (cst.swapused[1]>0)) {makescript(TODO_SWAPPINESS_DOWN);}
    if ((cst.loadavg[2]<=0.05) && (cst.swapused[1]>0)){makescript(TODO_SWAPPINESS_UP);}
    if (cst.swapuse[2]>0) {makescript(TODO_PAGECLUSTER_UP);}
    else {makescript(TODO_PAGECLUSTER_NORM);}
    if ( (cst.swapcached[1]>0) && (cst.swapuse[2]==0) && (cst.swapuse[3]==0) && (cst.loadav
g[3]<0.01)) {makescript(TODO_FLUSH_SWAP);}
    if (cst.ioread[3]<1) {makescript(TODO_READAHEAD_DOWN);}
    if (cst.ioread[3]<1) {makescript(TODO_READAHEAD_DOWN);}
    if (cst.ioread[2]>5*(cst.ioread[3]+1)) {makescript(TODO_READAHEAD_UP);}
    if ((cst.recv[3]>35*cst.recv[4]+1) && (cst.recv[3]+cst.recv[4]>0)) {makescript(TODO_RECVBUF_UP);}
    if ((cst.recv[4]>35*cst.recv[3]+1)  && (cst.recv[3]+cst.recv[4]<0)) {makescript(TODO_RECVBUF_DOWN);}
    if ((cst.send[3]>35*cst.send[4]+1) && (cst.send[3]+cst.send[4]>0)) {makescript(TODO_SENDBUF_UP);}
    if ((cst.send[4]>35*cst.send[3]+1) && (cst.send[3]+cst.send[4]<0)) {makescript(TODO_SENDBUF_DOWN);}

if (vfsu_after>0) vfsu_after=vfsu_after-1;
if (vfsd_after>0) vfsd_after=vfsd_after-1;
if (recu_after>0) recu_after=recu_after-1;
if (recd_after>0) recd_after=recd_after-1;
if (senu_after>0) senu_after=senu_after-1;
if (send_after>0) send_after=send_after-1;
// These are mandatory

// Deprecate!
//    makescript(TODO_CHECK_FILENR);
    if (vfsu_after==1) makescript(TODO_VFS_CACHE_DEC);
    if (vfsd_after==1) makescript(TODO_VFS_CACHE_INC);
    if (recu_after==1) makescript(TODO_RECVBUF_DOWN);
    if (recd_after==1) makescript(TODO_RECVBUF_UP);
    if (senu_after==1) makescript(TODO_SENDBUF_DOWN);
    if (send_after==1) makescript(TODO_SENDBUF_UP);

}

// Here we are now, entertain us..
int main()
{
    struct rlimit *rlm;

    cst.send[3]=0;
    cst.memuse[3]=0;
    cst.recv[3]=0;
    cst.buffers[3]=0;
    cst.cached[3]=0;
    logme("***dktune started***\n");
// DO NOT FALL VICTIM TO STUPID RESTRICTIONS!!!
    rlm->rlim_cur=5000;
    rlm->rlim_max=30000;
    setrlimit(RLIMIT_NOFILE,rlm);

    printf("Dynamic kernel tunning wannabe\nBy Milen Rangelov <mrangelov_@_globul_._bg>\n\nDaemonizing...\n");

// Detach from tty..
    if ((fork())!=0) exit(0);
    setsid();
    if ((fork())!=0) exit(0);

// Main Loop
    while (cindex!=-2)
        {
        getdata(10);
        analyze_data();
        givemyadvice();
        }
return 0;
}



Преди някой да почне да критикува: да, знам, не се пише код така, не се парсват стрингове така, не е хубаво толкова много system() да се ползва (съжалявам, набързо така ми е по-лесно), sprintf() хич не е безопасно да се ползва по тоя каруцарски начин и т.н и т.н..

За логиката на това в givemyadvice() и въобще за алгоритъма като цяло също вероятно ще си извадите извода че е дело на психично-болен индивид, няма да се обидя '<img'>

Не ви съветвам да го тествате засега все пак, това е само примерен код, за който засега единствено гарантирам че няма сработи като хората '<img'>

И откъде тези съотношения на базата на които си правя разни изводи: на базата на тестове на две машинки, т.е въобще не са меродавни и има доста да се преработват '<img'>



Активен

"Knowledge is power" - France is Bacon

kennedy

  • Напреднали
  • *****
  • Публикации: 2151
  • Николай Колев
    • Профил
Динамичен kernel tunning?
« Отговор #9 -: Jan 17, 2007, 10:46 »
а дали това няма да ти помогне?
http://kerneltrap.org/node/7578
Активен

"за всичко иде час" Еклесиаст 3:1
всеки пост - отговор на въпрос
-----------------
24.12.2003 "MS Free"

Подобни теми
Заглавие Започната от Отговора Прегледи Последна публикация
Kernel
Настройка на програми
mozly 11 8054 Последна публикация Jan 03, 2003, 19:40
от mozly
kernel i PS/2
Настройка на програми
rat 0 4249 Последна публикация Mar 21, 2003, 15:18
от rat
Kernel
Настройка на програми
mozly 9 3509 Последна публикация Aug 10, 2003, 00:39
от mironcho
kernel 2.6
Настройка на програми
Agent_SMITH 9 4192 Последна публикация Dec 22, 2003, 10:09
от ivo_bg
kernel 2.4.24 vs 2.6.0
Настройка на програми
Agent_SMITH 16 4924 Последна публикация Jan 08, 2004, 23:23
от Agent_SMITH