Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:67706 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 73640 invoked from network); 14 Jun 2013 18:04:20 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 14 Jun 2013 18:04:20 -0000 Authentication-Results: pb1.pair.com smtp.mail=ircmaxell@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=ircmaxell@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.212.52 as permitted sender) X-PHP-List-Original-Sender: ircmaxell@gmail.com X-Host-Fingerprint: 209.85.212.52 mail-vb0-f52.google.com Received: from [209.85.212.52] ([209.85.212.52:36869] helo=mail-vb0-f52.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id FD/9A-32590-22B5BB15 for ; Fri, 14 Jun 2013 14:04:19 -0400 Received: by mail-vb0-f52.google.com with SMTP id f12so654219vbg.39 for ; Fri, 14 Jun 2013 11:04:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type; bh=23zkxtwbLh67S69D8cCl7IJravZ5CikTIPEDQIbrjuk=; b=QgwUU5A+rJ6x6SlsmQEMskTjqAVxcjvAD52ZPcceB9AhCTZP3fgujRNaTun9vmlIhz oc9emL5q0g23DLUpV8e9s51x3TA/nm6rjpygaYaxyHOI43aSZ3bYO7aoz/QBIgJFeeJN LDU13vckhJfPCzWOQnb2LttvmMu/g1OrTUXxTvcGLp9cf7pZGj8V020JuurhBGsddMjo w0ZvQXBOhuL46HcpStVBvfIXjsDINg/84R1AGJVOCpFZfeMWQjVWyqrg5cBRFAmJf6gk EWmGys/Wxew94gTCfCbHsU3U/8Vjs3Z2aNkWzbAfxG+R2fIpSuoPhZP9YNb0rx5wew78 0MhA== MIME-Version: 1.0 X-Received: by 10.58.22.74 with SMTP id b10mr1319113vef.47.1371233056312; Fri, 14 Jun 2013 11:04:16 -0700 (PDT) Received: by 10.58.199.76 with HTTP; Fri, 14 Jun 2013 11:04:16 -0700 (PDT) Date: Fri, 14 Jun 2013 14:04:16 -0400 Message-ID: To: "internals@lists.php.net" Content-Type: multipart/alternative; boundary=089e013c69e639d3d204df211308 Subject: Zend GC Recursion Elimination From: ircmaxell@gmail.com (Anthony Ferrara) --089e013c69e639d3d204df211308 Content-Type: text/plain; charset=ISO-8859-1 Hey all, I was debugging a "bug" (quotes because of the extreme edge-case) where certain cases can cause a stackoverflow internally in the GC when dealing with extremely deep arrays. For example: this code is not an infinite loop, but it's so practically big that it's basically an infinite loop for our purposes. $a = array(&$a); function fill (&$a, $i = 3) { if (!$i--) return; foreach ($a as &$tmp) { $tmp = array($tmp, &$a); fill($tmp, $i); } } fill($a); When you run that on current master, you get a segfault stemming from the zval_mark_grey() GC function. This may or may not be "desired" (as you're basically creating a structure too big to be garbage collected). However, I started playing around with zval_mark_gray (and the 3 other functions similarly constructed) and tried re-writing them in a non-recursive manner. Basically, I'm using a time-memory tradeoff here. By caching the pointers instead of recursing, I trade a little bit of memory (defaults to blocks of 256*sizeof(**zval)) for decreased recursion (and hence significantly less stack usage). This tradeoff is a significant win on all fronts for deep arrays (since it only uses sizeof(**zval) per entry, as opposed to a full stack frame), but can be a memory loss for wide arrays... Here's my branch with the changes: https://github.com/ircmaxell/php-src/compare/zval_mark_grey_tail_recursion So I decided to clean up the changes, and start benchmarking it. To my surprise, the results were fairly significant. First, I modified the script from above to instead have a counter to kill the script after 200k function calls (fits into about 120mb of memory). Then, I wrote a benchmark script to execute bench.php and micro_bench.php multiple times (10 to be exact), and then put out the min, max and average for each test under this modified version, and stock master. Then it computed the difference in percentage. I'll link to the gist of the full results, but here are the 3 summaries (Total): Full: Total Core: 2.094 - 2.1429 - 2.278 Modified: 2.089 - 2.1323 - 2.208 Diff: 0.23878% - 0.46532% - 3.07287 Micro: Total Core: 9.309 - 9.4995 - 9.878 Modified: 8.62 - 8.8179 - 9.234 Diff: 7.40144% - 6.90018% - 6.51954 GC Core: 0.5937340259552 - 0.60687265396118 - 0.62824201583862 Modified: 0.43920111656189 - 0.44599950313568 - 0.47265577316284 Diff: 26.02730% - 25.60688% - 24.76534 As you can see, that's not a shabby gain in the micro bench (average of 10 runs is a 6.9% gain), and pretty much a gain all around (on average). Here's the full results (including test scripts, etc): https://gist.github.com/ircmaxell/5782139 Also note that PHP was compiled in both cases with: ./configure --disable-all --enable-cli --disable-cgi I also ran a few tests against the Symfony2 framework (stock testcase), and it pretty much showed a 1 to 3 second improvement over stock (for a 150 second test). So not a huge win overall, but can be significant in cases... What do you think? Is this worth pursuing further? is there a case I'm missing, or some other reason we shouldn't do this? Thanks, Anthony --089e013c69e639d3d204df211308--