diff --git a/src/arena.c b/src/arena.c index 43733cc..5c1a3b3 100644 --- a/src/arena.c +++ b/src/arena.c @@ -1266,6 +1266,7 @@ arena_dirty_count(arena_t *arena) return (ndirty); } +#define PURGE_VEC 1 static size_t arena_compute_npurge(arena_t *arena, bool all) { @@ -1280,6 +1281,10 @@ arena_compute_npurge(arena_t *arena, bool all) threshold = threshold < chunk_npages ? chunk_npages : threshold; npurge = arena->ndirty - threshold; +#if PURGE_VEC + if (npurge < arena->ndirty / 2) + npurge = arena->ndirty / 2; +#endif } else npurge = arena->ndirty; @@ -1366,6 +1371,31 @@ arena_stash_dirty(arena_t *arena, chunk_hooks_t *chunk_hooks, bool all, return (nstashed); } +#if PURGE_VEC +int mycomp(const void *a, const void *b) +{ + unsigned long a_b = (unsigned long)((struct iovec *)a)->iov_base; + unsigned long b_b = (unsigned long)((struct iovec *)b)->iov_base; + + if (a_b < b_b) + return -1; + if (a_b > b_b) + return 1; + return 0; +} + +#define MAX_IOVEC 32 +bool pages_purge_vec(struct iovec *iov, unsigned long nr_segs) +{ + int ret; + + qsort(iov, nr_segs, sizeof(struct iovec), mycomp); + ret = syscall(327, iov, nr_segs, MADV_DONTNEED); + + return !!ret; +} +#endif + static size_t arena_purge_stashed(arena_t *arena, chunk_hooks_t *chunk_hooks, arena_runs_dirty_link_t *purge_runs_sentinel, @@ -1374,6 +1404,10 @@ arena_purge_stashed(arena_t *arena, chunk_hooks_t *chunk_hooks, size_t npurged, nmadvise; arena_runs_dirty_link_t *rdelm; extent_node_t *chunkselm; +#if PURGE_VEC + struct iovec iovec[MAX_IOVEC]; + int vec_index = 0; +#endif if (config_stats) nmadvise = 0; @@ -1418,9 +1452,21 @@ arena_purge_stashed(arena_t *arena, chunk_hooks_t *chunk_hooks, flag_unzeroed = 0; flags = CHUNK_MAP_DECOMMITTED; } else { +#if !PURGE_VEC flag_unzeroed = chunk_purge_wrapper(arena, chunk_hooks, chunk, chunksize, pageind << LG_PAGE, run_size) ? CHUNK_MAP_UNZEROED : 0; +#else + flag_unzeroed = 0; + iovec[vec_index].iov_base = (void *)((uintptr_t)chunk + + (pageind << LG_PAGE)); + iovec[vec_index].iov_len = run_size; + vec_index++; + if (vec_index >= MAX_IOVEC) { + pages_purge_vec(iovec, vec_index); + vec_index = 0; + } +#endif flags = flag_unzeroed; } arena_mapbits_large_set(chunk, pageind+npages-1, 0, @@ -1449,6 +1495,10 @@ arena_purge_stashed(arena_t *arena, chunk_hooks_t *chunk_hooks, if (config_stats) nmadvise++; } +#if PURGE_VEC + if (vec_index > 0) + pages_purge_vec(iovec, vec_index); +#endif malloc_mutex_lock(&arena->lock); if (config_stats) {