Hi!

Yes, I expected the two functions - tsrm_new_interpreter() and
init_executor() to do that, as it is the function called in
php_request_startup() in main/main.c

As far as I remember, you need to run the whole request startup for the the thread, otherwise there will be unitilialized pieces. TSRM magic will create needed per-thread structures and call ctors, but ctors usually just null out stuff, you'd still need to fill it in.

Another possible application would be a parallel_include() type call,
which would call a given PHP file for each member of an array (or a PDO
result set), buffering the output from each, and inserting into the
output stream in sequence once each fragment is done (hopefully
interacting well with normal output buffering, if you didn't want the
results sent yet).  This would allow a large number of results to be
rendered in parallel on multicore systems.

That's what webservers do already, don't they? :)

I hope it will be possible to share already compiled code between
threads; this may mean disabling "eval" inside the thread or otherwise

The main problems you will be facing are the following:

1. All ZE structures are per-thread. This means using one thread's structures in another will be non-trivial task, as all code assumes that current thread's structures are used.

2. Even if you manage to hack around it by always passing the tsrm_ls pointers, etc. - memory managers are per-thread too. Which means you will be using data in one thread that is controlled by MM residing in another thread. Without locking.

3. You may think this is not very bad, since you'll be using stuff that's quite static, like classes and functions - they don't get deallocated inside request, so who cares which MM uses them? However, while classes themselves don't, structures containing them - hashtables - can change, be rebuilt, etc. and if it happens in a wrong moment, you're in trouble.

4. Next problem with using classes/functions is that they can contain variables - zvals, as default properties, static variables, etc. Since ZF is refcounting, these zvals may be modified by anybody who uses these variables - even just for reading. Again, no locking. Which, again, means trouble.

5. Then come resources and module globals. Imagine some function touches in some way some resource - connection, file, etc. - that another thread is using at the same time, without locking? Modules generally assume resources belong to their respective threads, so you'll need to run module initializations for each thread separately.

hobbling the compiler to avoid separate threads trying to modify the
optree at once.  If a shared optree cannot be achieved, then I guess it
would have to go back to the APC, but it would be good to avoid
overheads where possible to keep the thread startup cost low.

Because of the things described above, it will be very challenging to avoid those startup costs.

Even extremely restricted parallelism can help speed up some types of
work, so limitations I am happy to accept.

If you restrict it to using only copied data and never running any PHP code, it might work. Alternatively, you might launch independent engine instances that don't share structures and have them communicate, like Erlang does. Though, unlike Erlang, PHP engine would not help you much in this, I'm afraid.

--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to