@cryptotaxi247 / netdata-1 / commits / 1601f30e4

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 {