Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
tests/cache.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011-2012 johannes hanika.
4 Copyright (C) 2012 Richard Wonka.
5 Copyright (C) 2012, 2014, 2016 Tobias Ellinghaus.
6 Copyright (C) 2016 Roman Lebedev.
7 Copyright (C) 2020 Pascal Obry.
8 Copyright (C) 2022 Martin Bařinka.
9 Copyright (C) 2024 Alynx Zhou.
10 Copyright (C) 2026 Aurélien PIERRE.
11
12 darktable is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
16
17 darktable is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with darktable. If not, see <http://www.gnu.org/licenses/>.
24*/
25
26
27#define DT_UNIT_TEST
28// define dt alloc, so we don't need to include the rest of dt:
29#define MAX(a, b) ((a) > (b) ? (a) : (b))
30
31// unit test for the concurrent hopscotch hashmap and the LRU cache built on top of it.
32#include "common/cache.h"
33#include "common/cache.c"
34
35#include <assert.h>
36#include <stdio.h>
37#include <stdlib.h>
38#ifdef _OPENMP
39#include <omp.h>
40#endif
41
42int32_t alloc_dummy(void *data, const uint32_t key, int32_t *cost, void **buf)
43{
44 *cost = 1; // also the default
45 *buf = (void *)(long int)key;
46 // request write lock for our buffer?
47 return 0;
48}
49
50int main(int argc, char *arg[])
51{
52 dt_cache_t cache;
53 // dt_cache_init(&cache, 110000, 16, 64, 100000);
54 // really hammer it, make quota insanely low:
55 dt_cache_init(&cache, 110000, 16, 64, 100);
57 __OMP_PARALLEL_FOR__(schedule(guided) shared(cache, stderr) num_threads(16))
58 for(int k = 0; k < 100000; k++)
59 {
60 void *data = (void *)(long int)k;
61 const int size = 0; // dt_cache_size(&cache);
62 const int con1 = dt_cache_contains(&cache, k);
63 const int val1 = (int)(long int)dt_cache_read_get(&cache, k);
64 const int val2 = (int)(long int)dt_cache_read_get(&cache, k);
65 // fprintf(stderr, "\rinserted number %d, size %d, value %d - %d, contains %d - %d", k, size, val1, val2,
66 // con1, con2);
67 const int con2 = dt_cache_contains(&cache, k);
68 assert(con1 == 0);
69 assert(con2 == 1);
70 assert(val2 == k);
71 dt_cache_read_release(&cache, k);
72 dt_cache_read_release(&cache, k);
73 }
74 dt_cache_print_locked(&cache);
75 // fprintf(stderr, "\n");
76 fprintf(stderr, "[passed] inserting 100000 entries concurrently\n");
77
78 const int size = dt_cache_size(&cache);
79 const int lru_cnt = lru_check_consistency(&cache);
80 const int lru_cnt_r = lru_check_consistency_reverse(&cache);
81 // fprintf(stderr, "lru list contains %d|%d/%d entries\n", lru_cnt, lru_cnt_r, size);
82 assert(size == lru_cnt);
83 assert(lru_cnt_r == lru_cnt);
84 fprintf(stderr, "[passed] cache lru consistency after removals, have %d entries left.\n", size);
85
86 dt_cache_cleanup(&cache);
87
88
89
90 {
91 // now a harder case: a cache with only one entry and a lot of threads fighting over it:
92 dt_cache_t cache2;
93 // really hammer it, make quota insanely low:
94 // capacity 1 num threads 1 cache line size 64 ignored, quota 2 (80% => 1)
95 dt_cache_init(&cache2, 1, 1, 64, 2);
97 __OMP_PARALLEL_FOR__(schedule(guided) shared(cache2, stderr) num_threads(16))
98 for(int k = 0; k < 100000; k++)
99 {
100 void *data = (void *)(long int)k;
101 const int size = 0; // dt_cache_size(&cache);
102 const int con1 = dt_cache_contains(&cache2, k);
103 const int val1 = (int)(long int)dt_cache_read_get(&cache2, k);
104 const int val2 = (int)(long int)dt_cache_read_get(&cache2, k);
105 // fprintf(stderr, "\rinserted number %d, size %d, value %d - %d, contains %d - %d", k, size, val1,
106 // val2, con1, con2);
107 const int con2 = dt_cache_contains(&cache2, k);
108 assert(con1 == 0);
109 assert(con2 == 1);
110 assert(val2 == k);
111 dt_cache_read_release(&cache2, k);
112 dt_cache_read_release(&cache2, k);
113 }
114 dt_cache_print_locked(&cache2);
115 // fprintf(stderr, "\n");
116 fprintf(stderr, "[passed] inserting 100000 entries concurrently\n");
117
118 const int size = dt_cache_size(&cache2);
119 const int lru_cnt = lru_check_consistency(&cache2);
120 const int lru_cnt_r = lru_check_consistency_reverse(&cache2);
121 // fprintf(stderr, "lru list contains %d|%d/%d entries\n", lru_cnt, lru_cnt_r, size);
122 assert(size == lru_cnt);
123 assert(lru_cnt_r == lru_cnt);
124 fprintf(stderr, "[passed] cache lru consistency after removals, have %d entries left.\n", size);
125 dt_cache_cleanup(&cache2);
126 }
127
128 exit(0);
129}
130// clang-format off
131// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
132// vim: shiftwidth=2 expandtab tabstop=2 cindent
133// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
134// clang-format on
135
static void dt_cache_set_allocate_callback(dt_cache_t *cache, dt_cache_allocate_t allocate_cb, void *allocate_data)
char * key
#define __OMP_PARALLEL_FOR__(...)
Definition darktable.h:258
float *const restrict const size_t k
size_t size
Definition mipmap_cache.c:3
int main()
Definition prova.c:47
int32_t dt_cache_contains(dt_cache_t *cache, const uint32_t key)
void dt_cache_init(dt_cache_t *cache, size_t entry_size, size_t cost_quota)
void dt_cache_cleanup(dt_cache_t *cache)
int32_t alloc_dummy(void *data, const uint32_t key, int32_t *cost, void **buf)
Definition tests/cache.c:42