Various changes with focus to startup speedup

The startup timeout on Win32 is reduced to 80% without assembler and to 50% with assembler usage (which is optional)
proto.c
 - do not look up in filed tree and inserts in two steps but do it at once
 - next few small speedups
 - some often called elementary functions can be optionally implemented in assembler
 - dispart some functions to see more exact result from profiling
packet-tpnc.c
 - do not reallocate memory for each filed

svn path=/trunk/; revision=23643
This commit is contained in:
Tomas Kukosa 2007-11-28 10:18:16 +00:00
parent 60686647d2
commit ff7c20938e
9 changed files with 360 additions and 48 deletions

View File

@ -592,6 +592,7 @@ REQUIRED_TOOLS=\
/usr/bin/find \
$(PERL) \
$(PYTHON) \
$(NASM) \
sed \
unzip \
wget

View File

@ -80,6 +80,15 @@ MSVC_VARIANT=MSVC6
# Visual C++ 8.0, _MSC_VER 1400, msvcr80.dll
#MSVC_VARIANT=DOTNET20
#
# Optional: To compile some time critical code from assembler instead of C
#
# If you have the NASM compiler, set this to the NASM executable.
#
# If you don't have NASM, comment this line out, so that NASM
# isn't defined.
#
#NASM=c:\progs\nasm\nasm.exe
##### Libraries #####

View File

@ -74,7 +74,9 @@ EXTRA_libwireshark_la_SOURCES = \
g_ascii_strtoull.c \
g_ascii_strtoull.h \
inet_aton.c \
inet_aton.h
inet_aton.h \
asm_utils.c \
asm_utils.h
EXTRA_DIST = \
diam_dict.l \

View File

@ -55,7 +55,13 @@ EXTRA_OBJECTS = \
inet_pton.obj \
inet_ntop.obj \
mkstemp.obj \
strptime.obj
strptime.obj \
!IFDEF NASM
asm_utils_win32_x86.obj
!ELSE
asm_utils.obj
!ENDIF
!IFDEF DOXYGEN
@ -245,6 +251,14 @@ reassemble_test_install:
if exist reassemble_test.exe xcopy reassemble_test.exe $(INSTALL_DIR) /d
#
# Compile some time crtical code from assembler if NASM available
#
!IFDEF NASM
asm_utils_win32_x86.obj: asm_utils_win32_x86.asm
$(NASM) -f win32 -o $@ $?
!ENDIF
# (Windows only) Copy some sources from /trunk to /trunk/epan.
# It is a cleaner to compile these sources seperately with this makefile than
# using the object code compiled by the makefile in /trunk for both dynamically

67
epan/asm_utils.c Normal file
View File

@ -0,0 +1,67 @@
/* asm_utils.c
* Functions optionally implemented in assembler
*
* $Id$
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include <ctype.h>
#include <glib.h>
#include "asm_utils.h"
/* String comparison func for dfilter_token GTree */
int
wrs_strcmp(gconstpointer a, gconstpointer b)
{
return strcmp((const char*)a, (const char*)b);
}
int
wrs_strcmp_with_data(gconstpointer a, gconstpointer b, gpointer user_data _U_)
{
return strcmp((const char*)a, (const char*)b);
}
guchar
wrs_check_charset(const guchar table[256], const char *str)
{
const char *p = str;
guchar c;
do {
c = *(p++);
} while (table[c]);
return c;
}
guint
wrs_str_hash(gconstpointer v)
{
/* 31 bit hash function */
const signed char *p = v;
guint32 h = *p;
if (h)
for (p += 1; *p != '\0'; p++)
h = (h << 5) - h + *p;
return h;
}

37
epan/asm_utils.h Normal file
View File

@ -0,0 +1,37 @@
/* asm_utils.h
* Functions optionally implemented in assembler
*
* $Id$
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __ASM_UTILS_H__
#define __ASM_UTILS_H__
int wrs_strcmp(gconstpointer a, gconstpointer b);
int wrs_strcmp_with_data(gconstpointer a, gconstpointer b, gpointer user_data);
guchar wrs_check_charset(const guchar table[256], const char *str);
guint wrs_str_hash(gconstpointer v);
/* int wrs_count_bitshift(guint32 bitmask); */
#endif /* __ASM_UTILS_H__ */

