Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:106093 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 40138 invoked from network); 28 Jun 2019 19:33:05 -0000 Received: from unknown (HELO mail-io1-f54.google.com) (209.85.166.54) by pb1.pair.com with SMTP; 28 Jun 2019 19:33:05 -0000 Received: by mail-io1-f54.google.com with SMTP id e3so13847069ioc.12 for ; Fri, 28 Jun 2019 09:50:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=gtexwGfLaUIMKtszDqVeXwCcH+KKj7pqHG8Kz0oFE+I=; b=OqSx965FB+kcmZGi1QjDSl3zoUzttDxVOAmCvtndDuHz5jvtG83euerF9Ty72vzvBI MvaJT7qe/UB6O05GRPZUXeW3PhEvSvCujUF6Joi5QlRuW2KzS2+mraw/58WNtQ028ete KlAWvo60Xfr0AQZ/DhDDsFE0wFW3Uy/Tb9bvMb6NRwdjjwLFdoWKPJeGTlEuq2b5Rqhr IoNRweYatoKEp5Vruu2PrtT0y+Wyc2T11DOxzU0icIAhFTnCwWabwoo81vcT8El6mDOM GUQw/4pMYJIsA8pcMZKGLHC3GXQabo/uM2/cWGyhIQNwDe1rOcw+1sJvtz96zrbKzT/4 +jbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=gtexwGfLaUIMKtszDqVeXwCcH+KKj7pqHG8Kz0oFE+I=; b=cX7xT68btp6zwzPXvA1BVwFN8cDMeDvFkRGAN+EGEtGGbnpT5CGT06m+exc0dUHzs2 jvImHowH57S0i5vZIOeHmclKcoOxNWgdQb7GqeGkhnUi5+5FWhFz5IVFVmhVhdxMZyOp wcwYoD3L+JLTyhOLGdVQcPMOgrpjBpRRwkn/jD7/qu0AH3qegbV5sWEkdnk63x8V0Pri BQ0P4/A1I7HmyoJGfffRgSJlX6gaG0pzoMaXvWOLwF+4Sn4Q5PLLw5iMlv7eoyvdFTK1 ZIWO5t5W7tKLQ3Z2lqlv/fCdC9AYSJwYlPFc3MJvB59NN9IG1jqDbZlRAaX5CLCCYlLk 47TQ== X-Gm-Message-State: APjAAAW8s+DFkoV1UR4/0efcm+yOrHikgJwq3lf/SABMfQsWbuIC+jir kxQZE4ryYpvjGkyN1xmtA+I3A4Nzgb9Q2V3NGCdCPQNu+bg= X-Google-Smtp-Source: APXvYqwXOf3ROVldMZ6WBYfwE2TFuE4BEuDSXAtiHxvFvwcFlpdOpBmY1Ce8a42aQXXfCfZew4LtEfljJeIHclB3QyI= X-Received: by 2002:a05:6638:201:: with SMTP id e1mr12426854jaq.45.1561740601126; Fri, 28 Jun 2019 09:50:01 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 28 Jun 2019 18:49:49 +0200 Message-ID: To: =?UTF-8?Q?Johannes_Schl=C3=BCter?= Cc: PHP Internals Content-Type: multipart/alternative; boundary="000000000000c2f2f0058c651123" Subject: Re: [PHP-DEV] Memory leak in eval()'d code From: benjamin.morel@gmail.com (Benjamin Morel) --000000000000c2f2f0058c651123 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable > Theoretical it is thinkable we could either detect equal classes (but > unlikely to happen ... if it's the same why do it in eval, zthus cost > likely is higher than benefit in most cases?) Thanks for your reply. I do it in eval() because schema.org has many types (more than 600 at the moment), and each object ("Thing") can be an instance of one or more of these types. This creates an unmanageable number of possible combinations that I cannot pre-compute, so I need to dynamically create a definition for an object that implements an arbitrary number of interfaces. > or unload the class once > it's not needed anymore (which is hard to detect with reflection and > other mechanisms which aren't bound to an instance's zval and also not > cheap) AFAIK, unloading a class is not possible from userland, I guess you're talking about detecting this in PHP itself? Anyway, that's an edge case, I found a workaround which is to keep a cache of freshly created objects, indexed by interface name(s). Anytime I request a combination of types that's already been handled in the past, I return a clone of the cached object. Even though the possible combinations of types are huge and impossible to predict in advance, there are never more than a handful of such combinations used in a single document, and I'd be surprised if there are actually that many combinations actually used in the wild. So this should hardly be a problem. Thank you, Ben On Fri, 28 Jun 2019 at 17:59, Johannes Schl=C3=BCter wrote: > On Fri, 2019-06-28 at 02:41 +0200, Benjamin Morel wrote: > > Hi internals, > > > > I've tracked down a memory leak to an anonymous class created within > > eval(): > > > > ``` > > for ($i =3D 0; $i < 1000000; $i++) { > > $object =3D eval('return new class {};'); > > > > if ($i % 1000 =3D=3D 0) { > > echo memory_get_usage() . "\n"; > > } > > } > > > > ``` > > > > The memory usage quickly ramps up and memory_limit is reached in > > seconds. > > Without eval(), the memory usage stays flat. I'm on 7.3.6. > > > > *Is this a bug?* Or is this some inherent limitation of eval() that > > cannot > > be fixed? > > I case this is non-trivial to fix. Each invocation recompile a new > piece of code, which creates a new class. > > Similar to > > for ($i =3D 0; $i < 1000000; $i++) { > eval("function f$i(){}"); > } > f1(); > f2(); > ... > > or > > for ($i =3D 0; $i < 1000000; $i++) { > file_put_contents("c$i.php", 'return new class {};'); > $object =3D include "c$i.php"; > } > > Theoretical it is thinkable we could either detect equal classes (but > unlikely to happen ... if it's the same why do it in eval, zthus cost > likely is higher than benefit in most cases?) or unload the class once > it's not needed anymore (which is hard to detect with reflection and > other mechanisms which aren't bound to an instance's zval and also not > cheap) > > johannes > > --000000000000c2f2f0058c651123--