mirror of https://gitee.com/bigwinds/arangodb
re-use buffer for log messages to save mallocs
This commit is contained in:
parent
a1e53741f9
commit
ec92c1b3c3
|
@ -895,15 +895,27 @@ char* TRI_SHA256String(char const* source, size_t sourceLen, size_t* dstLen) {
|
|||
|
||||
char* TRI_EscapeControlsCString(TRI_memory_zone_t* zone, char const* in,
|
||||
size_t inLength, size_t* outLength,
|
||||
bool appendNewline, bool truncate) {
|
||||
bool appendNewline) {
|
||||
char* buffer = static_cast<char*>(
|
||||
TRI_Allocate(zone, (4 * inLength) + 1 + (appendNewline ? 1 : 0), false));
|
||||
TRI_Allocate(zone, TRI_MaxLengthEscapeControlsCString(inLength), false));
|
||||
|
||||
if (buffer == nullptr) {
|
||||
return TRI_EscapeControlsCString(in, inLength, buffer, outLength, appendNewline);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief escapes special characters using C escapes
|
||||
/// the target buffer must have been allocated already and big enough to hold
|
||||
/// the result of at most (4 * inLength) + 2 bytes!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* TRI_EscapeControlsCString(char const* in, size_t inLength,
|
||||
char* out, size_t* outLength,
|
||||
bool appendNewline) {
|
||||
if (out == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char* qtr = buffer;
|
||||
char* qtr = out;
|
||||
char const* ptr;
|
||||
char const* end;
|
||||
|
||||
|
@ -945,22 +957,8 @@ char* TRI_EscapeControlsCString(TRI_memory_zone_t* zone, char const* in,
|
|||
}
|
||||
|
||||
*qtr = '\0';
|
||||
*outLength = static_cast<size_t>(qtr - buffer);
|
||||
|
||||
if (!truncate) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
qtr = static_cast<char*>(TRI_Allocate(zone, (*outLength) + 1, false));
|
||||
|
||||
if (qtr != nullptr) {
|
||||
memcpy(qtr, buffer, (*outLength) + 1);
|
||||
}
|
||||
|
||||
TRI_Free(zone, buffer);
|
||||
|
||||
// may be nullptr
|
||||
return qtr;
|
||||
*outLength = static_cast<size_t>(qtr - out);
|
||||
return out;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -205,13 +205,32 @@ char* TRI_DecodeHexString(char const* source, size_t sourceLen, size_t* dstLen);
|
|||
|
||||
char* TRI_SHA256String(char const* source, size_t sourceLen, size_t* dstLen);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the maximum result length for an escaped string
|
||||
/// (4 * inLength) + 2 bytes!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
constexpr size_t TRI_MaxLengthEscapeControlsCString(size_t inLength) {
|
||||
return (4 * inLength) + 2; // for newline and 0 byte
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief escapes special characters using C escapes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* TRI_EscapeControlsCString(TRI_memory_zone_t*, char const* in,
|
||||
size_t inLength, size_t* outLength,
|
||||
bool appendNewline, bool truncate);
|
||||
bool appendNewline);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief escapes special characters using C escapes
|
||||
/// the target buffer must have been allocated already and big enough to hold
|
||||
/// the result of at most (4 * inLength) + 2 bytes!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* TRI_EscapeControlsCString(char const* in, size_t inLength,
|
||||
char* out, size_t* outLength,
|
||||
bool appendNewline);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief escapes special characters using unicode escapes
|
||||
|
|
|
@ -90,7 +90,7 @@ void LogAppenderFile::close() {
|
|||
|
||||
LogAppenderFile::LogAppenderFile(std::string const& filename,
|
||||
std::string const& filter)
|
||||
: LogAppender(filter), _pos(-1) {
|
||||
: LogAppender(filter), _pos(-1), _buffer(nullptr), _bufferSize(0) {
|
||||
// logging to stdout
|
||||
if (filename == "-") {
|
||||
_pos = 0;
|
||||
|
@ -123,7 +123,7 @@ LogAppenderFile::LogAppenderFile(std::string const& filename,
|
|||
}
|
||||
|
||||
if (pos == _fds.size()) {
|
||||
_fds.emplace_back(make_pair(fd, filename));
|
||||
_fds.emplace_back(std::make_pair(fd, filename));
|
||||
} else {
|
||||
_fds[pos].first = fd;
|
||||
}
|
||||
|
@ -132,6 +132,10 @@ LogAppenderFile::LogAppenderFile(std::string const& filename,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogAppenderFile::~LogAppenderFile() {
|
||||
delete[] _buffer;
|
||||
}
|
||||
|
||||
bool LogAppenderFile::logMessage(LogLevel level, std::string const& message,
|
||||
size_t offset) {
|
||||
|
@ -145,14 +149,41 @@ bool LogAppenderFile::logMessage(LogLevel level, std::string const& message,
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t escapedLength;
|
||||
char* escaped =
|
||||
TRI_EscapeControlsCString(TRI_UNKNOWN_MEM_ZONE, message.c_str(),
|
||||
message.size(), &escapedLength, true, false);
|
||||
// check required output length
|
||||
size_t const neededBufferSize = TRI_MaxLengthEscapeControlsCString(message.size());
|
||||
|
||||
// check if we can re-use our already existing buffer
|
||||
if (neededBufferSize > _bufferSize) {
|
||||
delete[] _buffer;
|
||||
_buffer = nullptr;
|
||||
_bufferSize = 0;
|
||||
}
|
||||
|
||||
if (escaped != nullptr) {
|
||||
writeLogFile(fd, escaped, static_cast<ssize_t>(escapedLength));
|
||||
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, escaped);
|
||||
if (_buffer == nullptr) {
|
||||
// create a new buffer
|
||||
try {
|
||||
// grow buffer exponentially
|
||||
_buffer = new char[neededBufferSize * 2];
|
||||
_bufferSize = neededBufferSize * 2;
|
||||
} catch (...) {
|
||||
// if allocation fails, simply give up
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
TRI_ASSERT(_buffer != nullptr);
|
||||
|
||||
size_t escapedLength;
|
||||
// this is guaranteed to succeed given that we already have a buffer
|
||||
TRI_EscapeControlsCString(message.c_str(), message.size(), _buffer, &escapedLength, true);
|
||||
|
||||
writeLogFile(fd, _buffer, static_cast<ssize_t>(escapedLength));
|
||||
|
||||
if (_bufferSize > 8192) {
|
||||
// free the buffer so the Logger is not hogging so much memory
|
||||
delete[] _buffer;
|
||||
_buffer = nullptr;
|
||||
_bufferSize = 0;
|
||||
}
|
||||
|
||||
return (isatty(fd) != 0);
|
||||
|
|
|
@ -34,6 +34,7 @@ class LogAppenderFile : public LogAppender {
|
|||
|
||||
public:
|
||||
LogAppenderFile(std::string const& filename, std::string const& filter);
|
||||
~LogAppenderFile();
|
||||
|
||||
bool logMessage(LogLevel, std::string const& message,
|
||||
size_t offset) override final;
|
||||
|
@ -48,6 +49,11 @@ class LogAppenderFile : public LogAppender {
|
|||
|
||||
private:
|
||||
ssize_t _pos;
|
||||
|
||||
/// @brief a reusable buffer for log messages
|
||||
char* _buffer;
|
||||
/// @brief allocation size of the buffer
|
||||
size_t _bufferSize;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue