problem: for loops over empty tables are slow.

This change doubles the performance of for loops over empty tables.

A bro binary that prints out this size shows for
testing/external/bro-testing/2009-M57-day11-18.trace, for loops are run
over tables of size:

11477 for size 0
8371 for size 1
1227 for size 3
239 for size 2
141 for size 6
57 for size 5
10 for size 4
5 for size 7
2 for size 13
2 for size 8
2 for size 11
1 for size 9

~53% of the for loops were across an empty table.  These loops come from
things like the for loop in the http script over c$http_state$pending

This change prevents the creation of an iteration cookie entirely if the
table is empty.

Using this test script:

    const scan_ports: table[port] of count = { };

    local x = 0;
    while ( x < 20000000 ) {
        for(p in scan_ports) {
        }
        ++x;
    }

$ time bro.orig -b ___bench.bro

real    0m10.732s
user    0m10.415s
sys     0m0.113s

$ time bro.nocookie -b ___bench.bro

real    0m4.694s
user    0m4.464s
sys     0m0.086s
This commit is contained in:
Justin Azoff 2017-10-17 18:45:06 -04:00
parent bfe94641cf
commit b730874ea1

View file

@ -1292,6 +1292,8 @@ Val* ForStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const
{
TableVal* tv = v->AsTableVal();
const PDict(TableEntryVal)* loop_vals = tv->AsTable();
if (!loop_vals->Length())
return ret;
HashKey* k;
IterCookie* c = loop_vals->InitForIteration();