mirror of
https://github.com/Jeffrey-Sardina/liberated-systemd.git
synced 2026-10-19 01:29:53 -05:00
journal-file: look up the window of an object only once
journal_file_move_to_object() maps the object header, reads the object size from it, and then looks up the window again for the whole object. That second lookup finds the same window nearly every time, since windows are 8 MiB and most objects are small. Have mmap_cache_fd_get() return how many bytes the window has after the offset, and skip the second lookup when the object fits in the window and in the file. Reading 1M entries of a real journal takes 10.7% fewer cycles.
This commit is contained in:
1 parent
f992bce2c1
commit
25428cd656
5 files changed
+57
-20
No files matched your search
@@ -848,14 +848,16 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
|
||||
return journal_file_fstat(f);
|
||||
}
|
||||
|
||||
static int journal_file_move_to(
|
||||
static int journal_file_move_to_full(
|
||||
JournalFile *f,
|
||||
ObjectType type,
|
||||
bool keep_always,
|
||||
uint64_t offset,
|
||||
uint64_t size,
|
||||
void **ret) {
|
||||
void **ret,
|
||||
uint64_t *ret_size) {
|
||||
|
||||
size_t window_size;
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
@@ -884,7 +886,27 @@ static int journal_file_move_to(
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
return mmap_cache_fd_get(f->cache_fd, type_to_category(type), keep_always, offset, size, &f->last_stat, ret);
|
||||
r = mmap_cache_fd_get(f->cache_fd, type_to_category(type), keep_always, offset, size, &f->last_stat, ret, &window_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* The window is rounded up to whole pages, and may extend beyond the end of the file, which must not
|
||||
* be accessed */
|
||||
if (ret_size)
|
||||
*ret_size = MIN((uint64_t) window_size, (uint64_t) f->last_stat.st_size - offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int journal_file_move_to(
|
||||
JournalFile *f,
|
||||
ObjectType type,
|
||||
bool keep_always,
|
||||
uint64_t offset,
|
||||
uint64_t size,
|
||||
void **ret) {
|
||||
|
||||
return journal_file_move_to_full(f, type, keep_always, offset, size, ret, /* ret_size= */ NULL);
|
||||
}
|
||||
|
||||
static uint64_t minimum_header_size(JournalFile *f, Object *o) {
|
||||
@@ -1106,8 +1128,9 @@ static int check_object(JournalFile *f, Object *o, uint64_t offset) {
|
||||
}
|
||||
|
||||
int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret) {
|
||||
int r;
|
||||
uint64_t size, available;
|
||||
Object *o;
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
@@ -1129,7 +1152,7 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset
|
||||
journal_object_type_to_string(type),
|
||||
offset);
|
||||
|
||||
r = journal_file_move_to(f, type, false, offset, offsetof(ObjectHeader, payload), (void**) &o);
|
||||
r = journal_file_move_to_full(f, type, false, offset, offsetof(ObjectHeader, payload), (void**) &o, &available);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1137,13 +1160,17 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = journal_file_move_to(f, type, false, offset, le64toh(READ_NOW(o->object.size)), (void**) &o);
|
||||
if (r < 0)
|
||||
return r;
|
||||
/* Usually the window of the header contains the whole object, which then needs no second lookup */
|
||||
size = le64toh(READ_NOW(o->object.size));
|
||||
if (size > available) {
|
||||
r = journal_file_move_to(f, type, false, offset, size, (void**) &o);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = check_object_header(f, o, type, offset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = check_object_header(f, o, type, offset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = check_object(f, o, offset);
|
||||
if (r < 0)
|
||||
@@ -4249,7 +4276,7 @@ int journal_file_open(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = mmap_cache_fd_get(f->cache_fd, MMAP_CACHE_CATEGORY_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h);
|
||||
r = mmap_cache_fd_get(f->cache_fd, MMAP_CACHE_CATEGORY_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h, /* ret_size= */ NULL);
|
||||
if (r == -EINVAL) {
|
||||
/* Some file systems (jffs2 or p9fs) don't support mmap() properly (or only read-only
|
||||
* mmap()), and return EINVAL in that case. Let's propagate that as a more recognizable error
|
||||
|
||||
@@ -404,7 +404,7 @@ static int contains_uint64(MMapFileDescriptor *f, uint64_t n, uint64_t p) {
|
||||
|
||||
c = (a + b) / 2;
|
||||
|
||||
r = mmap_cache_fd_get(f, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z);
|
||||
r = mmap_cache_fd_get(f, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z, /* ret_size= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -342,7 +342,8 @@ int mmap_cache_fd_get(
|
||||
uint64_t offset,
|
||||
size_t size,
|
||||
struct stat *st,
|
||||
void **ret) {
|
||||
void **ret,
|
||||
size_t *ret_size) {
|
||||
|
||||
MMapCache *m = mmap_cache_fd_cache(f);
|
||||
Window *w;
|
||||
@@ -386,6 +387,8 @@ found:
|
||||
|
||||
category_attach_window(m, c, w);
|
||||
*ret = (uint8_t*) w->ptr + (offset - w->offset);
|
||||
if (ret_size)
|
||||
*ret_size = w->offset + w->size - offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ int mmap_cache_fd_get(
|
||||
uint64_t offset,
|
||||
size_t size,
|
||||
struct stat *st,
|
||||
void **ret);
|
||||
void **ret,
|
||||
size_t *ret_size);
|
||||
|
||||
int mmap_cache_fd_pin(
|
||||
MMapFileDescriptor *f,
|
||||
|
||||
@@ -14,6 +14,7 @@ int main(int argc, char *argv[]) {
|
||||
char px[] = "/tmp/testmmapXXXXXXX", py[] = "/tmp/testmmapYXXXXXX", pz[] = "/tmp/testmmapZXXXXXX";
|
||||
MMapCache *m;
|
||||
void *p, *q;
|
||||
size_t sp, sq;
|
||||
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
@@ -30,21 +31,26 @@ int main(int argc, char *argv[]) {
|
||||
ASSERT_OK(z = mkostemp_safe(pz));
|
||||
(void) unlink(pz);
|
||||
|
||||
ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 1, 2, NULL, &p));
|
||||
ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 1, 2, NULL, &p, &sp));
|
||||
ASSERT_GE(sp, 2U);
|
||||
|
||||
ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 2, 2, NULL, &q));
|
||||
ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 2, 2, NULL, &q, &sq));
|
||||
|
||||
ASSERT_PTR_EQ((uint8_t*) p + 1, (uint8_t*) q);
|
||||
ASSERT_EQ(sq, sp - 1);
|
||||
|
||||
ASSERT_OK(mmap_cache_fd_get(fx, 1, false, 3, 2, NULL, &q));
|
||||
ASSERT_OK(mmap_cache_fd_get(fx, 1, false, 3, 2, NULL, &q, &sq));
|
||||
|
||||
ASSERT_PTR_EQ((uint8_t*) p + 2, (uint8_t*) q);
|
||||
ASSERT_EQ(sq, sp - 2);
|
||||
|
||||
ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p));
|
||||
ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p, &sp));
|
||||
ASSERT_GE(sp, 2U);
|
||||
|
||||
ASSERT_OK(mmap_cache_fd_get(fx, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q));
|
||||
ASSERT_OK(mmap_cache_fd_get(fx, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q, &sq));
|
||||
|
||||
ASSERT_PTR_EQ((uint8_t*) p + 1, (uint8_t*) q);
|
||||
ASSERT_EQ(sq, sp - 1);
|
||||
|
||||
mmap_cache_fd_free(fx);
|
||||
mmap_cache_unref(m);
|
||||
|
||||
Reference in new issue
Block a user