-
Notifications
You must be signed in to change notification settings - Fork 704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Switch from preallocating all databases to lazy allocation, reducing overhead and improving scalability for large database counts. #1609
base: unstable
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some immediate comments.
src/aof.c
Outdated
@@ -2210,7 +2210,8 @@ int rewriteAppendOnlyFileRio(rio *aof) { | |||
|
|||
for (j = 0; j < server.dbnum; j++) { | |||
char selectcmd[] = "*2\r\n$6\r\nSELECT\r\n"; | |||
serverDb *db = server.db + j; | |||
if (server.db[j] == NULL || kvstoreSize(server.db[j]->keys) == 0) continue; | |||
serverDb *db = server.db[j]; | |||
if (kvstoreSize(db->keys) == 0) continue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can probably remove this check now right?
src/cluster_legacy.c
Outdated
@@ -5704,7 +5704,7 @@ int verifyClusterConfigWithData(void) { | |||
|
|||
/* Make sure we only have keys in DB0. */ | |||
for (j = 1; j < server.dbnum; j++) { | |||
if (kvstoreSize(server.db[j].keys)) return C_ERR; | |||
if (server.db[j] && kvstoreSize(server.db[j]->keys)) return C_ERR; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this condition will probably repeat many times. suggest we encapsulate in a function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
introduced new function, databaseEmpty
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## unstable #1609 +/- ##
============================================
+ Coverage 71.01% 71.05% +0.03%
============================================
Files 121 121
Lines 65169 65273 +104
============================================
+ Hits 46281 46377 +96
- Misses 18888 18896 +8
|
1bfa8b4
to
9f07a4f
Compare
reducing overhead and improving scalability for large database counts. Signed-off-by: xbasel <[email protected]>
Running valkey with 10 million databases:
empty dbs: Before:
After:
db 8 million:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, this looks pretty strait-forward.
The benchmark with 10M databases is great, but not a very common I think. :) The main motivation for this optimization IMO is in combination with #1319. For cluster mode with 16 empty databases, does it go from 10MB to 1MB?
src/server.c
Outdated
// /* Initialize temporary db on replica for use during diskless replication. */ | ||
// serverDb *initTempDb(int id) { | ||
// int slot_count_bits = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not finished?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should have been removed. createDatabase
is not used, including for temp databases. I'll remove.
src/server.c
Outdated
void initDatabase(int id) { | ||
if (server.db[id] == NULL) { | ||
server.db[id] = createDatabase(id); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In kvstore.c
there is lazy creation of hashtables. It is similar to lazy creation of databases. In kvstore, a function called createHashtableIfNeeded is used in many places. It lazy-creates it and returns it.
I think we can use a similar pattern here. The name with "if needed" is also more clear than "init".
void initDatabase(int id) { | |
if (server.db[id] == NULL) { | |
server.db[id] = createDatabase(id); | |
} | |
} | |
serverDb *createDatabaseIfNeeded(int id) { | |
if (server.db[id] == NULL) { | |
server.db[id] = createDatabase(id); | |
} | |
return server.db[id]; | |
} |
It can be used for example like this for the SELECT command:
c->db = createDatabaseIfNeeded(id);
src/server.c
Outdated
/* Return non-zero if the database is empty */ | ||
int databaseEmpty(int id) { | ||
return id < 0 || id >= server.dbnum || !server.db[id] || kvstoreSize(server.db[id]->keys) == 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include "is" to make the function name more clear, like databaseIsEmpty
. Without it, it may looks like the function empties the database. We have some other functions like emptyData
that does that.
It's not forbidded to use bool
anymore. We made a decision to allow it. Using int
for booleans is also fine though.
Even if a database has no keys, it can have clients waiting for keys to be created (blocked on BLPOP), watched keys, etc., so the db structure it is not completely empty. Isn't what we need just to check if the database has been created or not, i.e. just check server.db[id] != NULL
? In that case, we can call it databaseIsCreated
or databaseExists
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming is bad here. This function is used to check if a certain db has no keys. I've replaced with:
bool dbHasNoKeys(int dbid)
This has been created artificially (this change hasn't been merged into multi-database code, i changed the code to create 16k slots without cluster mode) before (preallocated) with (16 databases, 16k slots):
allocated-on-demand (16 databases, 16k slots), database 0 is always pre-allocated..
|
Signed-off-by: xbasel <[email protected]>
fixes #1597