Mark Baker Posted October 14, 2009 Share Posted October 14, 2009 Can anybody explain why memory usage seems better when using shorter attribute names? I have the following test class: $loopCount = 1024 * 512; error_reporting(E_ALL); class testClass { public $veryLongAttributeName0 = NULL; public $veryLongAttributeName1 = NULL; public $veryLongAttributeName2 = NULL; public $veryLongAttributeName3 = NULL; public $veryLongAttributeName4 = NULL; public $veryLongAttributeName5 = NULL; public $veryLongAttributeName6 = NULL; public $veryLongAttributeName7 = NULL; public $veryLongAttributeName8 = NULL; public $veryLongAttributeName9 = NULL; function __construct($libraryType = null, $fileID = null) { } function _destructor() { } // function destructor } // class testClass $callStartTime = microtime(true); $testArray = array(); for ($i = 0; $i < $loopCount; ++$i) { $testArray[] = new testClass(); } $callEndTime = microtime(true); $callTime = $callEndTime - $callStartTime; echo '<br />Call time to instantiate '.$loopCount.' objects of testClass was '.sprintf('%.4f',$callTime)." seconds<br />\n"; echo date('H:i:s').' Peak memory usage: '.(memory_get_peak_usage(true) / 1024 / 1024).' MB<br />'; which produces the following result: Call time to instantiate 524288 objects of testClass was 3.4530 seconds 09:34:08 Peak memory usage: 494.75 MB If I simply change the attribute names public $veryLongAttributeName0 = NULL; public $veryLongAttributeName1 = NULL; public $veryLongAttributeName2 = NULL; public $veryLongAttributeName3 = NULL; public $veryLongAttributeName4 = NULL; public $veryLongAttributeName5 = NULL; public $veryLongAttributeName6 = NULL; public $veryLongAttributeName7 = NULL; public $veryLongAttributeName8 = NULL; public $veryLongAttributeName9 = NULL; to public $v0 = NULL; public $v1 = NULL; public $v2 = NULL; public $v3 = NULL; public $v4 = NULL; public $v5 = NULL; public $v6 = NULL; public $v7 = NULL; public $v8 = NULL; public $v9 = NULL; I get the following result: Call time to instantiate 524288 objects of testClass was 3.2260 seconds 09:37:46 Peak memory usage: 374.75 MB It appears to run fractionally faster (although that's harder to determine), but uses significantly less memory (494.75 MB reduced to 374.75 MB) That shouldn't be right... should it? Even in a semi-compiled language such as PHP, the memory usage (and possibly speed of execution) shouldn't be affected by the length of an attribute name. Link to comment https://forums.phpfreaks.com/topic/177641-solved-memory-usage-reduced-with-short-attribute-names/ Share on other sites More sharing options...
cags Posted October 14, 2009 Share Posted October 14, 2009 In a fully compiled language obviously there should be no difference at all since all the variable names are changed internally during the compile process. It would seem from your experiment that the 'on-the-fly' compiling as done by PHP is not perfect. Did you test the longname first followed by the shortname? Have you repeated the test multiple times and did you try performing it in the reverse order. As your creating over half a million objects we're talking about (assuming I did the maths right) 2 bytes per object, which is fairly negligable. Link to comment https://forums.phpfreaks.com/topic/177641-solved-memory-usage-reduced-with-short-attribute-names/#findComment-936696 Share on other sites More sharing options...
Mark Baker Posted October 14, 2009 Author Share Posted October 14, 2009 Did you test the longname first followed by the shortname? Have you repeated the test multiple times and did you try performing it in the reverse order.Several times on different versions of PHP, and different operating platforms. Each script has been run as a separate file, so they're not interfering with each other, or giving me a combined result. As your creating over half a million objects we're talking about (assuming I did the maths right) 2 bytes per object, which is fairly negligable. 494.75 MB - 374.75 MB = 120MB (interestingly the difference is only 100MB on Linux - RH ES4) 120MB / 524288 instances = 240 bytes per instance (approximate because I'm rounding memory_get_peak_usage() to MB) The difference in file length between the short and long variable name versions is 200 bytes Link to comment https://forums.phpfreaks.com/topic/177641-solved-memory-usage-reduced-with-short-attribute-names/#findComment-936712 Share on other sites More sharing options...
cags Posted October 14, 2009 Share Posted October 14, 2009 How on earth did I get 2 bytes, I did it on a calculator, yet I put the same formula in now and get 240 bytes I think my calculator is haunted. Oh well. Hmm.. your right, I tested it out myself. Call time to instantiate 524288 objects of testClass was 2.6321 seconds 13:43:15 Peak memory usage: 374.75 MB Call time to instantiate 524288 objects of testClass was 2.7372 seconds 13:43:59 Peak memory usage: 494.75 MB I guess the shortnames being quicker makes sense if it is consuming less space in memory because thats less writing going on. I tried a variable name with the length somewhere in the middle. The memory usage was roughly in the middle of the two results. It would seem that PHP does not optimise for class members in this way. Out of pure curiosity I tried messing about. I found it interesting that memory usage went up by nearly 40MB by changing the variables to private. I'm sure somebody with knowledge of some lower level languages could give a good reason for that, but I certainly didn't expect it. Link to comment https://forums.phpfreaks.com/topic/177641-solved-memory-usage-reduced-with-short-attribute-names/#findComment-936742 Share on other sites More sharing options...
Mark Baker Posted October 14, 2009 Author Share Posted October 14, 2009 I guess the shortnames being quicker makes sense if it is consuming less space in memory because thats less writing going on.I'd guessed that the slightly faster time was due to fewer calls to malloc because of the reduced memory requirement; but it's only a small difference and too susceptible to outside influences for this test to be a good measure. Out of pure curiosity I tried messing about. I found it interesting that memory usage went up by nearly 40MB by changing the variables to private. I'm sure somebody with knowledge of some lower level languages could give a good reason for that, but I certainly didn't expect it. Using short variable names for all three tests: With variables scoped as public: Call time to instantiate 524288 objects of testClass was 3.1972 seconds 17:00:35 Peak memory usage: 374.75 MB With variables scoped as protected: Call time to instantiate 524288 objects of testClass was 3.2360 seconds 17:00:16 Peak memory usage: 414.75 MB With variables scoped as private: Call time to instantiate 524288 objects of testClass was 3.3128 seconds 16:59:44 Peak memory usage: 454.75 MB The plot definitely thickens, and I am definitely intrigued Methinks I need to have a word with somebody from the PHP development team. Link to comment https://forums.phpfreaks.com/topic/177641-solved-memory-usage-reduced-with-short-attribute-names/#findComment-936823 Share on other sites More sharing options...
pastcow Posted October 14, 2009 Share Posted October 14, 2009 I believe (tho im not 100% certain so i'll check) that every single variable within a PHP script can be found within a "Symbol Table" (an internal array used by Zend). If your variable names are longer they take up more space in this table and so your script needs more memory to run. Link to comment https://forums.phpfreaks.com/topic/177641-solved-memory-usage-reduced-with-short-attribute-names/#findComment-936833 Share on other sites More sharing options...
Mark Baker Posted October 15, 2009 Author Share Posted October 15, 2009 Thanks to everybody that has provided help and advice on this problem. Based on the suggestions that have been given, I've come up with the following code using magic getters/setters: class testClass { private static $_propertyList = array( 'longVariableName0', 'longVariableName1', 'longVariableName2', 'longVariableName3', 'longVariableName4', 'longVariableName5', 'longVariableName6', 'longVariableName7', 'longVariableName8', 'longVariableName9' ); private $_data = array(); public function __set($name, $value) { $key = array_search($name,self::_propertyList); if ($key !== false) { $this->_data[$key] = $value; } } public function __get($name) { $key = array_search($name,self::_propertyList); if ($key !== false) { return $this->_data[$key]; } } function __construct() { } function _destructor() { } // function destructor } // class testClass Compared with my original script (running on the same server) Original script with long property/attribute names: Call time to instantiate 524288 objects of testClass was 3.1759 seconds 09:48:34 Peak memory usage: 494.75 MB Using magic getters/setters, which allows us to retain long property/attribute names Call time to instantiate 524288 objects of testClass was 1.8602 seconds 09:48:05 Peak memory usage: 150.75 MB That's an incredible gain, and we're really grateful to everybody on PHP Freaks and other forums who has helped us explain the cause of the problem, and provided us with a solution that not only gives us the ability to handle significantly larger volumes of data, but to do so with improved speed as well. We can apply this technique to many of the classes within the library, which should allow us to handle workbooks up to 3 times the size that we can now, without any changes being required by developers who are using the library. Link to comment https://forums.phpfreaks.com/topic/177641-solved-memory-usage-reduced-with-short-attribute-names/#findComment-937414 Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.