Rychlost paralelniho resolvovani (long)

Michal Krause michal na krause.cz
Pátek Leden 12 02:48:38 CET 2001


Zdravim,

uz par dni sre snazim vyresit tento problem: napsal jsem pro ucely
Navrcholu specialni web server a v nem je treba prevadet IP adresy na
jmena. Protoze jsem zvolil metodu multiplexovani, nelze dost dobre
mozne resolvovat pri kazdem pozadavku a ani to neni nutne, takze si IP
adresy syslim a zvlastni thread je postupne prevadi. Presto je nutne,
aby to delal co mozna nejrychleji a prave zde jsem tezce narazil. Cim
vice vlaken na resolvovani vytvorim, tim je prevod pomalejsi! Neni to
sice asi linearni, ale znatelne to je velmi dobre.

Nejdriv jsem to odhadoval na nejakou chybu v tom demonovi, takze jsem si
udelal testovaci programek, kteremu predhazuji 1000 IP adres.
Resolvujici thread vypada takto (THREADS = pocet threadu):

void *
resolver(void *arg)
{
        int     i;
        int     id = *(int *)arg;

        struct in_addr  addr;
        char            tmp_buf[1024];
        int             h_err;
        struct hostent  host, *p_host;

        for (i = id * 1000 / THREADS; i < (id + 1) * 1000 / THREADS; i++) {
                if (inet_aton(addrs[i], &addr) == 0)
                        continue;
                else {
                        gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
                                        &host, tmp_buf, 1024, &p_host, &h_err);
                        if (p_host == NULL)
                                strcpy(tmp_buf, "unknown");
                        else
                                strncpy(tmp_buf, host.h_name, 1024);
                }
        }

        return NULL;
}


Prosel jsem si to nekolikrat dokola, ale zjevnou chybu nevidim. Presto
jeden thread zresolvuje tech 1000 adres asi 48 vterin, deset threadu
priblizne za minutu. Ani pri opakovanych testech jsem se s vice vlakny
nedostal na stejny cas, jako s vlaknem jednim.

Zadna dalsi vlakna nebezi (main() jen vytvori thready a vola
pthread_exit()), takze chyba muze byt IMHO jedine v gethostbyaddr_r().
Kdyz jsem mel v podstate tutez funkci vlozenou v serveru, stalo se mi
navic casto, ze se vsechny resolvujici thready blokly prave v
gethostbyaddr_t(), coz jsem ovsem spis prikladal nejake moji chybe. Ted
uz si nejsem tak jist. Po chvili se zase rozbehly. Pro zajemce je zde
vypis stacku:

0x400acdcb in __sigsuspend (set=0xbebfe828) at ../sysdeps/unix/sysv/linux/sigsuspend.c:48
../sysdeps/unix/sysv/linux/sigsuspend.c:48: není souborem ani adresářem.
(gdb) where
#0  0x400acdcb in __sigsuspend (set=0xbebfe828) at ../sysdeps/unix/sysv/linux/sigsuspend.c:48
#1  0x40044c62 in __pthread_wait_for_restart_signal (self=0xbebffe40) at pthread.c:783
#2  0x400462a2 in __pthread_lock (lock=0x4038fe14, self=0xbebffe40) at spinlock.c:68
#3  0x400437ba in __pthread_mutex_lock (mutex=0x4038fe04) at mutex.c:84
#4  0x40389d20 in __res_send (buf=0xbebfeb8c "3+\001", buflen=45, 
    ans=0xbebff3c4 "dóż°ä˙\027@Ěá\027@@ţżž$˙żž13\0031", anssiz=1024) at res_send.c:321
#5  0x4038944e in res_query (name=0xbebfefc0 "42.113.113.195.in-addr.arpa", class=1, type=12, 
    answer=0xbebff3c4 "dóż°ä˙\027@Ěá\027@@ţżž$˙żž13\0031", anslen=1024) at res_query.c:134
#6  0x401fc23d in _nss_dns_gethostbyaddr_r (addr=0xbebffc54 "Ăqq*¨Ř\004\bX\210!@\204üżž˙", len=4, af=2, 
    result=0xbebff83c, buffer=0xbebff854 "ÂŐ ń", buflen=1024, errnop=0xbebffe88, h_errnop=0xbebff850)
    at nss_dns/dns-host.c:260
#7  0x40152926 in __gethostbyaddr_r (addr=0xbebffc54 "Ăqq*¨Ř\004\bX\210!@\204üżž˙", len=4, type=2, 
    resbuf=0xbebff83c, buffer=0xbebff854 "ÂŐ ń", buflen=1024, result=0xbebff838, h_errnop=0xbebff850)
    at ../nss/getXXbyYY_r.c:182
#8  0x804d74e in resolve_address (ip_addr=Cannot access memory at address 0xbec00268.
) at dns_thread.c:46

(mimochodem, nevi nekdo, proc pri attachnuti threadu gdb nelze prohlizet
skoro zadne promenne? - viz argumenty funkci).

Abych nezapomnel, v roli cachujiciho DNS serveru zde bezi dnscache od
DJB, ovsem proti Bindu to dela totez (jenom je to jeste pomalejsi).
Zkousel jsem misto gethostbyaddr_r pouzit funkce z dnslib (taktez djb),
ovsem vysledek me nepotesil - rychlost se nijak zvlast nezlepsila a
navic se nejak vytratilo cachovani - pri opakovanem volani programu s
gethostbyaddr_r klesl cas nekam na jednu az dve vteriny, zatimco s
dnslib to trvalo pokazde stejne (plus minus).

Mozna, ze nekde delam nejakou trivialni chybu, ale uz do toho civim dva
dny a na nic nemuzu prijit. Za kazde nakopnuti budu povdecen...

S pozdravem
-- 
Michal Krause                                                       /\
ICQ: 7665279            Informace (nejenom) ze sveta Linuxu      /\/  \
email: michal na krause.cz _______ http://www.root.cz/ _______ NAVRCHOLU.cz

                           Penguino  veritas


Další informace o konferenci Linux