Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:46728 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 16781 invoked from network); 14 Jan 2010 03:18:53 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 14 Jan 2010 03:18:53 -0000 Authentication-Results: pb1.pair.com header.from=tstarling@wikimedia.org; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=tstarling@wikimedia.org; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain wikimedia.org from 66.111.4.26 cause and error) X-PHP-List-Original-Sender: tstarling@wikimedia.org X-Host-Fingerprint: 66.111.4.26 out2.smtp.messagingengine.com Received: from [66.111.4.26] ([66.111.4.26:39994] helo=out2.smtp.messagingengine.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 2E/B0-00773-C1D8E4B4 for ; Wed, 13 Jan 2010 22:18:53 -0500 Received: from compute1.internal (compute1.internal [10.202.2.41]) by gateway1.messagingengine.com (Postfix) with ESMTP id E6D4CCD92E; Wed, 13 Jan 2010 22:18:49 -0500 (EST) Received: from heartbeat1.messagingengine.com ([10.202.2.160]) by compute1.internal (MEProxy); Wed, 13 Jan 2010 22:18:50 -0500 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=messagingengine.com; h=message-id:date:from:mime-version:to:cc:subject:references:in-reply-to:content-type:content-transfer-encoding; s=smtpout; bh=eUwGkT6y4uJ9qoFoJDC3hrtZfEY=; b=B9D1x20dfPQEsAFeJ7NFHq/3+ZXwwnOhmPZq4qng+5BM2b5fsjixI8ZqFslW1CSAev2CQAgT3ZYFe3rGmWZ47DcHrsniOgpYp2/GXaH3Pl5MUkT9TkMWadbupOSaZH3ifqHmiOksu66lXXCnGsHJF1Ec9YOkkcBMSPz6Jrtgv8M= X-Sasl-enc: ZEpPyy1rpWUQa8hjum6YhS/jN/eLHiaAK39dmPUCL/T6 1263439129 Received: from [10.0.0.2] (CPE-124-176-96-118.lns3.ken.bigpond.net.au [124.176.96.118]) by mail.messagingengine.com (Postfix) with ESMTPSA id E09C44AEFE9; Wed, 13 Jan 2010 22:18:48 -0500 (EST) Message-ID: <4B4E8D15.60508@wikimedia.org> Date: Thu, 14 Jan 2010 14:18:45 +1100 User-Agent: Thunderbird 2.0.0.23 (X11/20090817) MIME-Version: 1.0 To: Stanislav Malyshev CC: internals@lists.php.net References: <4B4DABED.4060202@easyflirt.com> <4B4DBF40.5040801@easyflirt.com> <4B4DCFDA.6090206@dmi.me.uk> <4B4DF01A.1080103@wikimedia.org> <4B4DFBDE.1020906@lerdorf.com> <4B4E5943.3000706@wikimedia.org> <4B4E5D5B.9020805@zend.com> <4B4E6BE5.1070404@wikimedia.org> <4B4E79A6.2010904@zend.com> In-Reply-To: <4B4E79A6.2010904@zend.com> X-Enigmail-Version: 0.95.7 OpenPGP: id=BF976370 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] About optimization From: tstarling@wikimedia.org (Tim Starling) Stanislav Malyshev wrote: > > opcodes can be cached (bytecode caches do it) but op_array can't > really be cached between requests because it contains dynamic > structures. Unlike Java, PHP does full cleanup after each request, > which means no preserving dynamic data. APC deep-copies the whole zend_op_array, see apc_copy_op_array() in apc_compile.c. It does it using an impressive pile of hacks which break with every major release and in some minor releases too. Every time the compiler allocates memory, there has to be a matching shared memory allocation in APC. But maybe you missed my point. I'm talking about a cache which is cheap to construct and cleared at the end of each request. It would optimise tight loops of calls to user-defined functions. The dynamic data, like static variable hashtables, would be in it. The compact pointerless structure could be stored between requests, and would not contain dynamic data. Basically a structure like the current zend_op_array would be created on demand by the executor instead of in advance by the compiler. > > I'm not sure how using pointers in op_array in such manner would help > though - you'd still need to store things like function names, for > example, and since you need to store it somewhere, you'd also have > some pointer to this place. You can do it with a length field and a char[1] at the end of the structure. When you allocate memory for the structure, you add some on for the string. Then you copy the string into the char[1], overflowing it. If you need several strings, then you can have several byte offsets, which are added to the start of the char[1] to find the location of the string in question. You can make the offset fields small, say 16 bits. But it's mostly zend_op I'm interested in rather than zend_op_array. Currently if a zend_op has a string literal argument, you'd make a zval for it and copy it into op1.u.constant. But the zval allocation could be avoided. The handler could cast the zend_op to a zend_op_with_a_string, which would have a length field and an overflowed char[1] at the end for the string argument. A variable op size would make iterating through zend_op_array.opcodes would be slightly more awkward, something like: for (; op < oparray_end; op = (zend_op*)((char*)op + op->size)) { ... But obviously you could clean that up with a macro. For Mr. "everyone has 8GB of memory and tiny little data sets" Lerdorf, I could point out that reducing the average zend_op size and placing strings close to other op data will also make execution faster, due to the improved CPU cache hit rate. -- Tim Starling