Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126259 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 7E5591A00BC for ; Fri, 31 Jan 2025 15:06:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1738335840; bh=bQHZnnXukuPtBvhY7rjQOOhXNhLFU0xTvTE+ow5/LnA=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=j07j1yNou0BoDvUxKVm90ytdZf9XNBKU9pseBfs/3fnvRdVn9JLvxvmvObE0sfB8o gF+ItgBTvWnXFNNmwW+c6JqSNmjX/sy6ZnOc+vMcnq71q04LG3fjMt+xfID5OsiEac ZcNWfYQ2z1KCWDuQepOcINWqk/R60nSpWP+aaAM1x87dE6qGmD/njmTgn4Cgqejiyt E0DNIMbS0uJJM3Ou2QO/QxLIuUMNB7vWlYRoGL+NA1XaR/tkd8BHuujtqBdMsMFAmQ QrJ9PlABpYn+MSJjQGgNocigywaLSBGMSBUW7fiG1q/7K1QdfzLY16CpMTGlUS5arj ffGlP5EZY5Ytg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 6632E18003B for ; Fri, 31 Jan 2025 15:03:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.2 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-qt1-f171.google.com (mail-qt1-f171.google.com [209.85.160.171]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 31 Jan 2025 15:03:58 +0000 (UTC) Received: by mail-qt1-f171.google.com with SMTP id d75a77b69052e-467a63f5d1cso16510351cf.0 for ; Fri, 31 Jan 2025 07:06:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ethaniel.com; s=google; t=1738336005; x=1738940805; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=bQHZnnXukuPtBvhY7rjQOOhXNhLFU0xTvTE+ow5/LnA=; b=TDXJzFXi/ObaiQXtzT+pnAmIaO5/GmuxTy897GzhAt30T7BkJTzjh1tzgtzpUgey5+ PjgQ+qrBn9+e22kwmK9+/ngd34AYCC+pGuaI0uG+RgJnPoi1cdQC1+u/oVzwCJhk549T K2KMrxBVcIX3pL9NhYWWZjjhLZ49F7fzed2Zc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738336005; x=1738940805; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=bQHZnnXukuPtBvhY7rjQOOhXNhLFU0xTvTE+ow5/LnA=; b=RRNUnq++m3/UdSWa1NelCqVbWHd7oRTodatslebZTPIt1DWEk1zgQGUOSvJwybbnDg NLVmQK+j2nBRnroA8VAB2bYeEEZpF7tEcfHdSJ5i40lMiPtBfb0fiCLQAqhOgRRqwr8f cjGGGZcygo7i1svy0JShrnlpDz4RlmMwcEZNbewCY7SWvv8IAbb+Nw3L3py1rnrPP5eM cK9bBn8gocNhruRwHhsuJ4GBHvBwXcZ4ML0TykbqcrLVHZxup9s5g3cLWTss1MyGeUyw MJZtE01ZuHm/90BptpNiIvCsCtTzyIwPVLu6cYJFb8NDvUZ/ZwO5zkXCnjA4Pyk255xn x0JQ== X-Gm-Message-State: AOJu0Yx+VIM4W6uErVjvfNBIEVWnaHwrJie7ucB2rJWaoSb5OqMuAb3b Sgcx2cz5E11CZh/9nVDnecy/Scz33KAr2rJ8ppDAqSU2G+b/BiG1vTMgU/mopaP33rxHlryvof+ JHJ1ZXzfhjyXWZ7AQM1L+ClLR3TQoqd+N/9kFK+uxjIixorJHxW4M X-Gm-Gg: ASbGnctetFxA4BSolR1g9PC3XEI3mPEYVI52iSA38D8ytlYV/RfX72QD37VYxnj5VAy 9Y22dgDAIthL4dBlpU/DGMiqS/J6SrMTNt04eHKbgOaRYN91VBNE2VitkvppLQgJtKrs/e52LVw == X-Google-Smtp-Source: AGHT+IHbTS/LV+OJk6KH+JF3YnxKkuh5GltzYEdIeoCIZpQ+gH1XE3iGLzFiFf593TxhiwJNDjr30Buf09A14LJm52I= X-Received: by 2002:ac8:6f0f:0:b0:467:6c18:9857 with SMTP id d75a77b69052e-46fd0b6f998mr186605261cf.37.1738336005539; Fri, 31 Jan 2025 07:06:45 -0800 (PST) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 31 Jan 2025 09:06:19 -0600 X-Gm-Features: AWEUYZlYqlmZvsFzjZAshUMnLYV3NG4MKUPt4sbecj4u34GRn5CQTmIlznI6SKc Message-ID: Subject: Re: [PHP-DEV] [RFC] Introducing pm.max_memory for PHP-FPM To: Jakub Zelenka Cc: internals@lists.php.net Content-Type: multipart/alternative; boundary="0000000000001c5a06062d01e40c" From: eth@ethaniel.com (Arkadiy Kulev) --0000000000001c5a06062d01e40c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi! > This wouldn't really work because FPM does not control the script during >>> execution and would have to check it out after each allocation which is= not >>> really viable. >>> >> >>> >> Thanks for the feedback! I agree that monitoring memory usage after each >> allocation would be infeasible. However, my suggestion was actually to >> check memory usage *only once per request*, specifically at request >> shutdown, when FPM regains control and before assigning another request = to >> that worker. >> > >> > I think that would require a different name because it would not reflect > max memory usage in any way - it would be measured at the time when the > memory usage is lowest. We could maybe set some options that would measur= e > the maximum of increase of memory between requests - I mean difference > between lowest memory usage (most likely after the first request) and the= n > compare against current usage after the latest request and set limit on > this difference. Not sure about the name for that. Maybe something like > pm.max_memory_increase or something like that. > I see where you=E2=80=99re coming from, but I believe measuring memory =E2= =80=9Cdelta=E2=80=9D or =E2=80=9Cincrease=E2=80=9D could be confusing for end users. In practice, a= dmins and developers often glance at tools like top or ps to see *current* memory usage for each FPM worker, spot outliers, and then set a threshold accordingly. If we start talking about =E2=80=9Clowest usage=E2=80=9D vs. =E2=80=9Ccurre= nt usage=E2=80=9D and a =E2=80=9Cmax increase,=E2=80=9D that becomes much harder to translate to real-world monitoring=E2=80=94and it=E2=80=99s non-intuitive compared to simply readin= g the value right off top and setting a limit. So, from a usability standpoint, I think a direct measurement of resident memory (as people see in common system tools) would be the most straightforward and least confusing. > Just to be clear, "memory_limit" helps kill runaway scripts mid-request. >> By contrast, the newly proposed pm.max_memory is meant to catch processe= s >> with a slow leak across multiple requests. We only need to check at the = end >> of each request, which is presumably when the worker returns control to = FPM. >> > > There is one thing to note that memory_limit actually measure only memory > allocated through the per request php memory allocator so it's not actual= ly > limit on total usage including the standard allocator memory usage. So > there would be still a use case for total limit using cgroups but I agree > that the more important use is to catch slow leaks which the above should > help with in a better way than pm.max_requests. > You=E2=80=99re absolutely right that cgroups handle total memory usage=E2= =80=94including memory outside the PHP allocator=E2=80=94more accurately. But as I=E2=80=99= ve mentioned before, relying on cgroups to limit memory typically means an OOM kill that can happen at *any* moment, often right in the middle of a request. That=E2= =80=99s precisely what I=E2=80=99m trying to avoid. The whole idea behind pm.max_memory is to allow a *graceful* check *after* each request completes, so we can recycle the worker before starting a new request. That way, no request gets abruptly killed. cgroups don=E2=80=99t r= eally accommodate that scenario=E2=80=94they=E2=80=99re great for overall resourc= e control but not for per-request, child-level recycling within FPM. --0000000000001c5a06062d01e40c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi!<= /div>
=C2=A0
This wouldn't really work because FPM does not control the script d= uring execution and would have to check it out after each allocation which = is not really viable.
=C2=A0
Thanks for the fee= dback! I agree that monitoring memory usage after each allocation would be = infeasible. However, my suggestion was actually to check memory usage on= ly once per request, specifically at request shutdown, when FPM regains= control and before assigning another request to that worker.=C2=A0=C2=A0
=C2=A0
I think that would requir= e a different name because it would not reflect max memory usage in any way= - it would be measured at the time when the memory usage is lowest. We cou= ld maybe set some options that would measure the maximum of increase of mem= ory between requests - I mean difference between lowest memory usage (most = likely after the first request) and then compare against current usage afte= r the latest request and set limit on this difference. Not sure about the n= ame for that. Maybe something like pm.max_memory_increase or something like= that.
=C2=A0
I see where= you=E2=80=99re coming from, but I believe measuring memory =E2=80=9Cdelta= =E2=80=9D or =E2=80=9Cincrease=E2=80=9D could be confusing for end users. I= n practice, admins and developers often glance at tools like=C2=A0top= =C2=A0or=C2=A0ps=C2=A0to see=C2=A0current=C2= =A0memory usage for each FPM worker, spot outliers, and then set a threshol= d accordingly.

If we start talking about =E2=80=9Clowest usage= =E2=80=9D vs. =E2=80=9Ccurrent usage=E2=80=9D and a =E2=80=9Cmax increase,= =E2=80=9D that becomes much harder to translate to real-world monitoring=E2= =80=94and it=E2=80=99s non-intuitive compared to simply reading the value r= ight off=C2=A0top=C2=A0and setting a limit. So, from a usabili= ty standpoint, I think a direct measurement of resident memory (as people s= ee in common system tools) would be the most straightforward and least conf= using.

=C2=A0
Just to be clear, "memory_limit" helps kill run= away scripts mid-request. By contrast, the newly proposed pm.max_memory is = meant to catch processes with a slow leak across multiple requests. We only= need to check at the end of each request, which is presumably when the wor= ker returns control to FPM.

There is one thing to note that memory_limit actually measure only memor= y allocated through the per request php memory allocator so it's not ac= tually limit on total usage including the standard allocator memory usage. = So there would be still a use case for total limit using cgroups but I agre= e that the more important use is to catch slow leaks which the above should= help with in a better way than pm.max_requests.

You=E2=80=99re absolutely right that cgroups handle total m= emory usage=E2=80=94including memory outside the PHP allocator=E2=80=94more= accurately. But as I=E2=80=99ve mentioned before, relying on cgroups to li= mit memory typically means an OOM kill that can happen at any mome= nt, often right in the middle of a request. That=E2=80=99s precisely what I= =E2=80=99m trying to avoid.

The whole idea behind pm.max_memory is to allow a graceful check after each requ= est completes, so we can recycle the worker before starting a new request. = That way, no request gets abruptly killed. cgroups don=E2=80=99t really acc= ommodate that scenario=E2=80=94they=E2=80=99re great for overall resource c= ontrol but not for per-request, child-level recycling within FPM.=C2=A0
--0000000000001c5a06062d01e40c--