Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:51158 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 30527 invoked from network); 31 Dec 2010 15:00:49 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 31 Dec 2010 15:00:49 -0000 Received: from [127.0.0.1] ([127.0.0.1:27894]) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ECSTREAM id 49/85-01063-120FD1D4 for ; Fri, 31 Dec 2010 10:00:49 -0500 Authentication-Results: pb1.pair.com smtp.mail=marcin.babij@nasza-klasa.pl; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=marcin.babij@nasza-klasa.pl; sender-id=pass Received-SPF: pass (pb1.pair.com: domain nasza-klasa.pl designates 209.85.215.170 as permitted sender) X-PHP-List-Original-Sender: marcin.babij@nasza-klasa.pl X-Host-Fingerprint: 209.85.215.170 mail-ey0-f170.google.com Received: from [209.85.215.170] ([209.85.215.170:49644] helo=mail-ey0-f170.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id D5/94-01063-0CBED1D4 for ; Fri, 31 Dec 2010 09:42:09 -0500 Received: by eyf5 with SMTP id 5so4797902eyf.29 for ; Fri, 31 Dec 2010 06:42:05 -0800 (PST) Received: by 10.213.33.143 with SMTP id h15mr1692596ebd.95.1293806525215; Fri, 31 Dec 2010 06:42:05 -0800 (PST) Received: from pc-mbabij (static.nk-net.pl [195.88.186.3]) by mx.google.com with ESMTPS id u1sm12335807eeh.4.2010.12.31.06.42.03 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 31 Dec 2010 06:42:04 -0800 (PST) Content-Type: multipart/mixed; boundary=----------AdzWaHMPXLZlDP0rcPH6K1 Date: Fri, 31 Dec 2010 15:40:44 +0100 To: internals@lists.php.net MIME-Version: 1.0 Organization: Nasza Klasa Message-ID: User-Agent: Opera Mail/11.00 (Win32) Subject: Zend engine's hashtable performance tweaks From: marcin.babij@nasza-klasa.pl ("Marcin Babij") ------------AdzWaHMPXLZlDP0rcPH6K1 Content-Type: text/plain; charset=utf-8; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Hello, I work for social network company, where we were running optimization project. One of it's results is patch to Zend engine's Hashtable, which we want to share and ask you for comments and improvements. Why we do this? We run profiling on our production servers and found out that zend_hash_* functions take 10-20% CPU time of request. So there is some room for easy improvements. What was done? - Hash function in zend_hash.h was rebuilt and became much faster, without losing the most important properties. - Hashtable implementation was changed from Simple chaining to Open addressing with linear probing, but with linked bucket, not included in hash array, which causes: -- Bucket structure to lose 2 pointers. -- Searching works similar, but don't have to jump with pointers stored in different memory locations, inserting, deleting and rehashing don't need to update linked list, but must search for first empty bucket, which is fast, because it scans continuous memory. -- Load factor decreases from 1.0 to 0.5-0.75 to make less collisions and faster hashtable, which in turn increases memory footprint a little. - Open addressing doesn't change significantly performance, but next thing was to create new array (arEmpty), which is of size nTableSize bytes, which keeps track of used/empty buckets and makes inserting and rehashing much faster. In future it can be tested as bit-array with size of nTableSize/8 bytes. - More macros were added to replace repetitive constructs. - New constants were added to allow: -- Creating new hashtables of size at least X (where 4 and 8 are reasonable), which makes no rehashing and reallocing memory while changing size to 2 and then to 4. -- For small tables it's better to extend them by a factor of 4 times, not 2, to make rehashing cost smaller for most hashtables, of cost of little higher memory consumption. -- For large tables it's better to have other load factor, closer to 1, while for small tables it's better to use load factor closer to 0.5. - APC was patched to take changes in Bucket structure into account. How was it tested? It was tested with make test, where one more (comparing to original sources) test fails, but it's most probably because http://bugs.php.net/bug.php?id=48858 - IMO test is badly constructed (is too simple) and any change of hashing function makes it fail. Also it was tested on our testing environment and production servers against >30mln requests to our site, with 120requests/s at peak on Xeon @ 2.50GHz with 8GB RAM running Debian Linux. What is the gain? After tests CPU usage dropped by about 4% -6%. Memory footprint goes up just by few percent. What can be done in future? - Make new constants configurable by php.ini. - Test if changing arEmpty from byte-array to bit-array helps on performance. - Tweak default constants' values using some real-live benchmarks. - Prove (or modify and prove) hash function to have property, that it has no collisions if two keys don't differ on no more than 6 bytes, which will lead to memcmp omit first (or last) 6 bytes of key. Also simpler thing may be proven, that is it has no collisions if two keys are not longer than 6 bytes, which will make most string keys omit memcpy at all. The patch was created and tested against php-5.3.0, apc-3.1.3p1, then merged with php-5.3.4, apc-3.1.6 without conflicts, and for these last versions patches are attached. Also, it shouldn't conflict with http://wiki.php.net/rfc/performanceimprovements . -- Marcin Babij nasza-klasa.pl ------------AdzWaHMPXLZlDP0rcPH6K1--