Page 1 of 1

Can someone explain this Xdebug trace info?

Posted: Thu Feb 22, 2007 7:04 am
by Chris Corbyn
I'm currently refactoring and optimizing my (complete) codebase. I am using Xdebug to profile my code and check memory usage etc.

I am quite confused by one point however. In PHP, how much memory should a "class", uninstantiated, actually use?

I've got a trace like this:

Code: Select all

TRACE START [2007-02-22 12:36:22]
    0.0008      43808     -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/tests/TestConfiguration.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/tests/benchmarks/mem_sending_with_swift.php:10
    0.0029     178520     -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/tests/benchmarks/mem_sending_with_swift.php:15
    0.0029     178536       -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:13
    0.0031     189368       -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/ConnectionBase.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:14
    0.0032     189368         -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/ConnectionBase.php:12
The second column shows memory used in bytes at this point in the script. Now, all the code is doing up to this point is including files which contain nothing more than classes. I've created no objects as yet...

Why is the memory going up so steeply here? I don't seem to be able to optimize it much neither. I tried reducing the number of calls to dirname(__FILE__) by assinging it to a variable but it has made little difference so I can only conclude that classes, even without instantiating them use a shed load of memory?? I get up to almost 1MB before I even instantiate anything. WTF?

Can anyone shed some light on this?

Code: Select all

TRACE START [2007-02-22 12:36:22]
    0.0008      43808     -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/tests/TestConfiguration.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/tests/benchmarks/mem_sending_with_swift.php:10
    0.0029     178520     -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/tests/benchmarks/mem_sending_with_swift.php:15
    0.0029     178536       -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:13
    0.0031     189368       -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/ConnectionBase.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:14
    0.0032     189368         -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/ConnectionBase.php:12
    0.0034     199240         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Connection.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/ConnectionBase.php:13
    0.0035     203040         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Connection/Exception.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/ConnectionBase.php:14
    0.0066     388648       -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:15
    0.0067     388648         -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message.php:14
    0.0070     402176         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Address.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message.php:15
    0.0070     402176           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Address.php:12
    0.0071     403640           -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/AddressContainer.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Address.php:12
    0.0086     490520         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Mime.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message.php:16
    0.0086     490520           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Mime.php:12
    0.0104     595904           -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Headers.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Mime.php:13
    0.0104     595904             -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Headers.php:12
    0.0117     672912             -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Encoder.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Headers.php:13
    0.0117     672912               -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Encoder.php:12
    0.0123     707632               -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/File.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Encoder.php:12
    0.0123     707632                 -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/File.php:12
    0.0125     713224                 -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/FileNameMaker.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/File.php:12
    0.0125     712776                 -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/File.php:13
    0.0127     716640                 -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/FileException.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/File.php:13
    0.0128     717248             -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/MimeException.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Headers.php:14
    0.0133     744792           -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Part.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Mime.php:14
    0.0133     744808             -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Part.php:12
    0.0141     777112           -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Attachment.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Mime.php:15
    0.0141     777216             -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Attachment.php:12
    0.0144     780416           -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Boundary.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Mime.php:20
    0.0148     794928         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/EmbeddedFile.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message.php:19
    0.0148     795032           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/EmbeddedFile.php:12
    0.0151     813904         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Image.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message.php:20
    0.0151     813920           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Message/Image.php:12
    0.0158     844864       -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/RecipientList.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:17
    0.0158     844880         -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/RecipientList.php:12
    0.0159     844880         -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/RecipientList.php:13
    0.0161     851896       -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Log.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:18
    0.0163     860160       -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Log/DefaultLog.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:19
    0.0163     860160         -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Log/DefaultLog.php:12
    0.0166     871872         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Log/Base.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Log/DefaultLog.php:12
    0.0166     871872           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Log/Base.php:12
    0.0169     876160       -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/ListenerMapper.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:20
    0.0169     875624       -> Swift::loadEvents() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:23
    0.0170     875688         -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:120
    0.0170     875752         -> glob() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:120
    0.0172     882328         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/BeforeCommandListener.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:122
    0.0172     882440           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/BeforeCommandListener.php:12
    0.0173     883768           -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/Listener.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/BeforeCommandListener.php:12
    0.0174     883416           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/BeforeCommandListener.php:13
    0.0176     892736           -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/CommandEvent.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/BeforeCommandListener.php:13
    0.0176     892824             -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/CommandEvent.php:12
    0.0178     896368             -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/CommandEvent.php:12
    0.0180     897000         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/BeforeSendListener.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:122
    0.0180     897088           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/BeforeSendListener.php:12
    0.0180     897088           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/BeforeSendListener.php:13
    0.0183     907848           -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/SendEvent.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/BeforeSendListener.php:13
    0.0183     907848             -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/SendEvent.php:12
    0.0185     908984         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/CommandListener.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:122
    0.0185     909072           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/CommandListener.php:12
    0.0186     909072           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/CommandListener.php:13
    0.0188     911720         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/ConnectEvent.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:122
    0.0188     911808           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/ConnectEvent.php:12
    0.0189     914896         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/ConnectListener.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:122
    0.0190     914984           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/ConnectListener.php:12
    0.0190     914984           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/ConnectListener.php:13
    0.0192     917576         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/DisconnectEvent.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:122
    0.0192     917664           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/DisconnectEvent.php:12
    0.0194     920776         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/DisconnectListener.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:122
    0.0194     920864           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/DisconnectListener.php:12
    0.0194     920944           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/DisconnectListener.php:13
    0.0197     928168         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/ResponseEvent.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:122
    0.0197     928256           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/ResponseEvent.php:12
    0.0199     931360         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/ResponseListener.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:122
    0.0199     931448           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/ResponseListener.php:12
    0.0200     931448           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/ResponseListener.php:13
    0.0201     933464         -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/SendListener.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift.php:122
    0.0202     933552           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/SendListener.php:12
    0.0202     933552           -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Events/SendListener.php:13
    0.0214     995456     -> require_once(/home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Connection/SMTP.php) /home/d11wtq/public_html/swiftmailer/trunk/php5/tests/benchmarks/mem_sending_with_swift.php:20
    0.0214     995456       -> dirname() /home/d11wtq/public_html/swiftmailer/trunk/php5/lib/Swift/Connection/SMTP.php:11
