Currently I'm running nntpcached on a somewhat memory-starved system. Users were complaining that it took too long for trn or tin to start up. As these times varied from 20 minutes to ten hours, I had to agree. It turns out that there's a simple performance modification that can be made to improve the common-case scenario: requesting the active file entry for a single, specific group. Rather than scanning through the entire active list sequentially, doing a glob match against each one, the patch notices when there are no metacharacters in the pattern and traverses the hash table/tree to get directly to the desired group. FWIW, that full search takes about a minute and a half. Repeat for every subscribed-to group at newsreader startup time, and you can see why it might take a really long time to get through that part. This is, of course, only a problem on memory-starved systems. It has no effect on the initial startup delay (twenty minutes for us). This is purely a memory system problem with no obvious and straight-forward work-around. I made the change in 1.0.1, but diff'ing against 1.0.5 shows no other changes in the relevant part of list.c. Therefore, I suspect this will work on any of the 1.0.* versions to date. The hash table size should also be increased, but since our server is already tight on memory, I haven't done this as yet. Our upstream provider has 41000 groups, and the distributed hash table size is 31337. A more appropriate value would be something like 100313, to allow a little more room for growth. Dworkin ================================================================ *** ../nntpcache-1.0.5/list.c Fri Feb 28 19:54:10 1997 --- list.c Tue Apr 22 15:15:23 1997 *************** *** 473,478 **** --- 440,490 ---- emitrn (NNTP_XGTITLE_OK); else emitrn (NNTP_LIST_FOLLOWS); + #if 1 + if (group_pat!=NULL && strchr(group_pat, '*')==NULL && strchr(group_pat, '?')==NULL) + { + struct newsgroup *p = newsgroup_find_add(group_pat, NULL, FALSE); + if (p != NULL) + { + switch (list->type) + { + case l_active: + { + int hi, lo; + if (!p->moderation) + break; + hi = MAX(p->hi, p->hi_server); + if (p->lo>0) + lo = p->lo; + else + lo = 0; + if (p->lo_server>0) + { + if (lo>0) + lo = MIN(lo, p->lo_server); + else + lo = p->lo_server; + } + emitf ("%s %d %d %c\r\n", p->group, hi, lo, p->moderation); + break; + } + case l_active_times: + if (p->creation_time && p->creator) + emitf ("%s %lu %s\r\n", p->group, p->creation_time, p->creator); + break; + case l_xgtitle: + case l_newsgroups: + if (p->desc) + emitf ("%s\t%s\r\n", p->group, p->desc); + break; + default: + break; + } + } + emitrn ("."); + return TRUE; + } + #endif for (n=Ni->newsgroup_head; n; n=n->next) { #ifdef READ_LOCKS