xaizek / vifm (License: GPLv2+) (since 2018-12-07)
Vifm is a file manager with curses interface, which provides Vi[m]-like environment for managing objects within file systems, extended with some useful ideas from mutt.
Commit da45e4e1e5b24931b0d2951a0d3791d0ff77448a

Optimize mixed small and large trie string allocs
When the requested size is larger than the minimal block size, the
buffer is full on the first use. So instead of resetting offset and
starting a new block on the next call just make the newly created block
penultimate to keep using the block allocated previously for smaller
allocations.
Author: xaizek
Author date (UTC): 2026-05-14 21:44
Committer name: xaizek
Committer date (UTC): 2026-05-15 12:48
Parent(s): 8ef02c3b33bf7bd9d753b401bd876ddfd9cc8b59
Signing key: 99DC5E4DB05F6BE2
Tree: 578cdf587efbcd30d28f849265d4747707e78a7f
File Lines added Lines deleted
src/utils/trie.c 21 2
tests/utils/trie.c 8 0
File src/utils/trie.c changed (mode: 100644) (index 968148e5a..e9310de44)
... ... alloc_string(trie_t *trie, const char str[], int len)
360 360 } }
361 361
362 362 trie->str_bufs = str_bufs; trie->str_bufs = str_bufs;
363 trie->str_bufs[trie->str_buf_count] = malloc(MAX(MIN_STR_BUF_SIZE, len));
364 if(trie->str_bufs[trie->str_buf_count] == NULL)
363
364 char *str_buf = malloc(MAX(MIN_STR_BUF_SIZE, len));
365 if(str_buf == NULL)
365 366 { {
366 367 return NULL; return NULL;
367 368 } }
368 369
369 370 ++trie->str_buf_count; ++trie->str_buf_count;
371
372 /* This is an optimization to avoid unnecessary fragmentation. When the
373 * requested size is larger than the minimal block size, the buffer is full
374 * on the first use. So instead of resetting offset and starting a new
375 * block on the next call just make the newly created block penultimate to
376 * keep using the block allocated previously for smaller allocations. */
377 if(len > MIN_STR_BUF_SIZE && trie->str_buf_count > 1 &&
378 trie->last_offset < MIN_STR_BUF_SIZE)
379 {
380 trie->str_bufs[trie->str_buf_count - 1] =
381 trie->str_bufs[trie->str_buf_count - 2];
382 trie->str_bufs[trie->str_buf_count - 2] = str_buf;
383
384 memcpy(str_buf, str, len);
385 return str_buf;
386 }
387
388 trie->str_bufs[trie->str_buf_count - 1] = str_buf;
370 389 trie->last_offset = 0; trie->last_offset = 0;
371 390 } }
372 391
File tests/utils/trie.c changed (mode: 100644) (index 9ee30fa04..7f72cc61e)
... ... TEST(huge_keys)
194 194 assert_success(trie_put(trie, a_key)); assert_success(trie_put(trie, a_key));
195 195 assert_success(trie_get(trie, a_key, &data)); assert_success(trie_get(trie, a_key, &data));
196 196
197 /* Use a small key. */
198 assert_success(trie_put(trie, "small"));
199 assert_success(trie_get(trie, "small", &data));
200
197 201 /* Another large key works. */ /* Another large key works. */
198 202 assert_success(trie_put(trie, b_key)); assert_success(trie_put(trie, b_key));
199 203 assert_success(trie_get(trie, b_key, &data)); assert_success(trie_get(trie, b_key, &data));
200 204
205 /* Small one again. */
206 assert_success(trie_put(trie, "short"));
207 assert_success(trie_get(trie, "short", &data));
208
201 209 /* The first one is still there. */ /* The first one is still there. */
202 210 assert_success(trie_get(trie, a_key, &data)); assert_success(trie_get(trie, a_key, &data));
203 211
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vifm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vifm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master