Merge pull request #8985 from ClickHouse/aku/demangle-faster

Avoid extra copying when demangling names.
This commit is contained in:
Alexander Kuzmenkov 2020-02-06 14:57:56 +03:00 committed by GitHub
commit 7f9bab3fc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 24 deletions

View File

@ -73,9 +73,15 @@ public:
for (size_t i = 0; i < input_rows_count; ++i)
{
StringRef source = column_concrete->getDataAt(i);
int status = 0;
std::string demangled = demangle(source.data, status);
result_column->insertDataWithTerminatingZero(demangled.data(), demangled.size() + 1);
auto demangled = tryDemangle(source.data);
if (demangled)
{
result_column->insertDataWithTerminatingZero(demangled.get(), strlen(demangled.get()));
}
else
{
result_column->insertDataWithTerminatingZero(source.data, source.size);
}
}
block.getByPosition(result).column = std::move(result_column);

View File

@ -1,5 +1,6 @@
#pragma once
#include <memory>
#include <string>
@ -14,3 +15,18 @@ inline std::string demangle(const char * name)
int status = 0;
return demangle(name, status);
}
// abi::__cxa_demangle returns a C string of known size that should be deleted
// with free().
struct FreeingDeleter
{
template <typename PointerType>
void operator() (PointerType ptr)
{
std::free(ptr);
}
};
typedef std::unique_ptr<char, FreeingDeleter> DemangleResult;
DemangleResult tryDemangle(const char * name);

View File

@ -10,6 +10,11 @@
#if _MSC_VER || MEMORY_SANITIZER
DemangleResult tryDemangle(const char * name)
{
return DemangleResult{};
}
std::string demangle(const char * name, int & status)
{
status = 0;
@ -21,28 +26,27 @@ std::string demangle(const char * name, int & status)
#include <stdlib.h>
#include <cxxabi.h>
std::string demangle(const char * name, int & status)
static DemangleResult tryDemangle(const char * name, int & status)
{
std::string res;
char * demangled_str = abi::__cxa_demangle(name, 0, 0, &status);
if (demangled_str)
{
try
{
res = demangled_str;
}
catch (...)
{
free(demangled_str);
throw;
}
free(demangled_str);
}
else
res = name;
return res;
return DemangleResult(abi::__cxa_demangle(name, nullptr, nullptr, &status));
}
DemangleResult tryDemangle(const char * name)
{
int status = 0;
return tryDemangle(name, status);
}
std::string demangle(const char * name, int & status)
{
auto result = tryDemangle(name, status);
if (result)
{
return std::string(result.get());
}
return name;
}
#endif