Ok, so there's a lot of includes, but still... wtf?

EDIT | If it helps, each file calls require_once for it's own dependencies, even if a parent file may have already included that file. Should that even matter? I'm wondering if because I have a file required, which in turn requires files, which requires files, which requires files.... etc etc, this could be doing something psychotic.

Posted: Thu Feb 22, 2007 7:50 am
by Begby
I haven't used XDebug and I am not sure how much memory a class should take. If a file gets required though it gets parsed or cached so that is probably why its taking up so much RAM, it appears you are including a lot of files.

You may want to look into implementing __autoload or setting up some sort of namespaces class or loadclass functionality to include files only when needed.

Any directory scans or calls to the files system are also costly, but I don't see why that would take up so much RAM. Why are you doing so many calls to dirname()?

Posted: Thu Feb 22, 2007 7:59 am
by Chris Corbyn
Begby wrote:I haven't used XDebug and I am not sure how much memory a class should take. If a file gets required though it gets parsed or cached so that is probably why its taking up so much RAM, it appears you are including a lot of files.

You may want to look into implementing __autoload or setting up some sort of namespaces class or loadclass functionality to include files only when needed.

Any directory scans or calls to the files system are also costly, but I don't see why that would take up so much RAM. Why are you doing so many calls to dirname()?
I'm trying to cut down on calls to dirname(). It's a library for public download and it's refactored into lots of classes - hence the number of files. I can't really use autoload because I'd have to override any existing autoloader in the end-user's code... and it's not possible to convert to PHP4. I know spl_autoload_register() is available, but then not everyone has SPL. Hmmf.

I'll implement a service locator (luckily I use PEAR naming so it won't be too tricky) and see if it helps much. I was quite surprised how much memory has been used just by including all the files 8O

Ahh, there's another reason the (read, some) files need to be included up-front. The instanceof operator is needed rather than is_a() in E_STRICT mode, but to use instanceof, the class needs to be declared first. Same problem with type-checking.

Posted: Thu Feb 22, 2007 8:03 am
by Begby
Well if its named well then you don't have much work to do then. You can just create a method kind of like the Zend::loadClass(). You would need to stick it all over in your code, but it would certainly make your script run better. Maybe have a class with two methods


IncludeThingy::SetAppRoot('/home/my/site/root') ;
IncludeThingy::LoadClass('my_class_name') ;


You could call SetAppRoot() from your main include file, do dirname(__FILE__) and store that in the IncludeThingy, then you can include all your files with absolute paths.

Posted: Thu Feb 22, 2007 8:15 am
by Chris Corbyn
Surely a class-loader would be a simple class of:

Code: Select all

Swift_ClassLoader::load("Swift_Message");
$message = new Swift_Message(...);
And all the implementation requires is that Swift_ClassLoader know's the path to itself relative to the other PEAR-named classes then:

Code: Select all

class Swift_ClassLoader
{
    public static function load($name)
    {
        if (!class_exists($name) && !interface_exists($name))
        {
            require_once "../" . str_replace("_", "/", $name) . ".php";
        }
    }
}
But then, if you do that *every* time you're about to instantiate the class, the calls to class_exists() and interface_exists() will become expensive.

Posted: Thu Feb 22, 2007 8:38 am
by Chris Corbyn
8O Wow, this is quite astonishing. I'll post some new Xdebug results soon... basically, because I'm now spreading the loading of the classes throughout the code base rather than doing it all in one shot, the memory doesn't peak so much. It's actually quite drastic!

Posted: Thu Feb 22, 2007 8:55 am
by Begby
d11wtq wrote: But then, if you do that *every* time you're about to instantiate the class, the calls to class_exists() and interface_exists() will become expensive.

There are two ways you can handle this.

A. Create a registry array of classes you have already loaded, just look in the array to see if its in there, if not then call require_once.

B. Just call require_once every time and let PHP sort it out. I think require_once is pretty efficient as it keeps a cache of files it already included and won't do any system calls or file scans if its called twice for the same file, but I could be mistaken.

C. If you need to use class_exists or interface_exists, then split it into two methods, LoadClass() and LoadInterface(), that will cut the expense in half.

Posted: Thu Feb 22, 2007 8:58 am
by Begby
Oh yeah, don't do str_replace('_', '/', $class), use str_replace('_', DIRECTORY_SEPARATOR, $class). That will assure it works without snafus on windows. You might need do a version check though and define the separator constant manually depending on how backwards compatible your app is.

Posted: Thu Feb 22, 2007 9:02 am
by Chris Corbyn
"/" and "\\" both work in windows ;)

I have come to the conclusion that the lesser memory being used while I go through my code using my just-in-time classloader is due to the fact PHP has chance to perform some garbage collection.