View File

@ -0,0 +1,147 @@
; asm_utils_win32_x86.c
; Functions optionally implemented in assembler
;
; $Id$
;
; Wireshark - Network traffic analyzer
; By Gerald Combs <gerald@wireshark.org>
; Copyright 1998 Gerald Combs
;
; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version 2
; of the License, or (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
;
SECTION .text
GLOBAL _wrs_strcmp
GLOBAL _wrs_strcmp_with_data
GLOBAL _wrs_check_charset
GLOBAL _wrs_str_hash
align 16
_wrs_strcmp
_wrs_strcmp_with_data
mov ecx, dword [esp + 4] ; a
mov edx, dword [esp + 8] ; b
push ebx
CMP_LOOP:
mov eax, dword [ecx]
mov ebx, dword [edx]
cmp al, bl
jne CMP_NEQ_END
or al, al
jz CMP_EQ_END
cmp ah, bh
jne CMP_NEQ_END
or ah, ah
jz CMP_EQ_END
shr eax, 16
shr ebx, 16
add ecx, byte 4
add edx, byte 4
cmp al, bl
jne CMP_NEQ_END
or al, al
jz CMP_EQ_END
cmp ah, bh
jne CMP_NEQ_END
or ah, ah
jnz CMP_LOOP
CMP_EQ_END:
pop ebx
xor eax, eax
retn
CMP_NEQ_END:
; returns 1 or -1 based on CF flag from the last comparision
sbb eax, eax
pop ebx
shl eax, 1
inc eax
retn
align 16
_wrs_check_charset:
mov edx, dword [esp + 4] ; table
mov ecx, dword [esp + 8] ; str
push edi
push ebx
mov edi, edx
mov bl, byte 0xFF
CHK_LOOP:
mov eax, dword [ecx]
movzx edx, al
test bl, byte [edi+edx]
jz CHK_AL_END
movzx edx, ah
test bl, byte [edi+edx]
jz CHK_AH_END
shr eax, 16
add ecx, byte 4
movzx edx, al
test bl, byte [edi+edx]
jz CHK_AL_END
movzx edx, ah
test bl, byte [edi+edx]
jnz CHK_LOOP
CHK_AH_END
movzx eax, ah
pop ebx
pop edi
retn
CHK_AL_END
movzx eax, al
pop ebx
pop edi
retn
align 16
_wrs_str_hash:
mov edx, dword [esp + 4] ; v
push ebx
xor eax, eax
mov ecx, dword [edx]
or cl, cl
movzx ebx, cl
jz HASH_END
HASH_LOOP:
sub ebx, eax
shl eax, 5
add eax, ebx
or ch, ch
movzx ebx, ch
jz HASH_END
sub ebx, eax
shl eax, 5
add eax, ebx
shr ecx, 16
add edx, byte 4
or cl, cl
movzx ebx, cl
jz HASH_END
sub ebx, eax
shl eax, 5
add eax, ebx
or ch, ch
movzx ebx, ch
jz HASH_END
sub ebx, eax
shl eax, 5
add eax, ebx
mov ecx, dword [edx]
or cl, cl
movzx ebx, cl
jnz HASH_LOOP
HASH_END:
pop ebx
retn

View File

@ -123,6 +123,7 @@ static value_string tpncp_enums_id_vals[MAX_ENUMS_NUM][MAX_ENUM_ENTRIES];
static gchar *tpncp_enums_name_vals[MAX_ENUMS_NUM];
static gint hf_size = 1;
static gint hf_allocated = 0;
static hf_register_info *hf = NULL;
static hf_register_info hf_tpncp[] = {
{
@ -575,9 +576,10 @@ static gint init_tpncp_data_fields_info(tpncp_data_field_info *data_fields_info,
if (!was_registered) {
/* Register non-standard data should be done only once. */
hf_allocated = hf_size+array_length(hf_tpncp)-1;
if ((hf = (hf_register_info *)g_realloc(hf, hf_allocated * sizeof(hf_register_info))) == NULL)
return (-1);
for (index = 0; index < array_length(hf_tpncp); index++) {
if ((hf = (hf_register_info *)realloc(hf, hf_size*sizeof(hf_register_info))) == NULL)
return (-1);
memcpy(hf + (hf_size - 1), hf_tpncp + index, sizeof(hf_register_info));
hf_size++;
}
@ -616,8 +618,8 @@ static gint init_tpncp_data_fields_info(tpncp_data_field_info *data_fields_info,
current_data_id = data_id;
}
else {
if ((current_tpncp_data_field_info->p_next =
(tpncp_data_field_info *)calloc(1, sizeof(tpncp_data_field_info)))
if ((current_tpncp_data_field_info->p_next =
(tpncp_data_field_info *)g_malloc0(sizeof(tpncp_data_field_info)))
== NULL)
return (-1);
current_tpncp_data_field_info = current_tpncp_data_field_info->p_next;
@ -655,8 +657,11 @@ static gint init_tpncp_data_fields_info(tpncp_data_field_info *data_fields_info,
break;
}
/* Register initialized hf_register_info in global database. */
if ((hf = (hf_register_info *)realloc(hf, hf_size*sizeof(hf_register_info))) == NULL)
return (-1);
if (hf_size > hf_allocated) {
hf_allocated += 1024;
if ((hf = (hf_register_info *)g_realloc(hf, hf_allocated * sizeof(hf_register_info))) == NULL)
return (-1);
}
memcpy(hf + hf_size - 1, &hf_entr, sizeof(hf_register_info));
hf_size++;
current_tpncp_data_field_info->tpncp_data_field_sign = tpncp_data_field_sign;

View File

@ -44,6 +44,7 @@
#include "tvbuff.h"
#include "emem.h"
#include "charsets.h"
#include "asm_utils.h"
#ifdef NEED_G_ASCII_STRCASECMP_H
#include "g_ascii_strcasecmp.h"
@ -68,6 +69,19 @@ struct ptvcursor {
gint offset;
};
/* Candidates for assembler */
int
wrs_count_bitshift(guint32 bitmask)
{
int bitshift = 0;
while ((bitmask & (1 << bitshift)) == 0)
bitshift++;
return bitshift;
}
#if GLIB_MAJOR_VERSION < 2
static void *discard_const(const void *const_ptr)
{
@ -209,9 +223,6 @@ proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint lengt
static int proto_register_field_init(header_field_info *hfinfo, int parent);
/* Comparision function for tree insertion. A wrapper around strcmp() */
static int g_strcmp(gconstpointer a, gconstpointer b);
/* special-case header field used within proto.c */
int hf_text_only = -1;
@ -287,6 +298,12 @@ gpa_hfinfo_t gpa_hfinfo;
/* Balanced tree of abbreviations and IDs */
static GTree *gpa_name_tree = NULL;
static header_field_info *same_name_hfinfo;
static void save_same_name_hfinfo(gpointer data)
{
same_name_hfinfo = (header_field_info*)data;
}
/* Points to the first element of an array of Booleans, indexed by
a subtree item type; that array element is TRUE if subtrees of
@ -326,8 +343,8 @@ proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data),
proto_names = g_hash_table_new(g_int_hash, g_int_equal);
proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
proto_short_names = g_hash_table_new(g_str_hash, g_str_equal);
proto_filter_names = g_hash_table_new(g_str_hash, g_str_equal);
proto_cleanup();
@ -339,7 +356,7 @@ proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data),
gpa_hfinfo.len=0;
gpa_hfinfo.allocated_len=0;
gpa_hfinfo.hfi=NULL;
gpa_name_tree = g_tree_new(g_strcmp);
gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
/* Initialize the ftype subsystem */
ftypes_initialize();
@ -386,13 +403,6 @@ proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data),
memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
}
/* String comparison func for dfilter_token GTree */
static int
g_strcmp(gconstpointer a, gconstpointer b)
{
return strcmp((const char*)a, (const char*)b);
}
void
proto_cleanup(void)
{
@ -3498,14 +3508,12 @@ proto_register_protocol(const char *name, const char *short_name, const char *fi
}
g_hash_table_insert(proto_names, key, (gpointer)name);
key = g_malloc (sizeof(gint));
*key = g_str_hash(short_name);
existing_name = g_hash_table_lookup(proto_short_names, key);
existing_name = g_hash_table_lookup(proto_short_names, (gpointer)short_name);
if (existing_name != NULL) {
g_error("Duplicate protocol short_name \"%s\"!"
" This might be caused by an inappropriate plugin or a development error.", short_name);
}
g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
found_invalid = FALSE;
for (i = 0; i < strlen(filter_name); i++) {
@ -3519,14 +3527,12 @@ proto_register_protocol(const char *name, const char *short_name, const char *fi
" Allowed are lower characters, digits, '-', '_' and '.'."
" This might be caused by an inappropriate plugin or a development error.", filter_name);
}
key = g_malloc (sizeof(gint));
*key = g_str_hash(filter_name);
existing_name = g_hash_table_lookup(proto_filter_names, key);
existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
if (existing_name != NULL) {
g_error("Duplicate protocol filter_name \"%s\"!"
" This might be caused by an inappropriate plugin or a development error.", filter_name);
}
g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
/* Add this protocol to the list of known protocols; the list
is sorted by protocol short name. */
@ -3765,9 +3771,29 @@ proto_register_field_array(int parent, hf_register_info *hf, int num_records)
}
}
static int
proto_register_field_init(header_field_info *hfinfo, int parent)
{
/* chars allowed in field abbrev */
static
const guchar fld_abbrev_chars[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
};
/* temporary function containing assert part for easier profiling */
static void tmp_fld_check_assert(header_field_info *hfinfo) {
/* The field must have a name (with length > 0) */
DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
@ -3812,10 +3838,17 @@ proto_register_field_init(header_field_info *hfinfo, int parent)
default:
break;
}
}
static int
proto_register_field_init(header_field_info *hfinfo, int parent)
{
tmp_fld_check_assert(hfinfo);
/* if this is a bitfield, compute bitshift */
if (hfinfo->bitmask) {
while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
hfinfo->bitshift++;
hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
}
hfinfo->parent = parent;
@ -3839,19 +3872,17 @@ proto_register_field_init(header_field_info *hfinfo, int parent)
/* if we have real names, enter this field in the name tree */
if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
const char *p;
header_field_info *same_name_next_hfinfo;
guchar c;
/* Check that the filter name (abbreviation) is legal;
* it must contain only alphanumerics, '-', "_", and ".". */
for (p = hfinfo->abbrev; (c = *p) != '\0'; p++) {
if (!(isalnum(c) || c == '-' || c == '_' || c == '.')) {
fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
c == '.');
}
c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
if (c) {
fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
DISSECTOR_ASSERT(!c);
}
/* We allow multiple hfinfo's to be registered under the same
* abbreviation. This was done for X.25, as, depending
* on whether it's modulo-8 or modulo-128 operation,
@ -3859,11 +3890,11 @@ proto_register_field_init(header_field_info *hfinfo, int parent)
* a byte, and we want to be able to refer to that field
* with one name regardless of whether the packets
* are modulo-8 or modulo-128 packets. */
#if GLIB_MAJOR_VERSION < 2
same_name_hfinfo = g_tree_lookup(gpa_name_tree, discard_const(hfinfo->abbrev));
#else
same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
#endif
same_name_hfinfo = NULL;
g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
/* if it is already present
* the previous hfinfo with the same name is saved
* to same_name_hfinfo by value destroy callback */
if (same_name_hfinfo) {
/* There's already a field with this name.
* Put it after that field in the list of
@ -3882,7 +3913,6 @@ proto_register_field_init(header_field_info *hfinfo, int parent)
same_name_hfinfo->same_name_next = hfinfo;
hfinfo->same_name_prev = same_name_hfinfo;
}
g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
}
return hfinfo->id;