Improve performance by using bsearch(3) instead of a std::set

The function name list is already in memory so we can avoid copying it into a std::set
if we sort the list alphabetically. This way no binary search tree has to be allocated.

Before (best of 5 runs):
./testrunner > /dev/null  0,21s user 0,00s system 95% cpu 0,221 total
After (best of 5 runs):
./testrunner > /dev/null  0,20s user 0,00s system 95% cpu 0,210 total
This commit is contained in:
Benjamin Kramer 2009-08-22 20:23:03 +02:00
parent ec050d2563
commit 0d6b6e840d
2 changed files with 28 additions and 43 deletions

View File

@ -23,6 +23,7 @@
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <set>
@ -37,6 +38,28 @@ CheckMemoryLeakInClass instance2;
CheckMemoryLeakStructMember instance3;
}
// This list needs to be alphabetically sorted so we can run bsearch on it
static const char * const call_func_white_list[] =
{
"atof", "atoi", "atol", "clearerr", "delete", "fchmod", "fcntl"
, "fdatasync", "feof", "ferror", "fflush", "fgetc", "fgetpos", "fgets"
, "flock", "for", "fprintf", "fputc", "fputs", "fread", "fseek"
, "fseeko", "fsetpos", "fstat", "fsync", "ftell", "ftello", "ftruncate"
, "fwrite", "getc", "if", "ioctl", "lockf", "lseek", "memchr", "memcpy"
, "memmove", "memset", "posix_fadvise", "posix_fallocate", "pread"
, "printf", "pwrite", "read", "readahead", "readdir", "readdir_r", "readv"
, "realloc", "return", "rewind", "rewinddir", "scandir", "seekdir"
, "setbuf", "setbuffer", "setlinebuf", "setvbuf", "sprintf", "strcasecmp"
, "strcat", "strchr", "strcmp", "strcpy", "stricmp", "strncat", "strncmp"
, "strncpy", "strrchr", "strstr", "strtod", "strtol", "strtoul", "switch"
, "sync_file_range", "telldir", "while", "write", "writev"
};
static int call_func_white_list_compare(const void *a, const void *b)
{
return strcmp((const char *)a, *(const char **)b);
}
//---------------------------------------------------------------------------
bool CheckMemoryLeak::isclass(const Tokenizer *_tokenizer, const Token *tok) const
@ -407,35 +430,6 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok)
return No;
}
void CheckMemoryLeakInFunction::init()
{
static const char * const white_list[] =
{
"if", "for", "while", "return", "switch", "realloc", "delete"
, "strcpy", "strncpy", "strcat", "strncat", "strcmp", "strncmp"
, "strcasecmp", "stricmp", "sprintf", "strchr", "strrchr", "strstr"
, "memset", "memcpy", "memmove", "memchr", "fgets", "fgetc", "getc"
, "fputs", "fputc", "feof", "ferror", "clearerr", "printf", "fprintf"
, "fread", "fwrite", "fflush", "fseek", "fseeko", "ftell", "ftello"
, "fsetpos", "fgetpos", "setvbuf", "setbuf", "setbuffer", "setlinebuf"
, "rewind", "read", "readv", "pread", "readahead", "write", "writev"
, "pwrite", "lseek", "ioctl", "fchmod", "fcntl", "flock", "lockf"
, "ftruncate", "fsync", "fdatasync", "fstat", "sync_file_range"
, "posix_fallocate", "posix_fadvise", "readdir", "readdir_r"
, "rewinddir", "telldir", "seekdir", "scandir", "atoi", "atof", "atol"
, "strtol", "strtoul", "strtod"
, NULL
};
size_t i = 0;
while (white_list[i] != NULL)
{
call_func_white_list.insert(white_list[i]);
++i;
}
}
bool CheckMemoryLeakInFunction::matchFunctionsThatReturnArg(const Token *tok, const unsigned int varid) const
{
return Token::Match(tok, "; %varid% = strcat|memcpy|memmove|strcpy ( %varid% ,", varid);
@ -480,7 +474,9 @@ static int countParameters(const Token *tok)
const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool &all, unsigned int sz)
{
if (call_func_white_list.find(tok->str()) != call_func_white_list.end())
if (bsearch(tok->str().c_str(), call_func_white_list,
sizeof(call_func_white_list) / sizeof(call_func_white_list[0]),
sizeof(call_func_white_list[0]), call_func_white_list_compare))
return 0;
if (getAllocationType(tok, varid) != No || getReallocationType(tok, varid) != No || getDeallocationType(tok, varid) != No)

View File

@ -145,16 +145,12 @@ class CheckMemoryLeakInFunction : private Check, private CheckMemoryLeak
public:
/** This constructor is used when registering this class */
CheckMemoryLeakInFunction() : Check(), CheckMemoryLeak(0, 0)
{
init();
}
{ }
/** This constructor is used when running checks */
CheckMemoryLeakInFunction(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
: Check(tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger)
{
init();
}
{ }
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
{
@ -272,13 +268,6 @@ private:
{
return "Is there any allocated memory when a function goes out of scope";
}
// Keywords and function names which not allocating nor deallocating memory
// (used by call_func())
std::set<std::string> call_func_white_list;
// Called in all constructors
void init();
};