Skip to content

Conversation

romange
Copy link
Collaborator

@romange romange commented Sep 11, 2025

We use adaptive precision, where we keep "millis" precision if we can, and switch to seconds precision if the deadline is too large.

This actually was before but now I reduced the cut-off to 4B ms, or 49 days. Also, the ttl in seconds is now limited to 4B sec, with larger values quietly rounded down to this limit.

@romange romange added this to the v1.35 milestone Sep 11, 2025
@romange romange force-pushed the Pr1 branch 4 times, most recently from 8e2daae to 15a484c Compare September 17, 2025 16:25
@romange romange marked this pull request as ready for review September 17, 2025 16:25
@romange
Copy link
Collaborator Author

romange commented Sep 17, 2025

the next step would be to start using expire_base_ and generations to represent the absolute times using ~49 days ExpirePeriod. The absolute time := expire_base_ + expire_period so we should refresh expire_base_ daily to maintain 48-49 days span.

@romange romange requested a review from dranikpg September 17, 2025 17:41
dranikpg
dranikpg previously approved these changes Sep 17, 2025
Copy link
Contributor

@dranikpg dranikpg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the next step would be to start using expire_base_ and generations to represent the absolute times using ~49 days ExpirePeriod. The absolute time := expire_base_ + expire_period so we should refresh expire_base_ daily to maintain 48-49 days span.

Not sure what the technical benefit of this would be. Not sure anyone would notice after 49 days 🤷🏻‍♂️ Who knows, it's not a long interval, especially for someone who has time sensitive data

Please see my comment around struct sizes

Comment on lines 1286 to 1288
VLOG(1) << "Performing flush";
error_code ec = Drakarys(flush_trans.get(), DbSlice::kDbAll);
if (ec) {
LOG(ERROR) << "Error flushing db " << ec.message();
}
Drakarys(flush_trans.get(), DbSlice::kDbAll);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this as well in #5821

Comment on lines +59 to 65
precision_ = 1; // seconds
if (ms < UINT64_MAX / 2) {
ms = (ms + 500) / 1000;
val_ = ms >= UINT32_MAX ? UINT32_MAX - 1 : ms;
} else {
val_ = UINT32_MAX - 1;
}
Copy link
Contributor

@dranikpg dranikpg Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand the if with int64_t::max / 2, why not just calculate the seconds value and see if it fits into int32_t 👀 Just check to divide first and then add the remainder > 0 (I assume the if is about this)

Copy link
Collaborator Author

@romange romange Sep 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

max64/2 is arbitrary, I could also check max64/1024. the goal is to prevent from (ms + 500) to overflow when we check if https://github.com/dragonflydb/dragonfly/pull/5797/files#diff-260e4d827ec66db63761ebe27e45792b6e2c8f9262f22d4a07e567c3fbfb5e40R61 fits uint32_t

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a little less intuitive

Comment on lines +47 to +49
uint32_t val_;
uint8_t gen_ : 2; // generation id.
uint8_t precision_ : 1; // 0 - ms, 1 - sec.
Copy link
Contributor

@dranikpg dranikpg Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you're optimizing with all those bitfields, but the struct is not packed either way 🙂
image

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know the memory usage in this PR does not go down. It's not the goal here. I want first to introduce all the supporting functionality to support 5 bytes expire offset and then eliminate the expire table completely by moving 5 byte expire value into PrimeValue. This will reduce the memory usage for TTL enabled use-cases but will increase it for use-cases that do not use TTLs. This is why I want to use 5 bytes for expire value so we could reduce the negative impact for these use-cases.

In order to support a 5-bytes expire offset, we must model the absolute time as base + period because we must update base from time to time, otherwise after 49 days of process being run you won't be able to represent a millisecond precision with the old base. And since updating the base needs to be done gradually (by traversing the whole table), we need to have multiple bases to support the transition state.

@dranikpg
Copy link
Contributor

Not sure if I have to start using the phrase "not sure" less 🤔

We use adaptive precision, where we keep "millis" precision if we can,
and switch to seconds precision if the deadline is too large.

This actually was before but now I reduced the cut-off to 4B ms,
or 49 days. Also, the ttl in seconds is now limited to 4B sec,
with larger values quietly rounded down to this limit.

Signed-off-by: Roman Gershman <[email protected]>
Comment on lines +610 to +611
uint8_t expire_allowed_ : 1;
uint8_t expire_base_index_ : 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you like this so much 😆

Comment on lines +59 to 65
precision_ = 1; // seconds
if (ms < UINT64_MAX / 2) {
ms = (ms + 500) / 1000;
val_ = ms >= UINT32_MAX ? UINT32_MAX - 1 : ms;
} else {
val_ = UINT32_MAX - 1;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a little less intuitive

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants