Hi Dmtry, thanks for taking a look at this.
On Wed, October 1, 2014 00:09, Dmitry Stogov wrote: > Hi, > > > I took a quick look over the patch. > I didn't get why it's named "native_tls" now, because it doesn't use > "__thread" variables anymore. I was wondering myself but now I see (intentionally taking the 5.2 source) http://lxr.php.net/xref/PHP_5_2/TSRM/TSRM.c#282 http://lxr.php.net/xref/PHP_5_2/TSRM/TSRM.c#329 We already use TLS :) It took quite some time to understand this. > Actually, now the patch get rid of additional TSRMLS_ arguments, but > performs near the same thing as TSRMLS_FETCH() on each module global > access. It leads to huge slowdown. > > bench.php. > > non-zts: 1.222 sec > zts: 1.362 sec > native_tls: 1.785 sec > > > I think, the patch makes no sense in this state. > Absolutely, this state is just to show we can drop the TSRMLS_* things without hurting the functional part. At least I'm glad you have noticed no regression on the functionality, but just the slowdown. > It looks like on Windows we can't use __declspec(thread) in DLLs loaded > using LoadLibray() at all, so we won't ale to build mod_php for Apache or > use __declspec(thread) for module globals of extensions build as DLL > > On Linux it must be possible, but it depends on TLS model (gcc > -ftls-model=...). "global-dynamic" model must work in all cases, but I'm > not sure about performance, because it'll lead to additional function call > for each "__thread" variable access (may be I'm wrong). Better models > (like > "initial-exec") have some limitations. I don't have enough experience to > say, if they could work for us. > With the linux part - yeah, the gcc linker does the great magic which makes __thread variables work between shared objects. The function call is needed specifically because on Windows it is not possible to do __declspec(dllexport) __declspec(thread). With __dllspec(thread) unusable when explicitly loaded - not true since Vista anymore. Please read here http://msdn.microsoft.com/en-us/library/windows/desktop/ms684175%28v=vs.85%29.aspx "Windows Server 2003 and Windows XP: The Visual C++ compiler supports a syntax that enables you to declare thread-local variables: _declspec(thread). If you use this syntax in a DLL, you will not be able to load the DLL explicitly using LoadLibrary on versions of Windows prior to Windows Vista. If your DLL will be loaded explicitly, you must use the thread local storage functions instead of _declspec(thread). For an example, see Using Thread Local Storage in a Dynamic Link Library." So this is not an issue as we won't support XP in PHP7 anyway. But the issue is that it cannot export a thread specific variable, but it can perfectly gain the access to it through an explicit tls storage query. MSDN provides also a snippet on how it works http://msdn.microsoft.com/en-us/library/windows/desktop/ms686997%28v=vs.85%29.aspx While investigating on it, i've added one more DLL which loads through LoadLibrary and it worked the same way as the DLL linked implicitly using a .lib file. Let me know if you'd like to look at my investigation code on this. Just to sumarize: - TLS is used all the way since at least 5.2 - the portable way to share the tls storage is by accessing it through tsrm_tls_get/tsrm_tls_set macros - function calls slow down everything That is why I mean - the patch is functionally doing the same what the mainstream does, but allows to remove the TSRMLS_* macros. Btw. the thread keys get allocated by Apache already. Maybe we have to care about that in some other SAPI but I'm not sure there is another one except mpm_worker/mpm_winnt which can exhaust all the TS potential. In Apache it's spread over several sources, however here is the essential part http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/win32/threadpriv.c?view=markup My current idea on how to speed up it - the __thread or __declspec(thread) variables can be used and are both portable within the same binary unit (say .so, .dll, .exe, etc.). Once we have a resource pointer, it can be cached in a local variable. In some header, it would be declared like TSRM_TLS extern void *tsrm_cache; And in one .c file it would be properly defined. The header would make it accessible from all the .c files in the same binary unit (all object files linked together). Of course, this variable has to be updated once per thread before any globals could be read. What is needed is to lookup the correct places to update that variable. Such a variable will have unfortunately to be defined in every so/dll/exe and then updated accordingly. But getting the tsrm cache per function call will still work. Maybe something comes in your mind where such correct places should be? zend_startup() and zend_activate()? When it's worky, it might even solve some perf issue also with Linux, if I understood it correctly. Regards Anatol -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php