mirror of
https://github.com/matrix-construct/construct
synced 2024-12-29 17:04:03 +01:00
ircd::allocator: Add incore(); replace as fs::fincore() impl.
This commit is contained in:
parent
b1cc013132
commit
536a496bee
4 changed files with 90 additions and 43 deletions
|
@ -46,6 +46,8 @@ namespace ircd::allocator
|
|||
template<class T> T set(const string_view &var, T val);
|
||||
bool trim(const size_t &pad = 0) noexcept; // malloc_trim(3)
|
||||
|
||||
size_t incore(const const_buffer &);
|
||||
|
||||
std::unique_ptr<char, decltype(&std::free)>
|
||||
aligned_alloc(const size_t &align, const size_t &size);
|
||||
}
|
||||
|
@ -60,6 +62,7 @@ namespace ircd::allocator::je
|
|||
namespace ircd
|
||||
{
|
||||
using allocator::aligned_alloc;
|
||||
using allocator::incore;
|
||||
}
|
||||
|
||||
/// Profiling counters. The purpose of this device is to gauge whether unwanted
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace ircd::fs
|
|||
std::string read(const fd &, const read_opts & = read_opts_default);
|
||||
|
||||
// Test whether bytes in the specified range are cached and should not block
|
||||
bool fincore(const fd &, const size_t &, const read_opts & = read_opts_default);
|
||||
bool incore(const fd &, const size_t &, const read_opts & = read_opts_default);
|
||||
|
||||
// Prefetch data for subsequent read(); offset given in opts (WILLNEED).
|
||||
size_t prefetch(const fd &, const size_t &, const read_opts & = read_opts_default);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
#include <RB_INC_SYS_RESOURCE_H
|
||||
#include <RB_INC_SYS_MMAN_H
|
||||
|
||||
// Uncomment or -D this #define to enable our own crude but simple ability to
|
||||
// profile dynamic memory usage. Global `new` and `delete` will be captured
|
||||
|
@ -72,6 +73,83 @@ ircd::allocator::aligned_alloc(const size_t &alignment_,
|
|||
};
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::allocator::incore(const const_buffer &buf)
|
||||
{
|
||||
const auto base
|
||||
{
|
||||
buffer::align(begin(buf), info::page_size)
|
||||
};
|
||||
|
||||
const auto top
|
||||
{
|
||||
buffer::align_up(end(buf), info::page_size)
|
||||
};
|
||||
|
||||
assert(base <= data(buf));
|
||||
const auto below
|
||||
{
|
||||
std::distance(base, begin(buf))
|
||||
};
|
||||
|
||||
assert(top >= data(buf) + size(buf));
|
||||
const auto span
|
||||
{
|
||||
std::distance(base, top)
|
||||
};
|
||||
|
||||
const auto above
|
||||
{
|
||||
std::distance(end(buf), top)
|
||||
};
|
||||
|
||||
assert(span >= 0);
|
||||
assert(above >= 0);
|
||||
assert(below >= 0);
|
||||
assert(above < ssize_t(info::page_size));
|
||||
assert(below < ssize_t(info::page_size));
|
||||
assert(below + ssize_t(size(buf)) + above == span);
|
||||
|
||||
auto remain(span), ret(0L);
|
||||
thread_local uint8_t vec alignas(64) [4096];
|
||||
for(auto i(0); i < span / ssizeof(vec) && remain > 0; ++i)
|
||||
{
|
||||
const auto len
|
||||
{
|
||||
std::min(ssizeof(vec) * ssize_t(info::page_size), remain)
|
||||
};
|
||||
|
||||
assert(len > 0);
|
||||
assert(len <= span);
|
||||
const ssize_t vec_size
|
||||
(
|
||||
std::ceil(len / double(info::page_size))
|
||||
);
|
||||
|
||||
assert(vec_size > 0);
|
||||
assert(vec_size <= ssizeof(vec));
|
||||
syscall(::mincore, mutable_cast(base), len, vec);
|
||||
for(auto j(0); j < vec_size; ++j)
|
||||
ret += (vec[j] & 0x01) * info::page_size;
|
||||
|
||||
remain -= len;
|
||||
assert(remain >= 0);
|
||||
if(!remain && (vec[vec_size - 1] & 0x01)) // last iteration
|
||||
ret -= above;
|
||||
|
||||
assert(ret >= 0);
|
||||
if(i == 0 && (vec[0] & 0x01)) // first iteration
|
||||
ret -= below;
|
||||
|
||||
assert(ret >= 0);
|
||||
}
|
||||
|
||||
assert(remain == 0);
|
||||
assert(ret <= ssize_t(size(buf)));
|
||||
assert(ret >= 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// control panel
|
||||
//
|
||||
|
|
50
ircd/fs.cc
50
ircd/fs.cc
|
@ -806,11 +806,6 @@ ircd::fs::flush(const fd &fd,
|
|||
// fs/read.h
|
||||
//
|
||||
|
||||
namespace ircd::fs
|
||||
{
|
||||
static bool fincore(void *const &map, const size_t &map_size, uint8_t *const &vec, const size_t &vec_size);
|
||||
}
|
||||
|
||||
ircd::fs::read_opts
|
||||
const ircd::fs::read_opts_default
|
||||
{};
|
||||
|
@ -828,13 +823,10 @@ ircd::fs::prefetch(const fd &fd,
|
|||
}
|
||||
|
||||
bool
|
||||
ircd::fs::fincore(const fd &fd,
|
||||
const size_t &count,
|
||||
const read_opts &opts)
|
||||
ircd::fs::incore(const fd &fd,
|
||||
const size_t &count,
|
||||
const read_opts &opts)
|
||||
{
|
||||
using word_t = unsigned long long;
|
||||
thread_local std::array<word_t, 64> tls_vec;
|
||||
|
||||
fs::map::opts map_opts;
|
||||
map_opts.offset = buffer::align(opts.offset, info::page_size);
|
||||
map_opts.blocking = false;
|
||||
|
@ -848,44 +840,18 @@ ircd::fs::fincore(const fd &fd,
|
|||
(map_size + info::page_size - 1) / info::page_size
|
||||
};
|
||||
|
||||
const size_t &vec_size
|
||||
{
|
||||
std::max(map_pages / sizeof(word_t), 1UL)
|
||||
};
|
||||
|
||||
const size_t &dynamic_vec_size
|
||||
{
|
||||
vec_size > tls_vec.size()?
|
||||
vec_size:
|
||||
0UL
|
||||
};
|
||||
|
||||
std::vector<word_t> dynamic_vec(dynamic_vec_size);
|
||||
auto *const vec
|
||||
{
|
||||
dynamic_vec_size?
|
||||
dynamic_vec.data():
|
||||
tls_vec.data()
|
||||
};
|
||||
|
||||
assert(map_opts.offset % 4096 == 0);
|
||||
const fs::map map
|
||||
{
|
||||
fd, map_opts, map_size
|
||||
};
|
||||
|
||||
assert(vec_size > 0 && vec_size <= map_size);
|
||||
return fincore(data(map), map_size, reinterpret_cast<uint8_t *>(vec), vec_size);
|
||||
}
|
||||
const size_t res
|
||||
{
|
||||
allocator::incore(map)
|
||||
};
|
||||
|
||||
bool
|
||||
ircd::fs::fincore(void *const &map,
|
||||
const size_t &map_size,
|
||||
uint8_t *const &vec,
|
||||
const size_t &vec_size)
|
||||
{
|
||||
syscall(::mincore, map, map_size, vec);
|
||||
return std::find(vec, vec + vec_size, 0UL) == vec + vec_size;
|
||||
return res == map_size;
|
||||
}
|
||||
|
||||
std::string
|
||||
|
|
Loading…
Reference in a new issue