Re: ZTS performance

php.internals

Wojtek Meler

23 years ago
> ZTS is *always* going to be slower than non ZTS.
Yes, but it can be faster than it is. PHP doesn't use almost any shared resources (compiled regexs?) so why it is so slow ? Thread-safe syscalls ? I don't think so.
> There's no need for rewriting TSRM, it's roughly as fast as it can be.
Things changes ... Now we have AD2003 and __thread keyword in gcc. I suppose that if we use it we could get rid of all this TSRMLS*. I know - PHP is not for linux only - but we could have it in TSRM implementation. I'm sure that compiler will optimize it better if __thread keyword will be used instead of TSRMLS*. Regards, Wojtek

Andi Gutmans

23 years ago
At 10:20 PM 3/24/2003 +0100, wmeler@wp-sa.pl wrote:
> > ZTS is *always* going to be slower than non ZTS. > >Yes, but it can be faster than it is. PHP doesn't use almost any shared >resources (compiled regexs?) so why it is so slow ? Thread-safe syscalls >? I don't think so.
Hmm, not worth arguing with you if you're so sure you know how PHP doesn't need any per-thread resources. It does...
> > There's no need for rewriting TSRM, it's roughly as fast as it can be. > >Things changes ... >Now we have AD2003 and __thread keyword in gcc. I suppose that if we use >it we could get rid of all this TSRMLS*. I know - PHP is not for linux >only - but we could have it in TSRM implementation. >I'm sure that compiler will optimize it better if __thread keyword will >be used instead of TSRMLS*.
I'm not sure how __thread works but the TSRM implementation already uses thread local storage to cache the per-thread objects. Not sure __thread doesn't do the same. Andi

Wojtek Meler

23 years ago
On Mon, Mar 24, 2003 at 11:25:47PM +0200, Andi Gutmans wrote:
> At 10:20 PM 3/24/2003 +0100, wmeler@wp-sa.pl wrote: > > > ZTS is *always* going to be slower than non ZTS. > > > >Yes, but it can be faster than it is. PHP doesn't use almost any shared > >resources (compiled regexs?) so why it is so slow ? Thread-safe syscalls > >? I don't think so. > > Hmm, not worth arguing with you if you're so sure you know how PHP doesn't > need any per-thread resources. It does...
You didn't understand me (my english isn't perfect and there are lacks in vocabulary). PHP uses almost only per-thread resources - global, but only for thread resources. It doesn't use process-global resources (I found only compiled regex cache) so it doesn't need to synchronize on them. There are no lock-contention problems in PHP.
> I'm not sure how __thread works but the TSRM implementation already uses > thread local storage to cache the per-thread objects. Not sure __thread > doesn't do the same.
as Sascha said - NPTL is the future for multi-threaded applications - I think there is a need for review of TSRM. Regards, Wojtek

Zeev Suraski

23 years ago
At 00:12 25/03/2003, Wojtek Meler wrote:
>as Sascha said - NPTL is the future for multi-threaded applications - I think >there is a need for review of TSRM.
If you read what Sascha said you can see that when NPTL is ready, we'll be taking advantage of it automatically. It's an implementation of POSIX threads, that's all. Be advised that TSRM was written initially around Windows, which has had a very efficient thread safety API for years. There's really nothing new about NPTL or __thread, equivalents of which were available under Windows for years. There's really no need for review of TSRM, as it was written taking all of this into account. If you feel the urge to review it, though, go ahead - I see no reason and have no intention to do it :) Zeev

Zeev Suraski

23 years ago
At 13:20 24/03/2003, wmeler@wp-sa.pl wrote:
> > ZTS is *always* going to be slower than non ZTS. > >Yes, but it can be faster than it is. PHP doesn't use almost any shared >resources (compiled regexs?) so why it is so slow ?
It uses lots of globals. These aren't shared resources, but they're resources that in ZTS mode, take more time to access than they do in non-ZTS mode. I mentioned the issues involved with this in my previous email.
> Thread-safe syscalls >? I don't think so.
That's one of the reasons, I would guess. The libc memory manager is not very efficient with multiple threads accessing it at once, it has locks (which is one of the reasons we implemented our own in ZE2). It's definitely one of the reasons, and as you know, performance penalties accumulate.
> > There's no need for rewriting TSRM, it's roughly as fast as it can be. > >Things changes ... >Now we have AD2003 and __thread keyword in gcc. I suppose that if we use >it we could get rid of all this TSRMLS*. I know - PHP is not for linux >only - but we could have it in TSRM implementation.
If __thread is any similar to Tls under Windows (which would be my guess), then we can't use it directly. We're already using pthread_setspecific so we're extremely quick with fetches as it is. As I said, I also doubt very much that our performance penalty is solely due to fetches, but mostly based on other issues, which __thread will not alter in any way. You're more than encouraged to try and implement a __thread based solution in place of the pthread_setspecific solution and see if it makes any difference. If it does, we can investigate further in that direction and see if it's usable.
>I'm sure that compiler will optimize it better if __thread keyword will >be used instead of TSRMLS*.
Probably not much more than pthread_setspecific. I wouldn't be surprised if __thread is built around that, actually. Zeev

