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:
parent
2d36c475f9
commit
c40c26c04c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue