-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Store CurrentThread in ThreadStatic #21328
Conversation
|
The thread is presumably the root of the ThreadStatics so might be a different approach that would be faster? (e.g. is it something else in the native call; as I assume ThreadStatic access is also a native call?) |
The
It is probably possible because of the access to thread statics is not as optimized as it can be in JITed code. However, I would rather be spending energy on optimizing thread statics in general than on trying to tweak the GetCurrentThread FCall to be faster. |
| internal static CultureInfo m_CurrentCulture; | ||
| [ThreadStatic] | ||
| internal static CultureInfo m_CurrentUICulture; | ||
| [ThreadStatic] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: The prefix for thread statics should t_.
System.Threading.Thread in CoreLib is left-over from full framework. It may be nice to do this in RuntimeThread.cs and get rid of Thread.CurrentThread in this file. (The FCall can still stay in this file.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be nice to do this in RuntimeThread.cs and get rid of Thread.CurrentThread in this file.
'Thread' is less accessible than 'RuntimeThread' but if it returned 'RuntimeThread' instead then that returns other errors so more properties would need to be moved up e.g.
'RuntimeThread' does not contain a definition for 'ExecutionContext'There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What file is that? Most places should be covered by using Thread = Internal.Runtime.Augments.RuntimeThread; already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, I can add it then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Issue is with ThreadPool.cs and ExecutionContext.cs which are in the System.Threading namespace.
Moving using Thread = Internal.Runtime.Augments.RuntimeThread; inside the namespace declaration gives Namespace 'System.Threading' contains a definition conflicting with alias 'Thread'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are also places that use properties that are on Thread but not on RuntimeThread
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to t_ anyway 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok. It see that it is complicated.
|
I tried to increase the iterations and use public class Program
{
const int Iters = 1000;
public static bool Thread_CurrentThread()
{
var ret = false;
for (var i = 0; i < Iters; i++)
{
ret ^= (Thread.CurrentThread == s_currentThread);
}
return ret;
}
public static bool ThreadStatic_CurrentThread()
{
var ret = false;
for (var i = 0; i < Iters; i++)
{
ret ^= (CurrentThread == s_currentThread);
}
return ret;
}
[ThreadStatic]
private static Thread t_currentThread;
private volatile static Thread s_currentThread;
private static Thread CurrentThread => t_currentThread ?? InitaliseCurrentThread();
[MethodImpl(MethodImplOptions.NoInlining)]
private static Thread InitaliseCurrentThread() => (t_currentThread = Thread.CurrentThread);
}But that gets so fast for the ThreadStatic I'm assuming its still loop hoisting it 😄 |
|
Not for this PR, but could also do something similar with private bool? _isThreadPoolThread;
public bool IsThreadPoolThread => _isThreadPoolThread ?? InitializeIsThreadPoolThread();
[MethodImpl(MethodImplOptions.NoInlining)]
private bool InitializeIsThreadPoolThread()
{
return (_isThreadPoolThread = IsThreadPoolThreadNative());
}However the InternalCall is IsThreadPoolThread so would need renaming in the C++ |
The thread flags should be cached eagerly when the thread is created, so that the flag can be checked without worrying whether it has been initialized. CoreRT has good prior art for this: |
Commit migrated from dotnet/coreclr@5a7f3c6
Accessing
Thread.CurrentThreadvia a[ThreadStatic]is 26% faster than via the InternalCallGetCurrentThreadNative; so cacheGetCurrentThreadNativein a[ThreadStatic]As its used very commonly (
ExecutionContext.Capture()andExecutionContext.Run(...)being the main examples for my usage)