ClickHouse/dbms/src/Common/MemoryTracker.cpp

96 lines
2.2 KiB
C++
Raw Normal View History

2015-09-29 19:19:54 +00:00
#include <common/likely.h>
#include <common/logger_useful.h>
2015-10-05 01:35:28 +00:00
#include <DB/Common/Exception.h>
#include <DB/Common/formatReadable.h>
#include <DB/IO/WriteHelpers.h>
#include <iomanip>
#include <DB/Common/MemoryTracker.h>
namespace DB
{
namespace ErrorCodes
{
extern const int MEMORY_LIMIT_EXCEEDED;
}
}
MemoryTracker::~MemoryTracker()
{
logPeakMemoryUsage();
}
void MemoryTracker::logPeakMemoryUsage() const
{
LOG_DEBUG(&Logger::get("MemoryTracker"),
"Peak memory usage" << (description ? " " + std::string(description) : "")
<< ": " << formatReadableSizeWithBinarySuffix(peak) << ".");
}
void MemoryTracker::alloc(Int64 size)
{
Int64 will_be = __sync_add_and_fetch(&amount, size);
/// Используется непотокобезопасный генератор случайных чисел. Совместное распределение в разных потоках не будет равномерным.
/// В данном случае, это нормально.
if (unlikely(fault_probability && drand48() < fault_probability))
{
free(size);
std::stringstream message;
message << "Memory tracker";
if (description)
message << " " << description;
message << ": fault injected. Would use " << formatReadableSizeWithBinarySuffix(will_be)
<< " (attempt to allocate chunk of " << size << " bytes)"
<< ", maximum: " << formatReadableSizeWithBinarySuffix(limit);
throw DB::Exception(message.str(), DB::ErrorCodes::MEMORY_LIMIT_EXCEEDED);
}
if (unlikely(limit && will_be > limit))
{
free(size);
std::stringstream message;
message << "Memory limit";
if (description)
message << " " << description;
message << " exceeded: would use " << formatReadableSizeWithBinarySuffix(will_be)
<< " (attempt to allocate chunk of " << size << " bytes)"
<< ", maximum: " << formatReadableSizeWithBinarySuffix(limit);
throw DB::Exception(message.str(), DB::ErrorCodes::MEMORY_LIMIT_EXCEEDED);
}
if (will_be > peak)
peak = will_be;
if (next)
next->alloc(size);
}
void MemoryTracker::free(Int64 size)
{
__sync_sub_and_fetch(&amount, size);
if (next)
next->free(size);
}
void MemoryTracker::reset()
{
amount = 0;
peak = 0;
limit = 0;
}
__thread MemoryTracker * current_memory_tracker = nullptr;