2022-02-25 11:05:00 +00:00
|
|
|
#if defined(OS_LINUX) || defined(OS_FREEBSD)
|
2020-07-15 11:16:00 +00:00
|
|
|
|
2020-04-19 20:49:13 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2022-02-25 11:05:00 +00:00
|
|
|
#if defined(OS_FREEBSD)
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <sys/user.h>
|
|
|
|
#endif
|
2020-04-19 20:49:13 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
#include "MemoryStatisticsOS.h"
|
|
|
|
|
2022-04-27 15:05:45 +00:00
|
|
|
#include <Common/logger_useful.h>
|
2021-10-02 07:13:14 +00:00
|
|
|
#include <base/getPageSize.h>
|
2020-04-19 20:49:13 +00:00
|
|
|
#include <Common/Exception.h>
|
|
|
|
#include <IO/ReadBufferFromMemory.h>
|
|
|
|
#include <IO/ReadHelpers.h>
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2022-02-25 11:05:00 +00:00
|
|
|
#if defined(OS_LINUX)
|
|
|
|
|
2020-04-19 20:49:13 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int FILE_DOESNT_EXIST;
|
|
|
|
extern const int CANNOT_OPEN_FILE;
|
|
|
|
extern const int CANNOT_READ_FROM_FILE_DESCRIPTOR;
|
2020-05-29 09:45:55 +00:00
|
|
|
extern const int CANNOT_CLOSE_FILE;
|
2020-04-19 20:49:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static constexpr auto filename = "/proc/self/statm";
|
|
|
|
|
|
|
|
MemoryStatisticsOS::MemoryStatisticsOS()
|
|
|
|
{
|
|
|
|
fd = ::open(filename, O_RDONLY | O_CLOEXEC);
|
|
|
|
|
|
|
|
if (-1 == fd)
|
2023-12-15 18:25:49 +00:00
|
|
|
ErrnoException::throwFromPath(
|
|
|
|
errno == ENOENT ? ErrorCodes::FILE_DOESNT_EXIST : ErrorCodes::CANNOT_OPEN_FILE, filename, "Cannot open file {}", filename);
|
2020-04-19 20:49:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MemoryStatisticsOS::~MemoryStatisticsOS()
|
|
|
|
{
|
|
|
|
if (0 != ::close(fd))
|
2020-05-29 09:45:55 +00:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2023-12-15 18:25:49 +00:00
|
|
|
ErrnoException::throwFromPath(
|
|
|
|
ErrorCodes::CANNOT_CLOSE_FILE, filename, "File descriptor for '{}' could not be closed", filename);
|
2020-05-29 09:45:55 +00:00
|
|
|
}
|
|
|
|
catch (const ErrnoException &)
|
|
|
|
{
|
|
|
|
DB::tryLogCurrentException(__PRETTY_FUNCTION__);
|
|
|
|
}
|
|
|
|
}
|
2020-04-19 20:49:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MemoryStatisticsOS::Data MemoryStatisticsOS::get() const
|
|
|
|
{
|
|
|
|
Data data;
|
|
|
|
|
|
|
|
constexpr size_t buf_size = 1024;
|
|
|
|
char buf[buf_size];
|
|
|
|
|
|
|
|
ssize_t res = 0;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
res = ::pread(fd, buf, buf_size, 0);
|
|
|
|
|
|
|
|
if (-1 == res)
|
|
|
|
{
|
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
|
|
|
|
2023-12-15 18:25:49 +00:00
|
|
|
ErrnoException::throwFromPath(ErrorCodes::CANNOT_READ_FROM_FILE_DESCRIPTOR, filename, "Cannot read from file {}", filename);
|
2020-04-19 20:49:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(res >= 0);
|
|
|
|
break;
|
|
|
|
} while (true);
|
|
|
|
|
|
|
|
ReadBufferFromMemory in(buf, res);
|
|
|
|
|
|
|
|
uint64_t unused;
|
|
|
|
readIntText(data.virt, in);
|
|
|
|
skipWhitespaceIfAny(in);
|
|
|
|
readIntText(data.resident, in);
|
|
|
|
skipWhitespaceIfAny(in);
|
|
|
|
readIntText(data.shared, in);
|
|
|
|
skipWhitespaceIfAny(in);
|
|
|
|
readIntText(data.code, in);
|
|
|
|
skipWhitespaceIfAny(in);
|
|
|
|
readIntText(unused, in);
|
|
|
|
skipWhitespaceIfAny(in);
|
|
|
|
readIntText(data.data_and_stack, in);
|
|
|
|
|
2020-10-30 21:24:16 +00:00
|
|
|
size_t page_size = static_cast<size_t>(::getPageSize());
|
|
|
|
data.virt *= page_size;
|
|
|
|
data.resident *= page_size;
|
|
|
|
data.shared *= page_size;
|
|
|
|
data.code *= page_size;
|
|
|
|
data.data_and_stack *= page_size;
|
2020-04-19 20:49:13 +00:00
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2022-02-25 11:05:00 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(OS_FREEBSD)
|
|
|
|
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
2022-02-25 11:37:12 +00:00
|
|
|
extern const int SYSTEM_ERROR;
|
2022-02-25 11:05:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MemoryStatisticsOS::MemoryStatisticsOS()
|
|
|
|
{
|
2022-02-25 14:02:49 +00:00
|
|
|
pagesize = static_cast<size_t>(::getPageSize());
|
2022-02-25 11:05:00 +00:00
|
|
|
self = ::getpid();
|
|
|
|
}
|
|
|
|
|
|
|
|
MemoryStatisticsOS::~MemoryStatisticsOS()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MemoryStatisticsOS::Data MemoryStatisticsOS::get() const
|
|
|
|
{
|
|
|
|
Data data;
|
|
|
|
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, self };
|
|
|
|
struct kinfo_proc kp;
|
|
|
|
size_t len = sizeof(struct kinfo_proc);
|
|
|
|
|
2022-09-07 20:16:15 +00:00
|
|
|
if (-1 == ::sysctl(mib, 4, &kp, &len, nullptr, 0))
|
2023-12-15 18:25:49 +00:00
|
|
|
throw ErrnoException(ErrorCodes::SYSTEM_ERROR, "Cannot sysctl(kern.proc.pid.{})", std::to_string(self));
|
2022-02-25 11:05:00 +00:00
|
|
|
|
|
|
|
if (sizeof(struct kinfo_proc) != len)
|
2022-02-25 11:37:12 +00:00
|
|
|
throw DB::Exception(DB::ErrorCodes::SYSTEM_ERROR, "Kernel returns structure of {} bytes instead of expected {}",
|
2022-02-25 11:05:00 +00:00
|
|
|
len, sizeof(struct kinfo_proc));
|
|
|
|
|
|
|
|
if (sizeof(struct kinfo_proc) != kp.ki_structsize)
|
2022-02-25 14:02:49 +00:00
|
|
|
throw DB::Exception(DB::ErrorCodes::SYSTEM_ERROR, "Kernel structure size ({}) does not match expected ({}).",
|
2022-02-25 11:05:00 +00:00
|
|
|
kp.ki_structsize, sizeof(struct kinfo_proc));
|
|
|
|
|
|
|
|
data.virt = kp.ki_size;
|
|
|
|
data.resident = kp.ki_rssize * pagesize;
|
|
|
|
data.code = kp.ki_tsize * pagesize;
|
|
|
|
data.data_and_stack = (kp.ki_dsize + kp.ki_ssize) * pagesize;
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2020-04-19 20:49:13 +00:00
|
|
|
}
|
2020-07-15 11:16:00 +00:00
|
|
|
|
|
|
|
#endif
|