From: Jim S. <ja...@ne...> - 2004-03-28 20:39:48
|
The GET_THREAD_DATA gets turned into a call to THD_get_specific, which in turn call pthread_getspecific. pthread_getspecific, by actual count of a Redhat 7.2 system, executes 26 instructions without only a single thread active. So we have a call to THD, a second call to pthread_getspecific with two arguments, and another 26 instructions (best case), and two returns and stack adjustments. Passing a pointer to the thread data object is a single push instruction. The difference between passing the thread data point and fetching it two call prologs, a net of one argument push, the 26 instructions (best case), and two return sequences. That's the code as it exists today. Passing arguments in the argument list is, in my opinion, a good way to pass arguments. Cobol, circa 1963, used only globals. Fortran programmers like common; sophisticated ones use named common. But I think a proper stack machine as much going for it. Perhaps there is or will be a C++ compiler/linker/runtime smart enough to declare thread variables, assign them to thread specific data areas, allocate a register to point to thread data, and reference thread variables off the register. There are probably better things to do with scarce registers, but it sure would speed up thread specific data, which is occasionally required. But depending on a such an beast (which Firebird most definitely doesn't use) for decent performance is not a great idea, particularly when the alternative is the preferred design anyway. But there are other reasons not to use GET_THREAD_DATA. The thread data object is used to pass context. Within execution of a request, the context sometimes changes, for example, from a user request to a system request. Tweaking the values in the thread data object is, like all other globals, dangerous, relying on careful reconstruction of state after execution. Passing the thread data object as a formal argument allows a piece of code to clone/alter the context safely, have the appropriate guys down stream receive the appropriate context, and not have to worry about having trashed the original. This eliminates the need to exception handlers to recover the state of a global thread data object. Thread data can't be eliminated. It isn't possible to implement recovery from a synchronous signal on Unix. It is also necessary for thread synchronization code so a thread relinquishing a resource can wake up the next lucky winner. But it absolutely does not belong in mainstream code. It is a crutch from an ill-considered attempt to increase thread parallelism that should have been removed years ago. Please don't try to justify it as a performance kicker. It isn't. |