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
71
src/util.cc
71
src/util.cc
|
@ -292,6 +292,26 @@ int streq(const char* s1, const char* s2)
|
||||||
return ! strcmp(s1, 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)
|
int expand_escape(const char*& s)
|
||||||
{
|
{
|
||||||
switch ( *(s++) ) {
|
switch ( *(s++) ) {
|
||||||
|
@ -309,23 +329,29 @@ int expand_escape(const char*& s)
|
||||||
--s; // put back the first octal digit
|
--s; // put back the first octal digit
|
||||||
const char* start = s;
|
const char* start = s;
|
||||||
|
|
||||||
// Don't increment inside loop control
|
// require at least one octal digit and parse at most three
|
||||||
// because if isdigit() is a macro it might
|
|
||||||
// expand into multiple increments ...
|
|
||||||
|
|
||||||
// Here we define a maximum length for escape sequence
|
int result = ParseOctDigit(*s++);
|
||||||
// to allow easy handling of string like: "^H0" as
|
if (result < 0)
|
||||||
// "\0100".
|
|
||||||
|
|
||||||
for ( int len = 0; len < 3 && isascii(*s) && isdigit(*s);
|
|
||||||
++s, ++len)
|
|
||||||
;
|
|
||||||
|
|
||||||
int result;
|
|
||||||
if ( sscanf(start, "%3o", &result) != 1 )
|
|
||||||
{
|
{
|
||||||
reporter->Warning("bad octal escape: %s", start);
|
reporter->Warning("bad octal escape: %s", start);
|
||||||
result = 0;
|
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;
|
return result;
|
||||||
|
@ -336,15 +362,20 @@ int expand_escape(const char*& s)
|
||||||
const char* start = s;
|
const char* start = s;
|
||||||
|
|
||||||
// Look at most 2 characters, so that "\x0ddir" -> "^Mdir".
|
// Look at most 2 characters, so that "\x0ddir" -> "^Mdir".
|
||||||
for ( int len = 0; len < 2 && isascii(*s) && isxdigit(*s);
|
|
||||||
++s, ++len)
|
|
||||||
;
|
|
||||||
|
|
||||||
int result;
|
int result = ParseHexDigit(*s++);
|
||||||
if ( sscanf(start, "%2x", &result) != 1 )
|
if (result < 0)
|
||||||
{
|
{
|
||||||
reporter->Warning("bad hexadecimal escape: %s", start);
|
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;
|
return result;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue