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>
|
2014-10-25 18:33:52 +00:00
|
|
|
#include <DB/Common/formatReadable.h>
|
2014-05-03 22:57:43 +00:00
|
|
|
#include <DB/IO/WriteHelpers.h>
|
2014-05-08 12:00:47 +00:00
|
|
|
#include <iomanip>
|
2014-05-03 22:57:43 +00:00
|
|
|
|
|
|
|
#include <DB/Common/MemoryTracker.h>
|
|
|
|
|
|
|
|
|
2016-10-24 04:06:27 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int MEMORY_LIMIT_EXCEEDED;
|
|
|
|
}
|
2016-01-11 21:46:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-03 22:57:43 +00:00
|
|
|
MemoryTracker::~MemoryTracker()
|
|
|
|
{
|
2016-01-13 03:59:24 +00:00
|
|
|
if (peak)
|
|
|
|
logPeakMemoryUsage();
|
2016-01-21 01:47:28 +00:00
|
|
|
|
|
|
|
if (amount && !next)
|
2016-12-20 02:29:35 +00:00
|
|
|
CurrentMetrics::sub(metric, amount);
|
2014-05-03 22:57:43 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 15:39:11 +00:00
|
|
|
|
|
|
|
void MemoryTracker::logPeakMemoryUsage() const
|
|
|
|
{
|
|
|
|
LOG_DEBUG(&Logger::get("MemoryTracker"),
|
|
|
|
"Peak memory usage" << (description ? " " + std::string(description) : "")
|
|
|
|
<< ": " << formatReadableSizeWithBinarySuffix(peak) << ".");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-08 15:54:51 +00:00
|
|
|
void MemoryTracker::alloc(Int64 size)
|
2014-05-03 22:57:43 +00:00
|
|
|
{
|
2016-07-31 03:53:16 +00:00
|
|
|
Int64 will_be = amount += size;
|
2014-05-03 22:57:43 +00:00
|
|
|
|
2016-01-21 01:47:28 +00:00
|
|
|
if (!next)
|
2016-12-20 02:29:35 +00:00
|
|
|
CurrentMetrics::add(metric, size);
|
2016-01-21 01:47:28 +00:00
|
|
|
|
2016-07-31 03:53:16 +00:00
|
|
|
/// Using non-thread-safe random number generator. Joint distribution in different threads would not be uniform.
|
|
|
|
/// In this case, it doesn't matter.
|
2015-12-23 07:39:28 +00:00
|
|
|
if (unlikely(fault_probability && drand48() < fault_probability))
|
|
|
|
{
|
|
|
|
free(size);
|
2015-12-30 15:39:11 +00:00
|
|
|
|
|
|
|
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);
|
2015-12-23 07:39:28 +00:00
|
|
|
}
|
|
|
|
|
2014-05-03 22:57:43 +00:00
|
|
|
if (unlikely(limit && will_be > limit))
|
|
|
|
{
|
|
|
|
free(size);
|
2015-12-30 15:39:11 +00:00
|
|
|
|
|
|
|
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);
|
2014-05-03 22:57:43 +00:00
|
|
|
}
|
|
|
|
|
2016-07-31 03:53:16 +00:00
|
|
|
if (will_be > peak.load(std::memory_order_relaxed)) /// Races doesn't matter. Could rewrite with CAS, but not worth.
|
|
|
|
peak.store(will_be, std::memory_order_relaxed);
|
2015-12-30 15:39:11 +00:00
|
|
|
|
|
|
|
if (next)
|
|
|
|
next->alloc(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MemoryTracker::free(Int64 size)
|
|
|
|
{
|
2016-07-31 03:53:16 +00:00
|
|
|
amount -= size;
|
2015-12-30 15:39:11 +00:00
|
|
|
|
|
|
|
if (next)
|
|
|
|
next->free(size);
|
2016-01-21 01:47:28 +00:00
|
|
|
else
|
2016-12-20 02:29:35 +00:00
|
|
|
CurrentMetrics::sub(metric, size);
|
2015-12-30 15:39:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MemoryTracker::reset()
|
|
|
|
{
|
2016-01-21 01:47:28 +00:00
|
|
|
if (!next)
|
2016-12-20 02:29:35 +00:00
|
|
|
CurrentMetrics::sub(metric, amount);
|
2016-01-21 01:47:28 +00:00
|
|
|
|
2015-12-30 15:39:11 +00:00
|
|
|
amount = 0;
|
|
|
|
peak = 0;
|
|
|
|
limit = 0;
|
2014-05-03 22:57:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
__thread MemoryTracker * current_memory_tracker = nullptr;
|