Sascha Schumann

23 years ago
> That's one of the reasons, I would guess. The libc memory manager is not > very efficient with multiple threads accessing it at once, it has locks > (which is one of the reasons we implemented our own in ZE2). It's > definitely one of the reasons, and as you know, performance penalties > accumulate.
Which libc are you referring to here?
> Probably not much more than pthread_setspecific. I wouldn't be surprised > if __thread is built around that, actually.
On Linux, there will be a huge win regarding TLS when NPTL[1] becomes stable enough. Today's Linuxthreads implementation uses a very simple mechanism to maintain TLS (calculating an object's address in software) whereas NPTL will shift this work to the processor's MMU. I expect a big win for PHP's thread-safe mode. This positive effect will be automatically achieved by continuing our use of POSIX APIs. [1] http://people.redhat.com/drepper/nptl-design.pdf and http://people.redhat.com/drepper/nptl/ - Sascha

Zeev Suraski

23 years ago
At 22:25 24/03/2003, Sascha Schumann wrote:
> > That's one of the reasons, I would guess. The libc memory manager is not > > very efficient with multiple threads accessing it at once, it has locks > > (which is one of the reasons we implemented our own in ZE2). It's > > definitely one of the reasons, and as you know, performance penalties > > accumulate. > > Which libc are you referring to here?
All, basically. Even the ultra optimized Windows memory manager is inefficient when it comes to simultaneous allocations in multiple threads, when compared to having different heaps for different threads.
> Today's Linuxthreads implementation uses a very simple > mechanism to maintain TLS (calculating an object's address in > software) whereas NPTL will shift this work to the > processor's MMU. I expect a big win for PHP's thread-safe > mode.
That's what Windows TLS does, IIRC.
> This positive effect will be automatically achieved by > continuing our use of POSIX APIs.
No surprise there... Zeev

Wojtek Meler

23 years ago
On Mon, Mar 24, 2003 at 09:59:36PM -0800, Zeev Suraski wrote:
> If __thread is any similar to Tls under Windows (which would be my guess), > then we can't use it directly. We're already using pthread_setspecific so > we're extremely quick with fetches as it is. As I said, I also doubt very > much that our performance penalty is solely due to fetches, but mostly > based on other issues, which __thread will not alter in any way. You're > more than encouraged to try and implement a __thread based solution in > place of the pthread_setspecific solution and see if it makes any > difference. If it does, we can investigate further in that direction and > see if it's usable.
I suppose that __thread is similar to __declspec( thread ). I really don't know what is faster - using __thread / __declspec(thread) struct {..} thread_globals; and accesing it in code by thread_globals.variable which probably relay on CPU's MMU (depends on compiler and libc) is probably faster than (((type) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(id)])->element) which cannot be well optimized because id is global variable and could change between function calls. I won't argue - you have more experience. I'll try to implement TSRM macros, but I don't have time now. I'll do it in July (if it won't be implemented yet). Regards, Wojtek

Shane Caraveo

23 years ago
Wojtek Meler wrote:
> On Mon, Mar 24, 2003 at 09:59:36PM -0800, Zeev Suraski wrote: > >>If __thread is any similar to Tls under Windows (which would be my guess), >>then we can't use it directly. We're already using pthread_setspecific so >>we're extremely quick with fetches as it is. As I said, I also doubt very >>much that our performance penalty is solely due to fetches, but mostly >>based on other issues, which __thread will not alter in any way. You're >>more than encouraged to try and implement a __thread based solution in >>place of the pthread_setspecific solution and see if it makes any >>difference. If it does, we can investigate further in that direction and >>see if it's usable. > > > I suppose that __thread is similar to __declspec( thread ). I really don't > know what is faster - using > > __thread / __declspec(thread) struct {..} thread_globals;
The reason it is not used in windows is because it does not (or at least at the time thread stuff was started it didn't) work correctly with dynamicaly loaded dll's. This was, at the time, well documented by MS to use TLS to get around the limitations of __declspec(thread). Shane

Zeev Suraski

23 years ago
At 01:37 25/03/2003, Wojtek Meler wrote:
>__thread / __declspec(thread) struct {..} thread_globals; > >and accesing it in code by > >thread_globals.variable > >which probably relay on CPU's MMU (depends on compiler and libc) is probably >faster than > >(((type) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(id)])->element)
If you compare these, no doubt the former will be slightly faster. But you won't be comparing these, as it will most probably not be practical to have different TLSs for shared objects, the number of TLSs is very limited, and at least under Windows, there are serious limitations with their use in the context of DLLs. This is what made us forget about it under Windows. Instead, the only thing you will be able to effectively use it for is one single TLS, as we already do today with TSRM. So essentially, you'd have to do something very similar to what we're doing today. The one field where this may save is the need to pass the context all over PHP, but it will most probably make no difference as far as fetches are concerned. Another note to remember is that we heavily rely on just-in-time construction of such globals. It won't necessarily be easy to implement such a feature if we let the compiler do it. signing off for the night, Zeev