Follow Stream: ensure linear performance with many packets

Reverse the payload chunks list to achieve a running time of O(n) rather
than O(n²) for insertion of all chunks. Executing a RelWithDebInfo+ASAN
build with `tshark -r chargen-session.pcapng.gz -qz follow,tcp,hex,0`
previously took 11m5s to complete, but now finishes in 16 seconds.

Tested using a capture file with 152k TCP packets (from bug 11777).
Backport note: must update ui/gtk/follow_stream.c too.

Change-Id: Icf70d45f33d4399e53209fb6199d3809608c8d99
Reviewed-on: https://code.wireshark.org/review/28595
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Peter Wu 2018-07-04 21:53:53 +02:00 committed by Anders Broman
parent 2d36c475f9
commit c40c26c04c
7 changed files with 14 additions and 14 deletions

View File

@ -514,8 +514,8 @@ ssl_follow_tap_listener(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _
appl_data->plain_data,
appl_data->data_len);
/* Append the record to the follow_info structure. */
follow_info->payload = g_list_append(follow_info->payload, follow_record);
/* Add the record to the follow_info structure. */
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
follow_info->bytes_written[from] += appl_data->data_len;
}

View File

@ -1001,7 +1001,7 @@ check_follow_fragments(follow_info_t *follow_info, gboolean is_server, guint32 a
fragment->data->data + new_pos,
new_frag_size);
follow_info->payload = g_list_append(follow_info->payload, follow_record);
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
}
follow_info->seq[is_server] += (fragment->data->len - new_pos);
@ -1019,7 +1019,7 @@ check_follow_fragments(follow_info_t *follow_info, gboolean is_server, guint32 a
if( EQ_SEQ(fragment->seq, follow_info->seq[is_server]) ) {
/* this fragment fits the stream */
if( fragment->data->len > 0 ) {
follow_info->payload = g_list_append(follow_info->payload, fragment);
follow_info->payload = g_list_prepend(follow_info->payload, fragment);
}
follow_info->seq[is_server] += fragment->data->len;
@ -1047,7 +1047,7 @@ check_follow_fragments(follow_info_t *follow_info, gboolean is_server, guint32 a
follow_record->seq = lowest_seq;
follow_info->seq[is_server] = lowest_seq;
follow_info->payload = g_list_append(follow_info->payload, follow_record);
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
return TRUE;
}
@ -1094,7 +1094,7 @@ follow_tcp_tap_listener(void *tapdata, packet_info *pinfo,
follow_info->seq[follow_record->is_server]++;
follow_info->bytes_written[follow_record->is_server] += follow_record->data->len;
follow_info->payload = g_list_append(follow_info->payload, follow_record);
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
return FALSE;
}
@ -1141,7 +1141,7 @@ follow_tcp_tap_listener(void *tapdata, packet_info *pinfo,
follow_info->seq[follow_record->is_server]++;
if (data_length > 0) {
follow_info->bytes_written[follow_record->is_server] += follow_record->data->len;
follow_info->payload = g_list_append(follow_info->payload, follow_record);
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
added_follow_record = TRUE;
}

View File

@ -142,7 +142,7 @@ follow_info_free(follow_info_t* follow_info)
GList *cur;
follow_record_t *follow_record;
for(cur = follow_info->payload; cur; cur = g_list_next(cur)) {
for (cur = follow_info->payload; cur; cur = g_list_next(cur)) {
if(cur->data) {
follow_record = (follow_record_t *)cur->data;
if(follow_record->data)
@ -206,7 +206,7 @@ follow_tvb_tap_listener(void *tapdata, packet_info *pinfo,
/* update stream counter */
follow_info->bytes_written[follow_record->is_server] += follow_record->data->len;
follow_info->payload = g_list_append(follow_info->payload, follow_record);
follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
return FALSE;
}

View File

@ -84,7 +84,7 @@ typedef struct {
typedef struct _follow_info {
show_stream_t show_stream;
char *filter_out_filter;
GList *payload;
GList *payload; /* "follow_record_t" entries, in reverse order. */
guint bytes_written[2]; /* Index with FROM_CLIENT or FROM_SERVER for readability. */
guint32 seq[2]; /* TCP only */
GList *fragments[2]; /* TCP only */

View File

@ -2564,7 +2564,7 @@ sharkd_session_process_follow(char *buf, const jsmntok_t *tokens, int count)
printf(",\"payloads\":[");
for (cur = follow_info->payload; cur; cur = g_list_next(cur))
for (cur = g_list_last(follow_info->payload); cur; cur = g_list_previous(cur))
{
follow_record = (follow_record_t *) cur->data;

View File

@ -184,9 +184,9 @@ static void follow_draw(void *contextp)
else
printf("Node 1: %s:%u\n", buf, follow_info->server_port);
for (cur = follow_info->payload, chunk = 1;
for (cur = g_list_last(follow_info->payload), chunk = 1;
cur != NULL;
cur = g_list_next(cur), chunk++)
cur = g_list_previous(cur), chunk++)
{
follow_record = (follow_record_t *)cur->data;
if (!follow_record->is_server) {

View File

@ -1004,7 +1004,7 @@ FollowStreamDialog::readFollowStream()
elapsed_timer.start();
for (cur = follow_info_.payload; cur; cur = g_list_next(cur)) {
for (cur = g_list_last(follow_info_.payload); cur; cur = g_list_previous(cur)) {
if (dialogClosed()) break;
follow_record = (follow_record_t *)cur->data;