Well, having just tweaked GtkCLists so that setting foreground and
background colors in the summary display didn't turn reading a file into
an N^2 process, I decided to see what else could be improved.
The first profiled run after that showed "ioctl()" and "read()" at the
top; statically-linking Ethereal (and running it in the debugger with
breakpoints set appropriately) showed that most of the "ioctl()"s were
done as a result of the
while (gtk_events_pending())
gtk_main_iteration();
in "wtap_dispatch_cb()" (either in the bowels of GTK+, or Xlib, doing
FIONREADs to see, presumably, whether the X server has sent us
something; this could be different on different platforms, so Your
Mileage May Vary).
I #ifed that out (in practice, we'd probably want to do something such
as doing that on every Nth packet we read in, so that the screen doesn't
completely freeze up - in a half-displayed state - while we're reading
packets in), and "integral()", "fsnprintf()", "strings()", and
"numtoa()" showed up at the top - all related to "snprintf()" used to,
presumably, generate the column data. Fixing that up probably involves
doing that less frequently, somehow (although our "snprintf()" took more
CPU than the Solaris 2.5.1 "sprintf()" took if you just turn
"snprintf()" and "vsnprintf()" into wrappers around "sprintf()" and
"vsprintf()").
After that come "lseek()" and "read()"; I can get rid of "lseek()" by
having Wiretap keep track of the file position itself, but "read()" goes
away only if you don't actually read the packet data.
*If* the OS's VM system isn't too obnoxious, "mmap()" (or its Win32
equivalent) may help here. The trick is that "mmap()" only works if the
file fits in your address space; we can either
1) say "if you have a big honking file, get a machine with a
64-bit processor *and* a 64-bit OS"
or
2) map regions of the file, as necessary, into a window.
(Using "mmap()" in Wiretap would also get rid of "lseek()"....)
"mmap()" wouldn't work on pipes, but Wiretap does seeks and may or may
not work on pipes in any case. ("fseek()"s back to 0 might work OK on a
pipe if you've only read one bufferful of data from the file descriptor,
but I'm not sure how many standard I/O implementations would actually
manage to figure that out and do the right thing.)