ss: speedup resolve_service()

Lets implement a full cache with proper hash table, memory got cheaper
these days.

Before :

$ time ss -t | wc -l
529678

real	0m22.708s
user	0m19.591s
sys	0m2.969s

After :

$ time ss -t | wc -l
528291

real	0m5.078s
user	0m4.099s
sys	0m0.985s

Signed-off-by: Eric Dumazet <edumazet@google.com>
This commit is contained in:
Eric Dumazet 2015-05-29 04:45:48 -07:00 committed by Stephen Hemminger
parent d2055ea597
commit 22588a0e65

View File

@ -858,8 +858,7 @@ static const char *print_ms_timer(int timeout)
return buf; return buf;
} }
struct scache struct scache {
{
struct scache *next; struct scache *next;
int port; int port;
char *name; char *name;
@ -949,11 +948,15 @@ static const char *__resolve_service(int port)
return NULL; return NULL;
} }
#define SCACHE_BUCKETS 1024
static struct scache *cache_htab[SCACHE_BUCKETS];
static const char *resolve_service(int port) static const char *resolve_service(int port)
{ {
static char buf[128]; static char buf[128];
static struct scache cache[256]; struct scache *c;
const char *res;
int hash;
if (port == 0) { if (port == 0) {
buf[0] = '*'; buf[0] = '*';
@ -961,45 +964,35 @@ static const char *resolve_service(int port)
return buf; return buf;
} }
if (resolve_services) { if (!resolve_services)
if (dg_proto == RAW_PROTO) { goto do_numeric;
if (dg_proto == RAW_PROTO)
return inet_proto_n2a(port, buf, sizeof(buf)); return inet_proto_n2a(port, buf, sizeof(buf));
} else {
struct scache *c;
const char *res;
int hash = (port^(((unsigned long)dg_proto)>>2))&255;
for (c = &cache[hash]; c; c = c->next) {
if (c->port == port && hash = (port^(((unsigned long)dg_proto)>>2)) % SCACHE_BUCKETS;
c->proto == dg_proto) {
if (c->name) for (c = cache_htab[hash]; c; c = c->next) {
return c->name; if (c->port == port && c->proto == dg_proto)
goto do_numeric; goto do_cache;
}
} }
if ((res = __resolve_service(port)) != NULL) { c = malloc(sizeof(*c));
if ((c = malloc(sizeof(*c))) == NULL) if (!c)
goto do_numeric; goto do_numeric;
} else { res = __resolve_service(port);
c = &cache[hash];
if (c->name)
free(c->name);
}
c->port = port; c->port = port;
c->name = NULL; c->name = res ? strdup(res) : NULL;
c->proto = dg_proto; c->proto = dg_proto;
if (res) { c->next = cache_htab[hash];
c->name = strdup(res); cache_htab[hash] = c;
c->next = cache[hash].next;
cache[hash].next = c; do_cache:
}
if (c->name) if (c->name)
return c->name; return c->name;
}
}
do_numeric: do_numeric:
sprintf(buf, "%u", port); sprintf(buf, "%u", port);
return buf; return buf;
} }