Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp858309pxk; Wed, 9 Sep 2020 23:42:12 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxNQ3YL5fT2ZqmQAfNuPOPSowXADrNEfEXRwihDSVAUmpCLFooj/xHhhGIrqffmfMWWnfq0 X-Received: by 2002:a17:906:f11:: with SMTP id z17mr7578705eji.88.1599720132204; Wed, 09 Sep 2020 23:42:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1599720132; cv=none; d=google.com; s=arc-20160816; b=g2U2ee3rnv44IuKcVZZtXTNYXA4kCV2R0K8IB4hG7/IfDNmi7MP9eZtvA7KdzDmEIb ncE1Xi8QeVnmBWk5W7KUmG4K03qKj9TfOc78hiP9EZPe7gPZRssX1WwKzdNFhza/0xza qetZcKuWI2v//7E56cjG/Fz5cJa79pKhiSyGc36mfv4HtD4nfyS4SJ66fqp/M+YkqYLA plwLZhJ4hzbp34sRPe1XB6XXrvTd+9NXNkt4HGFXZt55FaCp95rb96i9wUvDWiAwgCJx srKQ+Gl4mrDlgeRUucuwir2c9DExz7u3KvrUbKZZypk8Ep8EYBLXbbOjX2vR5To+E5So +PBQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=GzpkhECVivbbxVgp+QkERBRuQKYx97kDrCEsWiAnM9s=; b=Srh+0RgOfXfrYIULKb3m8QhbKQcfTf0oQ70GFO6nxb1zt9S90qEolYBt4mWoYB1nrf /um97l/uFOe+DCXqLrqSXA9drvT4lqFU1j2t+wL+tBZlCF4xBWZCTwBv2PhnVXYP7xxM ne1FbgDHRaJUWuGhG9M2grJXpwMbq/8ZXUyVjnpgkKV5U0FH+md3Oyfwd6xra6pFlpGr QxrymbvvIJ86kq8knH6gOr7WsfRkXn67O/EBkHgxcmmgyzr1fISLyqyTGq/f8hKvdxqe 7HU4PWfF8aCjHZBZKn2+HgHKFeoJNLJuwfi4zWWZ4fb2CcmDFsTUsNXL37qyGfEY0rTV ogAA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amazon.com header.s=amazon201209 header.b=eqrGHGTW; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id rv15si3136131ejb.364.2020.09.09.23.41.48; Wed, 09 Sep 2020 23:42:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@amazon.com header.s=amazon201209 header.b=eqrGHGTW; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727830AbgIJGie (ORCPT + 99 others); Thu, 10 Sep 2020 02:38:34 -0400 Received: from smtp-fw-6002.amazon.com ([52.95.49.90]:44938 "EHLO smtp-fw-6002.amazon.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727770AbgIJGhW (ORCPT ); Thu, 10 Sep 2020 02:37:22 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1599719842; x=1631255842; h=from:to:cc:subject:date:message-id:in-reply-to: mime-version; bh=GzpkhECVivbbxVgp+QkERBRuQKYx97kDrCEsWiAnM9s=; b=eqrGHGTWOcYQDTFvK4V7hC4d347sRYuVslGSprlpm+0ajmKKcWKycfcu XuHg8w78O7p4ICDgRsG1520AnQPnLMtgdVxPeqOqf229yQNk3xdjHNxpJ B+SwIYjOjA90p9FogFYZLu5PfsTDp2qUmNqaMwlX+DHuySwo0NcYR7yIa o=; X-IronPort-AV: E=Sophos;i="5.76,412,1592870400"; d="scan'208";a="53096358" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-2c-1968f9fa.us-west-2.amazon.com) ([10.43.8.6]) by smtp-border-fw-out-6002.iad6.amazon.com with ESMTP; 10 Sep 2020 06:37:19 +0000 Received: from EX13D31EUA001.ant.amazon.com (pdx4-ws-svc-p6-lb7-vlan3.pdx.amazon.com [10.170.41.166]) by email-inbound-relay-2c-1968f9fa.us-west-2.amazon.com (Postfix) with ESMTPS id 9C012A06BF; Thu, 10 Sep 2020 06:37:17 +0000 (UTC) Received: from u3f2cd687b01c55.ant.amazon.com (10.43.160.100) by EX13D31EUA001.ant.amazon.com (10.43.165.15) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 10 Sep 2020 06:37:10 +0000 From: SeongJae Park To: Shakeel Butt CC: Johannes Weiner , Roman Gushchin , Michal Hocko , Yang Shi , Greg Thelen , David Rientjes , =?UTF-8?q?Michal=20Koutn=C3=BD?= , Andrew Morton , , , Subject: Re: [PATCH] memcg: introduce per-memcg reclaim interface Date: Thu, 10 Sep 2020 08:36:56 +0200 Message-ID: <20200910063656.25038-1-sjpark@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200909215752.1725525-1-shakeelb@google.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.43.160.100] X-ClientProxiedBy: EX13D05UWB004.ant.amazon.com (10.43.161.208) To EX13D31EUA001.ant.amazon.com (10.43.165.15) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2020-09-09T14:57:52-07:00 Shakeel Butt wrote: > Introduce an memcg interface to trigger memory reclaim on a memory cgroup. > > Use cases: > ---------- > > 1) Per-memcg uswapd: > > Usually applications consists of combination of latency sensitive and > latency tolerant tasks. For example, tasks serving user requests vs > tasks doing data backup for a database application. At the moment the > kernel does not differentiate between such tasks when the application > hits the memcg limits. So, potentially a latency sensitive user facing > task can get stuck in high reclaim and be throttled by the kernel. > > Similarly there are cases of single process applications having two set > of thread pools where threads from one pool have high scheduling > priority and low latency requirement. One concrete example from our > production is the VMM which have high priority low latency thread pool > for the VCPUs while separate thread pool for stats reporting, I/O > emulation, health checks and other managerial operations. The kernel > memory reclaim does not differentiate between VCPU thread or a > non-latency sensitive thread and a VCPU thread can get stuck in high > reclaim. > > One way to resolve this issue is to preemptively trigger the memory > reclaim from a latency tolerant task (uswapd) when the application is > near the limits. Finding 'near the limits' situation is an orthogonal > problem. > > 2) Proactive reclaim: > > This is a similar to the previous use-case, the difference is instead of > waiting for the application to be near its limit to trigger memory > reclaim, continuously pressuring the memcg to reclaim a small amount of > memory. This gives more accurate and uptodate workingset estimation as > the LRUs are continuously sorted and can potentially provide more > deterministic memory overcommit behavior. The memory overcommit > controller can provide more proactive response to the changing behavior > of the running applications instead of being reactive. > > Benefit of user space solution: > ------------------------------- > > 1) More flexible on who should be charged for the cpu of the memory > reclaim. For proactive reclaim, it makes more sense to centralized the > overhead while for uswapd, it makes more sense for the application to > pay for the cpu of the memory reclaim. > > 2) More flexible on dedicating the resources (like cpu). The memory > overcommit controller can balance the cost between the cpu usage and > the memory reclaimed. > > 3) Provides a way to the applications to keep their LRUs sorted, so, > under memory pressure better reclaim candidates are selected. This also > gives more accurate and uptodate notion of working set for an > application. > > Questions: > ---------- > > 1) Why memory.high is not enough? > > memory.high can be used to trigger reclaim in a memcg and can > potentially be used for proactive reclaim as well as uswapd use cases. > However there is a big negative in using memory.high. It can potentially > introduce high reclaim stalls in the target application as the > allocations from the processes or the threads of the application can hit > the temporary memory.high limit. > > Another issue with memory.high is that it is not delegatable. To > actually use this interface for uswapd, the application has to introduce > another layer of cgroup on whose memory.high it has write access. > > 2) Why uswapd safe from self induced reclaim? > > This is very similar to the scenario of oomd under global memory > pressure. We can use the similar mechanisms to protect uswapd from self > induced reclaim i.e. memory.min and mlock. > > Interface options: > ------------------ > > Introducing a very simple memcg interface 'echo 10M > memory.reclaim' to > trigger reclaim in the target memory cgroup. > > In future we might want to reclaim specific type of memory from a memcg, > so, this interface can be extended to allow that. e.g. > > $ echo 10M [all|anon|file|kmem] > memory.reclaim > > However that should be when we have concrete use-cases for such > functionality. Keep things simple for now. > > Signed-off-by: Shakeel Butt > --- > Documentation/admin-guide/cgroup-v2.rst | 9 ++++++ > mm/memcontrol.c | 37 +++++++++++++++++++++++++ > 2 files changed, 46 insertions(+) > > diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst > index 6be43781ec7f..58d70b5989d7 100644 > --- a/Documentation/admin-guide/cgroup-v2.rst > +++ b/Documentation/admin-guide/cgroup-v2.rst > @@ -1181,6 +1181,15 @@ PAGE_SIZE multiple when read back. > high limit is used and monitored properly, this limit's > utility is limited to providing the final safety net. > > + memory.reclaim > + A write-only file which exists on non-root cgroups. > + > + This is a simple interface to trigger memory reclaim in the > + target cgroup. Write the number of bytes to reclaim to this > + file and the kernel will try to reclaim that much memory. > + Please note that the kernel can over or under reclaim from > + the target cgroup. > + > memory.oom.group > A read-write single value file which exists on non-root > cgroups. The default value is "0". > diff --git a/mm/memcontrol.c b/mm/memcontrol.c > index 75cd1a1e66c8..2d006c36d7f3 100644 > --- a/mm/memcontrol.c > +++ b/mm/memcontrol.c > @@ -6456,6 +6456,38 @@ static ssize_t memory_oom_group_write(struct kernfs_open_file *of, > return nbytes; > } > > +static ssize_t memory_reclaim(struct kernfs_open_file *of, char *buf, > + size_t nbytes, loff_t off) > +{ > + struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of)); > + unsigned int nr_retries = MAX_RECLAIM_RETRIES; > + unsigned long nr_to_reclaim, nr_reclaimed = 0; > + int err; > + > + buf = strstrip(buf); > + err = page_counter_memparse(buf, "", &nr_to_reclaim); > + if (err) > + return err; > + > + while (nr_reclaimed < nr_to_reclaim) { > + unsigned long reclaimed; > + > + if (signal_pending(current)) > + break; > + > + reclaimed = try_to_free_mem_cgroup_pages(memcg, > + nr_to_reclaim - nr_reclaimed, > + GFP_KERNEL, true); > + > + if (!reclaimed && !nr_retries--) > + break; Shouldn't the if condition use '||' instead of '&&'? I think it could be easier to read if we put the 'nr_retires' condition in the while condition as below (just my personal preference, though). while (nr_reclaimed < nr_to_reclaim && nr_retires--) Thanks, SeongJae Park