Use datafile block pos (#21098)
* Keep the datafile block for extents instead of position. Extents are always aligned Reduce internal structures memory footprint * Replace block offset calculations with BLOCK_TO_OFFSET and OFFSET_TO_BLOCK macros * Cleanup * Fix compilation with NETDATA_INTERNAL_CHECKS
Stelios Fragkakis committed
Oct 6, 2025 at 19:21 UTC
1601f30e4ebfa2f76f154eadcecfb1898fd78399
7 files changed
+72
-72
src/database/engine/cache.c
+3
-3
@@ -2484,15 +2484,15 @@ void pgc_open_cache_to_journal_v2(
2484
// update the extents JudyL
2485
2486
size_t current_extent_index_id;
2487
- Pvoid_t *PValue = JudyLIns(&JudyL_extents_pos, xio->pos, PJE0);
2487
+ Pvoid_t *PValue = JudyLIns(&JudyL_extents_pos, xio->block, PJE0);
2488
if(!PValue || PValue == PJERR)
2489
fatal("CACHE: JudyLIns(JudyL_extents_pos, %" PRIu64 ") failed, JudyL_extents_pos = %p, result = %p",
2490
- xio->pos, JudyL_extents_pos, PValue);
2490
+ BLOCK_TO_OFFSET(xio->block), JudyL_extents_pos, PValue);
2491
2492
struct jv2_extents_info *ei;
2493
if(!*PValue) {
2494
ei = aral_mallocz(ar_ei); // callocz(1, sizeof(struct jv2_extents_info));
2495
- ei->pos = xio->pos;
2495
+ ei->block = xio->block;
2496
ei->bytes = xio->bytes;
2497
ei->number_of_pages = 1;
2498
ei->index = master_extent_index_id++;
src/database/engine/journalfile.c
+10
-7
@@ -709,9 +709,14 @@ static void journalfile_restore_extent_metadata(struct rrdengine_instance *ctx,
709
mrg_metric_expand_retention(main_mrg, metric, vd.start_time_s, vd.end_time_s, vd.update_every_s);
710
711
pgc_open_add_hot_page(
712
- (Word_t)ctx, metric_id, vd.start_time_s, vd.end_time_s, vd.update_every_s,
713
- journalfile->datafile,
714
- jf_metric_data->extent_offset, jf_metric_data->extent_size, jf_metric_data->descr[i].page_length);
712
+ (Word_t)ctx,
713
+ metric_id,
714
+ vd.start_time_s,
715
+ vd.end_time_s,
716
+ vd.update_every_s,
717
+ journalfile->datafile,
718
+ jf_metric_data->extent_offset,
719
+ jf_metric_data->extent_size);
720
721
extent_first_time_s = MIN(extent_first_time_s, vd.start_time_s);
722
@@ -1179,7 +1184,7 @@ void *journalfile_v2_write_extent_list(Pvoid_t JudyL_extents_pos, void *data)
1184
ext_info = *PValue;
1185
size_t index = ext_info->index;
1186
j2_extent_base[index].file_index = 0;
1182
- j2_extent_base[index].datafile_offset = ext_info->pos;
1187
+ j2_extent_base[index].datafile_offset = BLOCK_TO_OFFSET(ext_info->block);
1188
j2_extent_base[index].datafile_size = ext_info->bytes;
1189
j2_extent_base[index].pages = ext_info->number_of_pages;
1190
count++;
@@ -1246,14 +1251,12 @@ void *journalfile_v2_write_data_page(struct journal_v2_header *j2_header, void *
1251
if (journalfile_verify_space(j2_header, data, sizeof(*data_page)))
1252
return NULL;
1253
1249
- struct extent_io_data *ei = page_info->custom_data;
1250
-
1254
data_page->delta_start_s = (uint32_t) (page_info->start_time_s - (time_t) (j2_header->start_time_ut) / USEC_PER_SEC);
1255
data_page->delta_end_s = (uint32_t) (page_info->end_time_s - (time_t) (j2_header->start_time_ut) / USEC_PER_SEC);
1256
data_page->extent_index = page_info->extent_index;
1257
1258
data_page->update_every_s = page_info->update_every_s;
1256
- data_page->page_length = (uint16_t) (ei ? ei->page_length : page_info->page_length);
1259
+ data_page->page_length = 0;
1260
data_page->type = 0;
1261
1262
return ++data_page;
src/database/engine/pagecache.c
+18
-20
@@ -296,10 +296,8 @@ static ALWAYS_INLINE_HOT size_t get_page_list_from_pgc(PGC *cache, METRIC *metri
296
if(datafile_acquire(datafile, DATAFILE_ACQUIRE_PAGE_DETAILS)) { // for pd
297
struct extent_io_data *xio = (struct extent_io_data *) pgc_page_custom_data(cache, page);
298
pd->datafile.ptr = pgc_page_data(page);
299
- pd->datafile.file = xio->file;
300
- pd->datafile.extent.pos = xio->pos;
301
- pd->datafile.extent.bytes = xio->bytes;
302
- pd->datafile.fileno = pd->datafile.ptr->fileno;
299
+ pd->datafile.block = xio->block;
300
+ pd->datafile.bytes = xio->bytes;
301
pd->status |= PDC_PAGE_DATAFILE_ACQUIRED | PDC_PAGE_DISK_PENDING;
302
}
303
else {
@@ -464,9 +462,8 @@ static ALWAYS_INLINE_HOT size_t list_has_time_gaps(
462
463
internal_fatal(pd->status & PDC_PAGE_SKIP, "page is disk pending and skipped");
464
internal_fatal(!pd->datafile.ptr, "datafile is NULL");
467
- internal_fatal(!pd->datafile.extent.bytes, "datafile.extent.bytes zero");
468
- internal_fatal(!pd->datafile.extent.pos, "datafile.extent.pos is zero");
469
- internal_fatal(!pd->datafile.fileno, "datafile.fileno is zero");
465
+ internal_fatal(!pd->datafile.bytes, "datafile.bytes zero");
466
+ internal_fatal(!pd->datafile.block, "datafile.block is zero");
467
}
468
}
469
else {
@@ -587,17 +584,14 @@ static NOT_INLINE_HOT size_t get_page_list_from_journal_v2(struct rrdengine_inst
584
}
585
586
uint32_t page_update_every_s = page_entry_in_journal->update_every_s;
590
- size_t page_length = page_entry_in_journal->page_length;
587
588
if (datafile_acquire(datafile, DATAFILE_ACQUIRE_OPEN_CACHE)) {
589
//for open cache item
590
// add this page to open cache
591
bool added = false;
592
struct extent_io_data ei = {0};
597
- ei.pos = extent_list[page_entry_in_journal->extent_index].datafile_offset;
593
+ ei.block = OFFSET_TO_BLOCK(extent_list[page_entry_in_journal->extent_index].datafile_offset);
594
ei.bytes = extent_list[page_entry_in_journal->extent_index].datafile_size;
599
- ei.page_length = page_length;
600
- ei.file = datafile->file;
595
ei.fileno = datafile->fileno;
596
597
PGC_ENTRY e = {0};
@@ -657,10 +651,8 @@ void add_page_details_from_journal_v2(PGC_PAGE *page, void *JudyL_pptr) {
651
struct page_details *pd = page_details_get();
652
*PValue = pd;
653
660
- pd->datafile.extent.pos = ei->pos;
661
- pd->datafile.extent.bytes = ei->bytes;
662
- pd->datafile.file = ei->file;
663
- pd->datafile.fileno = ei->fileno;
654
+ pd->datafile.block = ei->block;
655
+ pd->datafile.bytes = ei->bytes;
656
pd->first_time_s = pgc_page_start_time_s(page);
657
pd->last_time_s = pgc_page_end_time_s(page);
658
pd->datafile.ptr = datafile;
@@ -1043,18 +1035,24 @@ struct pgc_page *pg_cache_lookup_next(
1035
return page;
1036
}
1037
1046
-void pgc_open_add_hot_page(Word_t section, Word_t metric_id, time_t start_time_s, time_t end_time_s, uint32_t update_every_s,
1047
- struct rrdengine_datafile *datafile, uint64_t extent_offset, unsigned extent_size, uint32_t page_length) {
1038
+void pgc_open_add_hot_page(
1039
+ Word_t section,
1040
+ Word_t metric_id,
1041
+ time_t start_time_s,
1042
+ time_t end_time_s,
1043
+ uint32_t update_every_s,
1044
+ struct rrdengine_datafile *datafile,
1045
+ uint64_t extent_offset,
1046
+ unsigned extent_size)
1047
+{
1048
1049
if(!datafile_acquire(datafile, DATAFILE_ACQUIRE_OPEN_CACHE)) // for open cache item
1050
fatal("DBENGINE: cannot acquire datafile to put page in open cache");
1051
1052
struct extent_io_data ext_io_data = {
1053
- .file = datafile->file,
1053
.fileno = datafile->fileno,
1055
- .pos = extent_offset,
1054
+ .block = OFFSET_TO_BLOCK(extent_offset),
1055
.bytes = extent_size,
1057
- .page_length = page_length
1056
};
1057
1058
PGC_ENTRY page_entry = {
src/database/engine/pagecache.h
+9
-1
@@ -46,6 +46,14 @@ void pg_cache_preload(struct rrdeng_query_handle *handle);
46
struct pgc_page *pg_cache_lookup_next(struct rrdengine_instance *ctx, struct page_details_control *pdc, time_t now_s, uint32_t last_update_every_s, size_t *entries);
47
void pgc_and_mrg_initialize(void);
48
49
-void pgc_open_add_hot_page(Word_t section, Word_t metric_id, time_t start_time_s, time_t end_time_s, uint32_t update_every_s, struct rrdengine_datafile *datafile, uint64_t extent_offset, unsigned extent_size, uint32_t page_length);
49
+void pgc_open_add_hot_page(
50
+ Word_t section,
51
+ Word_t metric_id,
52
+ time_t start_time_s,
53
+ time_t end_time_s,
54
+ uint32_t update_every_s,
55
+ struct rrdengine_datafile *datafile,
56
+ uint64_t extent_offset,
57
+ unsigned extent_size);
58
59
#endif /* NETDATA_PAGECACHE_H */
src/database/engine/pdc.c
+15
-22
@@ -4,10 +4,8 @@
4
#include "dbengine-compression.h"
5
6
struct extent_page_details_list {
7
- uv_file file;
8
- uint64_t extent_offset;
7
+ uint32_t extent_block;
8
uint32_t extent_size;
10
- unsigned number_of_pages_in_JudyL;
9
Pvoid_t page_details_by_metric_id_JudyL;
10
struct page_details_control *pdc;
11
struct rrdengine_datafile *datafile;
@@ -497,7 +495,7 @@ static ALWAYS_INLINE struct rrdeng_cmd *epdl_get_cmd(void *epdl_ptr) {
495
static ALWAYS_INLINE EPDL_EXTENT *epdl_find_extent_base(EPDL *epdl) {
496
EPDL_EXTENT *e = NULL;
497
rw_spinlock_read_lock(&epdl->datafile->extent_epdl.spinlock);
500
- Pvoid_t *PValue = JudyLGet(epdl->datafile->extent_epdl.epdl_per_extent, epdl->extent_offset, PJE0);
498
+ Pvoid_t *PValue = JudyLGet(epdl->datafile->extent_epdl.epdl_per_extent, epdl->extent_block, PJE0);
499
internal_fatal(PValue == PJERR, "DBENGINE: corrupted pending extent judy");
500
if(PValue)
501
e = *PValue;
@@ -508,7 +506,7 @@ static ALWAYS_INLINE EPDL_EXTENT *epdl_find_extent_base(EPDL *epdl) {
506
e = epdl_extent_get();
507
508
rw_spinlock_write_lock(&epdl->datafile->extent_epdl.spinlock);
511
- PValue = JudyLIns(&epdl->datafile->extent_epdl.epdl_per_extent, epdl->extent_offset, PJE0);
509
+ PValue = JudyLIns(&epdl->datafile->extent_epdl.epdl_per_extent, epdl->extent_block, PJE0);
510
internal_fatal(!PValue || PValue == PJERR, "DBENGINE: corrupted pending extent judy");
511
if(!*PValue) {
512
*PValue = e;
@@ -599,30 +597,26 @@ ALWAYS_INLINE_HOT void pdc_to_epdl_router(struct rrdengine_instance *ctx, PDC *p
597
internal_fatal(pd->page,
598
"DBENGINE: page details has a page linked to it, but it is marked for loading");
599
602
- PValue1 = PDCJudyLIns(&JudyL_datafile_list, pd->datafile.fileno, PJE0);
600
+ PValue1 = PDCJudyLIns(&JudyL_datafile_list, pd->datafile.ptr->fileno, PJE0);
601
if (PValue1 && !*PValue1) {
602
*PValue1 = deol = deol_get();
603
deol->extent_pd_list_by_extent_offset_JudyL = NULL;
606
- deol->fileno = pd->datafile.fileno;
604
+ deol->fileno = pd->datafile.ptr->fileno;
605
}
606
else
607
deol = *PValue1;
608
611
- PValue2 = PDCJudyLIns(&deol->extent_pd_list_by_extent_offset_JudyL, pd->datafile.extent.pos, PJE0);
609
+ PValue2 = PDCJudyLIns(&deol->extent_pd_list_by_extent_offset_JudyL, pd->datafile.block, PJE0);
610
if (PValue2 && !*PValue2) {
611
*PValue2 = epdl = epdl_get();
612
epdl->page_details_by_metric_id_JudyL = NULL;
615
- epdl->number_of_pages_in_JudyL = 0;
616
- epdl->file = pd->datafile.file;
617
- epdl->extent_offset = pd->datafile.extent.pos;
618
- epdl->extent_size = pd->datafile.extent.bytes;
613
+ epdl->extent_block = pd->datafile.block;
614
+ epdl->extent_size = pd->datafile.bytes;
615
epdl->datafile = pd->datafile.ptr;
616
}
617
else
618
epdl = *PValue2;
619
624
- epdl->number_of_pages_in_JudyL++;
625
-
620
Pvoid_t *pd_by_first_time_s_judyL = PDCJudyLIns(&epdl->page_details_by_metric_id_JudyL, pd->metric_id, PJE0);
621
Pvoid_t *pd_pptr = PDCJudyLIns(pd_by_first_time_s_judyL, pd->first_time_s, PJE0);
622
*pd_pptr = pd;
@@ -1022,7 +1016,7 @@ static void epdl_extent_loading_error_log(struct rrdengine_instance *ctx, EPDL *
1016
"%s from %ld (%s) to %ld (%s) %s%s: "
1017
"%s",
1018
epdl->datafile->fileno, ctx->config.tier,
1025
- epdl->extent_offset, epdl->extent_size,
1019
+ BLOCK_TO_OFFSET(epdl->extent_block), epdl->extent_size,
1020
used_epdl ? "to extract page (PD)" : used_descr ? "expected page (DESCR)" : "part of a query (PDC)",
1021
start_time_s, start_time_str, end_time_s, end_time_str,
1022
used_epdl || used_descr ? " of metric " : "",
@@ -1277,7 +1271,7 @@ static bool epdl_populate_pages_from_extent_data(
1271
return true;
1272
}
1273
1280
-static inline void *datafile_extent_read(struct rrdengine_instance *ctx, uv_file file, uint64_t pos, unsigned size_bytes)
1274
+static inline void *datafile_extent_read(struct rrdengine_instance *ctx, uv_file file, uint32_t block, unsigned size_bytes)
1275
{
1276
void *buffer = NULL;
1277
uv_fs_t request;
@@ -1286,7 +1280,7 @@ static inline void *datafile_extent_read(struct rrdengine_instance *ctx, uv_file
1280
(void)posix_memalignz(&buffer, RRDFILE_ALIGNMENT, real_io_size);
1281
1282
uv_buf_t iov = uv_buf_init(buffer, real_io_size);
1289
- int ret = uv_fs_read(NULL, &request, file, &iov, 1, (int64_t)pos, NULL);
1283
+ int ret = uv_fs_read(NULL, &request, file, &iov, 1, (int64_t) BLOCK_TO_OFFSET(block), NULL);
1284
if (unlikely(-1 == ret)) {
1285
ctx_io_error(ctx);
1286
posix_memalign_freez(buffer);
@@ -1314,9 +1308,8 @@ NOT_INLINE_HOT void epdl_find_extent_and_populate_pages(struct rrdengine_instanc
1308
bool should_stop = __atomic_load_n(&epdl->pdc->workers_should_stop, __ATOMIC_RELAXED);
1309
for(EPDL *ep = epdl->query.next; ep ;ep = ep->query.next) {
1310
internal_fatal(ep->datafile != epdl->datafile, "DBENGINE: datafiles do not match");
1317
- internal_fatal(ep->extent_offset != epdl->extent_offset, "DBENGINE: extent offsets do not match");
1311
+ internal_fatal(ep->extent_block != epdl->extent_block, "DBENGINE: extent blocks do not match");
1312
internal_fatal(ep->extent_size != epdl->extent_size, "DBENGINE: extent sizes do not match");
1319
- internal_fatal(ep->file != epdl->file, "DBENGINE: files do not match");
1313
1314
if(!__atomic_load_n(&ep->pdc->workers_should_stop, __ATOMIC_RELAXED)) {
1315
should_stop = false;
@@ -1335,7 +1328,7 @@ NOT_INLINE_HOT void epdl_find_extent_and_populate_pages(struct rrdengine_instanc
1328
void *extent_compressed_data = NULL;
1329
PGC_PAGE *extent_cache_page = pgc_page_get_and_acquire(
1330
extent_cache, (Word_t)ctx,
1338
- (Word_t)epdl->datafile->fileno, (time_t)epdl->extent_offset,
1331
+ (Word_t)epdl->datafile->fileno, (time_t)epdl->extent_block,
1332
PGC_SEARCH_EXACT);
1333
1334
if(extent_cache_page) {
@@ -1351,7 +1344,7 @@ NOT_INLINE_HOT void epdl_find_extent_and_populate_pages(struct rrdengine_instanc
1344
if(worker)
1345
worker_is_busy(UV_EVENT_DBENGINE_EXTENT_MMAP);
1346
1354
- void *extent_data = datafile_extent_read(ctx, epdl->file, epdl->extent_offset, epdl->extent_size);
1347
+ void *extent_data = datafile_extent_read(ctx, epdl->datafile->file, epdl->extent_block, epdl->extent_size);
1348
if(extent_data != NULL) {
1349
1350
void *tmp = dbengine_extent_alloc(epdl->extent_size);
@@ -1367,7 +1360,7 @@ NOT_INLINE_HOT void epdl_find_extent_and_populate_pages(struct rrdengine_instanc
1360
.hot = false,
1361
.section = (Word_t) ctx,
1362
.metric_id = (Word_t) epdl->datafile->fileno,
1370
- .start_time_s = (time_t) epdl->extent_offset,
1363
+ .start_time_s = (time_t) epdl->extent_block,
1364
.size = epdl->extent_size,
1365
.end_time_s = 0,
1366
.update_every_s = 0,
src/database/engine/rrdengine.c
+8
-6
@@ -697,12 +697,14 @@ extent_flush_to_open(struct rrdengine_instance *ctx, struct extent_io_descriptor
697
698
if (likely(still_running && !have_error))
699
pgc_open_add_hot_page(
700
- (Word_t)ctx, descr->metric_id,
701
- (time_t) (descr->start_time_ut / USEC_PER_SEC),
702
- (time_t) (descr->end_time_ut / USEC_PER_SEC),
703
- descr->update_every_s,
704
- datafile,
705
- xt_io_descr->pos, xt_io_descr->bytes, descr->page_length);
700
+ (Word_t)ctx,
701
+ descr->metric_id,
702
+ (time_t)(descr->start_time_ut / USEC_PER_SEC),
703
+ (time_t)(descr->end_time_ut / USEC_PER_SEC),
704
+ descr->update_every_s,
705
+ datafile,
706
+ xt_io_descr->pos,
707
+ xt_io_descr->bytes);
708
709
page_descriptor_release(descr);
710
}
src/database/engine/rrdengine.h
+9
-13
@@ -24,6 +24,9 @@
24
25
extern unsigned rrdeng_pages_per_extent;
26
27
+#define BLOCK_TO_OFFSET(block) ((uint64_t)(block) << 12)
28
+#define OFFSET_TO_BLOCK(ofs) ((uint64_t)(ofs) >> 12)
29
+
30
#define UNLINK_FILE(ctx, path, ret_var) \
31
do { \
32
uv_fs_t _req; \
@@ -136,13 +139,8 @@ PDC *pdc_get(void);
139
struct page_details {
140
struct {
141
struct rrdengine_datafile *ptr;
139
- uv_file file;
140
- unsigned fileno;
141
-
142
- struct {
143
- uint64_t pos;
144
- uint32_t bytes;
145
- } extent;
142
+ uint32_t block; // the block in the datafile. Offset in the datafile is block * RRDENG_BLOCK_SIZE
143
+ uint32_t bytes;
144
} datafile;
145
146
struct pgc_page *page;
@@ -165,10 +163,10 @@ struct page_details *page_details_get(void);
163
#define pdc_page_status_clear(pd, flag) __atomic_and_fetch(&((od)->status), ~(flag), __ATOMIC_RELEASE)
164
165
struct jv2_extents_info {
168
- size_t index;
169
- uint64_t pos;
166
+ uint32_t index;
167
+ uint32_t block;
168
unsigned bytes;
171
- size_t number_of_pages;
169
+ uint32_t number_of_pages;
170
};
171
172
struct jv2_metrics_info {
@@ -301,10 +299,8 @@ enum rrdeng_opcode {
299
300
struct extent_io_data {
301
unsigned fileno;
304
- uv_file file;
305
- uint64_t pos;
302
+ uint32_t block;
303
unsigned bytes;
307
- uint16_t page_length;
304
};
305
306
struct extent_io_descriptor {