mirror of
https://github.com/zeek/zeek.git
synced 2025-10-09 01:58:20 +00:00
util: optimize expand_escape() by avoiding sscanf()
sscanf() is notoriously slow, and the default scripts have lots of hex escapes. This patch reduces Zeek's startup time by 9%. Before: 245.04 msec task-clock:u # 1.002 CPUs utilized 0 context-switches:u # 0.000 K/sec 0 cpu-migrations:u # 0.000 K/sec 16,411 page-faults:u # 0.067 M/sec 629,238,575 cycles:u # 2.568 GHz 1,237,236,556 instructions:u # 1.97 insn per cycle 262,223,957 branches:u # 1070.142 M/sec 3,351,083 branch-misses:u # 1.28% of all branches After: 220.99 msec task-clock:u # 1.002 CPUs utilized 0 context-switches:u # 0.000 K/sec 0 cpu-migrations:u # 0.000 K/sec 16,419 page-faults:u # 0.074 M/sec 544,603,653 cycles:u # 2.464 GHz 1,065,862,324 instructions:u # 1.96 insn per cycle 229,207,957 branches:u # 1037.181 M/sec 3,045,270 branch-misses:u # 1.33% of all branches
This commit is contained in:
parent
70b45d1aba
commit
0b3317b1c2
1 changed files with 52 additions and 21 deletions
73
src/util.cc
73
src/util.cc
|
@ -292,6 +292,26 @@ int streq(const char* s1, const char* s2)
|
|||
return ! strcmp(s1, s2);
|
||||
}
|
||||
|
||||
static constexpr int ParseOctDigit(char ch) noexcept
|
||||
{
|
||||
if (ch >= '0' && ch <= '7')
|
||||
return ch - '0';
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static constexpr int ParseHexDigit(char ch) noexcept
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return ch - '0';
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
return 0xa + ch - 'a';
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
return 0xa + ch - 'A';
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int expand_escape(const char*& s)
|
||||
{
|
||||
switch ( *(s++) ) {
|
||||
|
@ -309,23 +329,29 @@ int expand_escape(const char*& s)
|
|||
--s; // put back the first octal digit
|
||||
const char* start = s;
|
||||
|
||||
// Don't increment inside loop control
|
||||
// because if isdigit() is a macro it might
|
||||
// expand into multiple increments ...
|
||||
// require at least one octal digit and parse at most three
|
||||
|
||||
// Here we define a maximum length for escape sequence
|
||||
// to allow easy handling of string like: "^H0" as
|
||||
// "\0100".
|
||||
|
||||
for ( int len = 0; len < 3 && isascii(*s) && isdigit(*s);
|
||||
++s, ++len)
|
||||
;
|
||||
|
||||
int result;
|
||||
if ( sscanf(start, "%3o", &result) != 1 )
|
||||
int result = ParseOctDigit(*s++);
|
||||
if (result < 0)
|
||||
{
|
||||
reporter->Warning("bad octal escape: %s ", start);
|
||||
result = 0;
|
||||
reporter->Warning("bad octal escape: %s", start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// second digit?
|
||||
int digit = ParseOctDigit(*s);
|
||||
if (digit >= 0)
|
||||
{
|
||||
result = (result << 3) | digit;
|
||||
++s;
|
||||
|
||||
// third digit?
|
||||
digit = ParseOctDigit(*s);
|
||||
if (digit >= 0)
|
||||
{
|
||||
result = (result << 3) | digit;
|
||||
++s;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -336,15 +362,20 @@ int expand_escape(const char*& s)
|
|||
const char* start = s;
|
||||
|
||||
// Look at most 2 characters, so that "\x0ddir" -> "^Mdir".
|
||||
for ( int len = 0; len < 2 && isascii(*s) && isxdigit(*s);
|
||||
++s, ++len)
|
||||
;
|
||||
|
||||
int result;
|
||||
if ( sscanf(start, "%2x", &result) != 1 )
|
||||
int result = ParseHexDigit(*s++);
|
||||
if (result < 0)
|
||||
{
|
||||
reporter->Warning("bad hexadecimal escape: %s", start);
|
||||
result = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// second digit?
|
||||
int digit = ParseHexDigit(*s);
|
||||
if (digit >= 0)
|
||||
{
|
||||
result = (result << 4) | digit;
|
||||
++s;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue