PHP performs garbage collection at three primary junctures:
When you tell it to
When you leave a function
When the script ends
Situation 1 occurs when you use unset(), mysql_free_result(), or other resource-destroying functions that explicitly clear up after your variables. Situation 2 clears up resources implicitly - any variable that leaves scope, i.e. is no longer applicable, gets cleared up for you. Finally, situation 3 frees up all script-related resources implicitly.
It is important to understand that situations 2 and 3 both use the same code path as situation 1 - that is, if you free up a resource using unset() or another resource-destroying function, it will take as much time to do as if PHP had to destroy the resource at the end of the script. This might sound like a rather mundane and, quite frankly, obvious thing to say, however it has profound implications because it means there is little reason to rely on PHP for garbage collection unless you are lazy!
Now, of course that is not quite true - unless you are really strapped for resources, there is little point calling unset() on each of your variables when you are done with them, and similarly there is little point in explicitly cleaning up after a resource just before the script is about to end, as it is going to happen anyway without the need to clog up your script. However, if there is any sizeable delay between you finishing using a big resource, and the juncture at which automatic garbage collection will take place (usually script end, but might also be function end), then you should clean up after yourself and claim the resource back.