From patchwork Fri Oct 12 10:11:57 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Vorontsov X-Patchwork-Id: 12181 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 4757923FB3 for ; Fri, 12 Oct 2012 10:15:04 +0000 (UTC) Received: from mail-ia0-f180.google.com (mail-ia0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id CDE39A1855C for ; Fri, 12 Oct 2012 10:15:03 +0000 (UTC) Received: by mail-ia0-f180.google.com with SMTP id f6so1916442iag.11 for ; Fri, 12 Oct 2012 03:15:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=YHkINMzvPL1YJjJaAnV4i76qhe131GdlNEw4EYvVGoE=; b=CJO2MmVpAWz0J3nuXDVNCGVvlB5FTi3NQ8emJ34qyKdbW1iRl+Q0iuxueqy/auSXVc KRWmlJha3bHvz0n7H7DOcbbBhiWqUWkf/vsjkjrJ30BjWvxbatB3qyclwphowhHciLnk jnpIVGdFrT2fLXCDDYV14lUYZPdL5K36GxCnqCBJ17hreCiIJSGOLpurL6MmmJS5BiDQ 4x/BzNBozgNkBc3EB8PK4oLoUDjarpMhuQOrU0iZLHWkQbWb6HxtmdwY7KwzGW0t6IFx Y1hmNUTRpsF7iPDcE4vVwIZbvFBxyxiFgK2KCsGo02dPFvR4k3W6j8BtnYGu1pBpxCMp 47/A== Received: by 10.50.91.195 with SMTP id cg3mr1654574igb.57.1350036903233; Fri, 12 Oct 2012 03:15:03 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.67.148 with SMTP id n20csp175496igt; Fri, 12 Oct 2012 03:15:02 -0700 (PDT) Received: by 10.68.237.106 with SMTP id vb10mr12004947pbc.112.1350036902483; Fri, 12 Oct 2012 03:15:02 -0700 (PDT) Received: from mail-pa0-f50.google.com (mail-pa0-f50.google.com [209.85.220.50]) by mx.google.com with ESMTPS id np6si6238236pbc.359.2012.10.12.03.15.02 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 12 Oct 2012 03:15:02 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.50 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) client-ip=209.85.220.50; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.50 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) smtp.mail=anton.vorontsov@linaro.org Received: by mail-pa0-f50.google.com with SMTP id hz11so2968783pad.37 for ; Fri, 12 Oct 2012 03:15:02 -0700 (PDT) Received: by 10.68.233.198 with SMTP id ty6mr11996332pbc.107.1350036902237; Fri, 12 Oct 2012 03:15:02 -0700 (PDT) Received: from localhost (c-71-204-165-222.hsd1.ca.comcast.net. [71.204.165.222]) by mx.google.com with ESMTPS id jw14sm4239033pbb.36.2012.10.12.03.15.00 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 12 Oct 2012 03:15:01 -0700 (PDT) From: Anton Vorontsov To: Pekka Enberg Cc: Mel Gorman , Leonid Moiseichuk , KOSAKI Motohiro , Minchan Kim , Bartlomiej Zolnierkiewicz , John Stultz , linux-mm@kvack.org, linux-kernel@vger.kernel.org, linaro-kernel@lists.linaro.org, patches@linaro.org, kernel-team@android.com Subject: [PATCH 1/3] mm: vmstat: Implement set_zone_stat_thresholds() helper Date: Fri, 12 Oct 2012 03:11:57 -0700 Message-Id: <1350036719-29031-1-git-send-email-anton.vorontsov@linaro.org> X-Mailer: git-send-email 1.7.12.1 In-Reply-To: <20121012101115.GA11825@lizard> References: <20121012101115.GA11825@lizard> X-Gm-Message-State: ALoCoQmcYKcFIqVA9ZgYgRe2XJxPDRjqUosIvfmj7T01Zlblpc6ghdlx5z7yqsFFUpbJD10yWG6B There are two things that affect vmstat accuracy: - Per CPU pageset stats to global stats synchronization time; - Per CPU pageset stats thresholds; Currently user can only change vmstat update time (via stat_interval sysctl, which is 1 second by default). As for thresholds, the max threshold is 125 pages, which is per CPU, per zone, so the vmstat inaccuracy might be significant. With vmevent API we will able to set vmstat thresholds as well -- we will use this small helper for this. Note that since various MM areas depend on the accuracy too, we should be very carefully to not downgrade it. User also have to understand that lower thresholds puts more pressure on caches, and can somewhat degrade performance, especially on very large systems. But that's the price for accuracy (if it is needed). p.s. set_pgdat_percpu_threshold() used for_each_possible_cpu(), and refresh_zone_stat_thresholds() used for_each_online_cpu(). I think for_each_possible_cpu() is unnecessary, as on CPU hotplug we call refresh_zone_stat_thresholds() anyway. Signed-off-by: Anton Vorontsov --- include/linux/vmstat.h | 6 ++++++ mm/vmstat.c | 52 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index ad2cfd5..590808d 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h @@ -202,6 +202,9 @@ int calculate_pressure_threshold(struct zone *zone); int calculate_normal_threshold(struct zone *zone); void set_pgdat_percpu_threshold(pg_data_t *pgdat, int (*calculate_pressure)(struct zone *)); +s8 set_zone_stat_thresholds(struct zone *zone, + int (*calc_thres)(struct zone *zone), + s8 force); #else /* CONFIG_SMP */ /* @@ -248,6 +251,9 @@ static inline void __dec_zone_page_state(struct page *page, #define set_pgdat_percpu_threshold(pgdat, callback) { } +static inline s8 set_zone_stat_thresholds(struct zone *zone, + int (*calc_thres)(struct zone *zone), + s8 force) { return 0; } static inline void refresh_cpu_vm_stats(int cpu) { } static inline void refresh_zone_stat_thresholds(void) { } diff --git a/mm/vmstat.c b/mm/vmstat.c index df7a674..3609e3e 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -155,22 +155,55 @@ int calculate_normal_threshold(struct zone *zone) } /* + * set_zone_stat_thresholds() - Set zone stat thresholds + * @zone: A zone to set thresholds for + * @calc_thres: An optional callback to calculate thresholds + * @force: An optional threshold value to force thresholds + * + * This function sets stat thresholds for a desired zone. The thresholds + * are either calculated by the optional @calc_thres callback, or set to + * the @force value. If @force is greater than current zone's threshold, + * the new value is ignored. + */ +s8 set_zone_stat_thresholds(struct zone *zone, + int (*calc_thres)(struct zone *zone), + s8 force) +{ + static s8 forced_threshold; + s8 thres = force; + uint cpu; + + if (!calc_thres) { + if (!force) + calc_thres = calculate_normal_threshold; + forced_threshold = force; + } + + if (calc_thres) { + thres = calc_thres(zone); + if (forced_threshold) + thres = min(thres, forced_threshold); + } + + for_each_online_cpu(cpu) + per_cpu_ptr(zone->pageset, cpu)->stat_threshold = thres; + + return thres; +} + +/* * Refresh the thresholds for each zone. */ void refresh_zone_stat_thresholds(void) { struct zone *zone; - int cpu; int threshold; for_each_populated_zone(zone) { unsigned long max_drift, tolerate_drift; - threshold = calculate_normal_threshold(zone); - - for_each_online_cpu(cpu) - per_cpu_ptr(zone->pageset, cpu)->stat_threshold - = threshold; + threshold = set_zone_stat_thresholds(zone, + calculate_normal_threshold, 0); /* * Only set percpu_drift_mark if there is a danger that @@ -189,8 +222,6 @@ void set_pgdat_percpu_threshold(pg_data_t *pgdat, int (*calculate_pressure)(struct zone *)) { struct zone *zone; - int cpu; - int threshold; int i; for (i = 0; i < pgdat->nr_zones; i++) { @@ -198,10 +229,7 @@ void set_pgdat_percpu_threshold(pg_data_t *pgdat, if (!zone->percpu_drift_mark) continue; - threshold = (*calculate_pressure)(zone); - for_each_possible_cpu(cpu) - per_cpu_ptr(zone->pageset, cpu)->stat_threshold - = threshold; + set_zone_stat_thresholds(zone, calculate_pressure, 0); } }