22#define JEMALLOC_INTERNAL_HPA_UTILS_H
33
44#include "jemalloc/internal/hpa.h"
5+ #include "jemalloc/internal/extent.h"
56
67#define HPA_MIN_VAR_VEC_SIZE 8
8+ /*
9+ * This is used for jemalloc internal tuning and may change in the future based
10+ * on production traffic.
11+ *
12+ * This value protects two things:
13+ * 1. Stack size
14+ * 2. Number of huge pages that are being purged in a batch as we do not
15+ * allow allocations while making madvise syscall.
16+ */
17+ #define HPA_PURGE_BATCH_MAX 16
18+
719#ifdef JEMALLOC_HAVE_PROCESS_MADVISE
820typedef struct iovec hpa_io_vector_t ;
921#else
@@ -13,27 +25,35 @@ typedef struct {
1325} hpa_io_vector_t ;
1426#endif
1527
28+ static inline size_t
29+ hpa_process_madvise_max_iovec_len (void ) {
30+ assert (
31+ opt_process_madvise_max_batch <= PROCESS_MADVISE_MAX_BATCH_LIMIT );
32+ return opt_process_madvise_max_batch == 0
33+ ? HPA_MIN_VAR_VEC_SIZE
34+ : opt_process_madvise_max_batch ;
35+ }
36+
1637/* Actually invoke hooks. If we fail vectorized, use single purges */
1738static void
1839hpa_try_vectorized_purge (
19- hpa_shard_t * shard , hpa_io_vector_t * vec , size_t vlen , size_t nbytes ) {
40+ hpa_hooks_t * hooks , hpa_io_vector_t * vec , size_t vlen , size_t nbytes ) {
2041 bool success = opt_process_madvise_max_batch > 0
21- && !shard -> central -> hooks . vectorized_purge (vec , vlen , nbytes );
42+ && !hooks -> vectorized_purge (vec , vlen , nbytes );
2243 if (!success ) {
2344 /* On failure, it is safe to purge again (potential perf
24- * penalty) If kernel can tell exactly which regions
25- * failed, we could avoid that penalty.
26- */
45+ * penalty) If kernel can tell exactly which regions
46+ * failed, we could avoid that penalty.
47+ */
2748 for (size_t i = 0 ; i < vlen ; ++ i ) {
28- shard -> central -> hooks .purge (
29- vec [i ].iov_base , vec [i ].iov_len );
49+ hooks -> purge (vec [i ].iov_base , vec [i ].iov_len );
3050 }
3151 }
3252}
3353
3454/*
35- * This struct accumulates the regions for process_madvise.
36- * It invokes the hook when batch limit is reached
55+ * This structure accumulates the regions for process_madvise. It invokes the
56+ * hook when batch limit is reached.
3757 */
3858typedef struct {
3959 hpa_io_vector_t * vp ;
@@ -51,16 +71,16 @@ hpa_range_accum_init(hpa_range_accum_t *ra, hpa_io_vector_t *v, size_t sz) {
5171}
5272
5373static inline void
54- hpa_range_accum_flush (hpa_range_accum_t * ra , hpa_shard_t * shard ) {
74+ hpa_range_accum_flush (hpa_range_accum_t * ra , hpa_hooks_t * hooks ) {
5575 assert (ra -> total_bytes > 0 && ra -> cur > 0 );
56- hpa_try_vectorized_purge (shard , ra -> vp , ra -> cur , ra -> total_bytes );
76+ hpa_try_vectorized_purge (hooks , ra -> vp , ra -> cur , ra -> total_bytes );
5777 ra -> cur = 0 ;
5878 ra -> total_bytes = 0 ;
5979}
6080
6181static inline void
6282hpa_range_accum_add (
63- hpa_range_accum_t * ra , void * addr , size_t sz , hpa_shard_t * shard ) {
83+ hpa_range_accum_t * ra , void * addr , size_t sz , hpa_hooks_t * hooks ) {
6484 assert (ra -> cur < ra -> capacity );
6585
6686 ra -> vp [ra -> cur ].iov_base = addr ;
@@ -69,14 +89,14 @@ hpa_range_accum_add(
6989 ra -> cur ++ ;
7090
7191 if (ra -> cur == ra -> capacity ) {
72- hpa_range_accum_flush (ra , shard );
92+ hpa_range_accum_flush (ra , hooks );
7393 }
7494}
7595
7696static inline void
77- hpa_range_accum_finish (hpa_range_accum_t * ra , hpa_shard_t * shard ) {
97+ hpa_range_accum_finish (hpa_range_accum_t * ra , hpa_hooks_t * hooks ) {
7898 if (ra -> cur > 0 ) {
79- hpa_range_accum_flush (ra , shard );
99+ hpa_range_accum_flush (ra , hooks );
80100 }
81101}
82102
@@ -114,4 +134,28 @@ struct hpa_purge_batch_s {
114134 size_t npurged_hp_total ;
115135};
116136
137+ static inline bool
138+ hpa_batch_full (hpa_purge_batch_t * b ) {
139+ /* It's okay for ranges to go above */
140+ return b -> npurged_hp_total == b -> max_hp
141+ || b -> item_cnt == b -> items_capacity
142+ || b -> nranges >= b -> range_watermark ;
143+ }
144+
145+ static inline void
146+ hpa_batch_pass_start (hpa_purge_batch_t * b ) {
147+ b -> item_cnt = 0 ;
148+ b -> nranges = 0 ;
149+ b -> ndirty_in_batch = 0 ;
150+ }
151+
152+ static inline bool
153+ hpa_batch_empty (hpa_purge_batch_t * b ) {
154+ return b -> item_cnt == 0 ;
155+ }
156+
157+ /* Purge pages in a batch using given hooks */
158+ void hpa_purge_batch (
159+ hpa_hooks_t * hooks , hpa_purge_item_t * batch , size_t batch_sz );
160+
117161#endif /* JEMALLOC_INTERNAL_HPA_UTILS_H */
0 commit comments