]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Set initial arc_c to arc_c_min instead of arc_c_max
authorAlexander Motin <mav@FreeBSD.org>
Wed, 17 Jun 2020 21:27:04 +0000 (17:27 -0400)
committerGitHub <noreply@github.com>
Wed, 17 Jun 2020 21:27:04 +0000 (14:27 -0700)
For at least 15 years since OpenSolaris arc_c was set by default to
arc_c_max, later decreased under memory pressure.  I've noticed that
if arc_c was set high enough to cause memory pressure as considered
by ZFS, setting of arc_no_grow to TRUE in arc_reap_cb_check() makes
no effect until both arc_kmem_reap_soon() and delay(reap_retry_ms)
return.  All that time ZFS can continue increasing its effective ARC
size, causing more memory pressure, potentially up to the point when
OS low memory handler activates and reduces arc_c, requesting fast
reclamation of just allocated memory.

The problem seems to be more serious on FreeBSD and I guess Linux,
since neither of them implement/use asynchronous kmem reclamation,
so arc_kmem_reap_soon() can take more time.  On older FreeBSD 11 not
supporting multiple memory domains system with lots of RAM can get
completely unresponsive for minutes due to heavy lock congestion
between ARC reclamation and page daemon kmem reclamation threads.
With this change to more conservative arc_c value ARC stops growing
just it time and does not need later reclamation.

Also while there, since now growing arc_c is a more often situation,
use aggsum_upper_bound() instead of aggsum_compare() in arc_adapt()
to reduce lock congestion.  It is also getting in sync with code in
arc_get_data_impl().

Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Reviewed-by: Allan Jude <allanjude@freebsd.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Alexander Motin <mav@FreeBSD.org>
Sponsored-By: iXsystems, Inc.
Closes #10437

module/zfs/arc.c

index c2e6720d3e2343fc70d25db30a1be3dca0cba52b..5717405d624a4069cae052553f3384f596627cb0 100644 (file)
@@ -4974,8 +4974,8 @@ arc_adapt(int bytes, arc_state_t *state)
         * cache size, increment the target cache size
         */
        ASSERT3U(arc_c, >=, 2ULL << SPA_MAXBLOCKSHIFT);
-       if (aggsum_compare(&arc_size, arc_c - (2ULL << SPA_MAXBLOCKSHIFT)) >=
-           0) {
+       if (aggsum_upper_bound(&arc_size) >=
+           arc_c - (2ULL << SPA_MAXBLOCKSHIFT)) {
                atomic_add_64(&arc_c, (int64_t)bytes);
                if (arc_c > arc_c_max)
                        arc_c = arc_c_max;
@@ -7078,7 +7078,7 @@ arc_tuning_update(boolean_t verbose)
            (zfs_arc_max >= 64 << 20) && (zfs_arc_max < allmem) &&
            (zfs_arc_max > arc_c_min)) {
                arc_c_max = zfs_arc_max;
-               arc_c = arc_c_max;
+               arc_c = MIN(arc_c, arc_c_max);
                arc_p = (arc_c >> 1);
                if (arc_meta_limit > arc_c_max)
                        arc_meta_limit = arc_c_max;
@@ -7325,7 +7325,7 @@ arc_init(void)
        arc_c_min = MAX(arc_c_max / 2, 2ULL << SPA_MAXBLOCKSHIFT);
 #endif
 
-       arc_c = arc_c_max;
+       arc_c = arc_c_min;
        arc_p = (arc_c >> 1);
 
        /* Set min to 1/2 of arc_c_min */