1
0
Fork 0

re-use buffer for log messages to save mallocs

This commit is contained in:
jsteemann 2016-05-16 21:33:00 +02:00
parent a1e53741f9
commit ec92c1b3c3
4 changed files with 84 additions and 30 deletions

View File

@ -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;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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);

View File

@ -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;
};
}