Ethereal-dev: [Ethereal-dev] Re: Improving filter speed

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: ronnie sahlberg <ronniesahlberg@xxxxxxxxx>
Date: Thu, 5 May 2005 06:36:35 -0400
On 5/5/05, Guy Harris <gharris@xxxxxxxxx> wrote:
> ronnie sahlberg wrote:
> > That was from the packet-... .c patches   resetting tree to NULL to
> early.
> > 
> > Works now.
> 
> I assume that, to achieve the maximum speedup, every dissector would 
> need to have the
> 
>  if (!proto_field_is_referenced(parent_tree, proto_xxx)) {
>   tree = NULL;
>   subtree = NULL;
>  }
> 
> code?

Yes.
Modulo the escapes needed to make it still handle updates of the
various columns which needs to be filled regardless of whether we
filter or not.

There are also a lot of expensive val_to_str() calls that should be
filtered out when not nessecary (most of them would dissapear from the
codepath with the change you menation).

We should also optimize further by doing proper refcounting and
distinguish between filters referencing only the protocol name (common
color filters?) and filters of sub fields. so that even if the filter
"tcp" is used we can still make tree==NULL above.



Another unrelated performance issue i belive is there, but have not
collected hard data for yet it that i suspect that the ghashtable
routines are slow for how we use them.
I do see a huge slowdown in filtering when hashtable intensive
functions such as TCP analysis is used and there is a massive numnber
of different tcp sessions in the trace.
I will try this weekend to do some real hard testing on this and see
if it is possible to implement a small semi-simple  ghashtable...
replacement (using the same names, same signature to be drop in
compatible) and if there is any measureable gain in performance for
large hashtables.
I think   if performance gain is <20% for tables with a large
(thousands) number of entries it is not worth bothering about.
My feel is that it seems for certain large captures that filtering
starts being very fast and then gradually slowing down to a crawl
towards the end for in particular traces with many many tcp sessions.

I have a theoretical model for a design of a very fast, reasonably
safe hash that can self-adjust to always use the optimal hash key
using radix-sort and close-to-zero cost for determining the optimal
byte in the key to use for hashing.
I need to test it further and also see whether it is useful to add
subhashes for when very many items go into the same bucket.
I might be having some code this weekend (unlikely) with design ideas
available for comments.





> 
> If so, perhaps there can be some sort of standard {routine,macro,...} to 
> use at the beginning of a dissector to create the top-level item and do 
> the check.  (Also, perhaps the routine should be renamed, to take into 
> account the fact that it returns TRUE if either
> 
>  1) a field for that protocol is used in the filter expression
> 
> or
> 
>  2) the tree is visible.)
> 

Yes,
An idea i toyed with to make this apply with no changes at all for any
of the dissectors were to build this into the call_dissector  helpers.
If the helper decides to call dissector_X   first check if protocol X
is referenced and if not, just set tree==NULL before even calling the
dissector.
This wouldnt work that well for protocols such as NLM  or others that
use dissection helpers and thus filter fields from other protocols  so
it would have required a new style of proto_registration routine. :-(

NLM is using the NFS filehandle dissector helpers and thus  we have to
be careful to make sure nfs.fh.hash   still work for NLM and that tree
is not set to NULL for NLM in this case.