@@ -52,6 +52,11 @@ typedef struct GroupMerge_params {
5252 int n_objs_to_evict ;
5353 int pos_in_metric_list ;
5454
55+ int64_t n_obj_inserted ;
56+ int64_t n_byte_inserted ;
57+ int64_t n_obj_retained ;
58+ int64_t n_byte_retained ;
59+
5560 int64_t n_obj_rewritten ;
5661 int64_t n_byte_rewritten ;
5762} GroupMerge_params_t ;
@@ -107,7 +112,9 @@ cache_t *GroupMerge_init(const common_cache_params_t ccache_params,
107112 memset (params , 0 , sizeof (GroupMerge_params_t ));
108113 cache -> eviction_params = params ;
109114
110- params -> group_size = 20 * 1024 * 1024 ; // 20 MiB
115+ // default group_size = cache_size / 1000
116+ params -> group_size = (int64_t )ccache_params .cache_size / 1000 ;
117+ if (params -> group_size < 1 ) params -> group_size = 1 ;
111118 params -> n_exam_groups = 4 ;
112119 params -> retain_policy = RETAIN_POLICY_RECENCY ;
113120 params -> next_to_exam = NULL ;
@@ -125,6 +132,20 @@ cache_t *GroupMerge_init(const common_cache_params_t ccache_params,
125132
126133 assert (params -> group_size > 0 && params -> n_exam_groups >= 2 );
127134
135+ // clamp group_size so it cannot exceed a fraction of the cache; otherwise
136+ // each scan covers ~the whole cache while retaining everything, forcing
137+ // batched evictions of 1, which is O(N^2) per pass.
138+ int64_t max_group_size = (int64_t )ccache_params .cache_size /
139+ (int64_t )(params -> n_exam_groups * 2 );
140+ if (max_group_size < 1 ) max_group_size = 1 ;
141+ if (params -> group_size > max_group_size ) {
142+ WARN ("GroupMerge: group-size %ld too large for cache size %lu; "
143+ "clamping to %ld (cache_size / (2*E))\n" ,
144+ (long )params -> group_size , (unsigned long )ccache_params .cache_size ,
145+ (long )max_group_size );
146+ params -> group_size = max_group_size ;
147+ }
148+
128149 snprintf (cache -> cache_name , CACHE_NAME_ARRAY_LEN ,
129150 "GroupMerge_gs%ld_E%d_%s" , (long )params -> group_size ,
130151 params -> n_exam_groups ,
@@ -135,6 +156,15 @@ cache_t *GroupMerge_init(const common_cache_params_t ccache_params,
135156
136157static void GroupMerge_free (cache_t * cache ) {
137158 GroupMerge_params_t * params = (GroupMerge_params_t * )cache -> eviction_params ;
159+ double retain_ratio = params -> n_byte_inserted > 0
160+ ? (double )params -> n_byte_retained / (double )params -> n_byte_inserted
161+ : 0.0 ;
162+ INFO (
163+ "%s: inserted %ld obj / %ld bytes, retained %ld obj / %ld bytes "
164+ "(retained/inserted byte ratio = %.4f)\n" ,
165+ cache -> cache_name , (long )params -> n_obj_inserted ,
166+ (long )params -> n_byte_inserted , (long )params -> n_obj_retained ,
167+ (long )params -> n_byte_retained , retain_ratio );
138168 free (params -> metric_list );
139169 my_free (sizeof (GroupMerge_params_t ), params );
140170 cache_struct_free (cache );
@@ -170,6 +200,9 @@ static cache_obj_t *GroupMerge_insert(cache_t *cache, const request_t *req) {
170200 cache_obj -> GroupMerge .freq = 0 ;
171201 cache_obj -> GroupMerge .last_access_vtime = (int32_t )cache -> n_req ;
172202
203+ params -> n_obj_inserted += 1 ;
204+ params -> n_byte_inserted += cache_obj -> obj_size ;
205+
173206 return cache_obj ;
174207}
175208
@@ -195,6 +228,8 @@ static void GroupMerge_evict(cache_t *cache, const request_t *req) {
195228 for (int i = params -> n_objs_to_evict ; i < params -> n_objs_in_batch ; i ++ ) {
196229 cache_obj_t * retained = params -> metric_list [i ].cache_obj ;
197230 retained -> GroupMerge .freq = (retained -> GroupMerge .freq + 1 ) / 2 ;
231+ params -> n_obj_retained += 1 ;
232+ params -> n_byte_retained += retained -> obj_size ;
198233 }
199234 params -> pos_in_metric_list = INT32_MAX ;
200235 }
@@ -291,6 +326,8 @@ static void GroupMerge_evict(cache_t *cache, const request_t *req) {
291326 for (int i = params -> n_objs_to_evict ; i < params -> n_objs_in_batch ; i ++ ) {
292327 cache_obj_t * retained = params -> metric_list [i ].cache_obj ;
293328 retained -> GroupMerge .freq = (retained -> GroupMerge .freq + 1 ) / 2 ;
329+ params -> n_obj_retained += 1 ;
330+ params -> n_byte_retained += retained -> obj_size ;
294331 }
295332 params -> pos_in_metric_list = INT32_MAX ;
296333 }
0 commit comments