So, I have a game in which the main thread executes the usual update / rendering logic that you expect and the second thread that does very intensive processing. The problem I am facing is that sometimes the main thread will be interrupted and the game will drop below 60FPS. I am sure that it is blocked by another thread, but since there is no explicit blocking, I can not prove it.
There are several scenarios that I can come up with why the main thread will be blocked by the secondary thread:
- The second stream highlights many small objects; memory allocation makes one thread wait while another allocates memory. This seems unlikely, since you expect that after allocating one small object, the main thread can move on to distributing what it needs.
- Some form of JIT optimization that prevents interruption of the secondary stream when it takes too long. It makes no sense.
- Some kind of cross reference, which is blocked. It is unlikely that the code is intentionally shared by a queue, where the secondary thread grabs items from the queue, but does not block or put items placed in the queue.
- Incorrect suspension of the OS stream is also very unlikely, since this problem occurs both on Linux and Windows.
, , " 500-"; , .
- , , ?
----- EDIT -----
Mono :
Monitor lock summary
Lock object 0x7f05190c9fe0: 1 contentions
0.002126 secs total wait time, 0.002126 max, 0.002126 average
1 contentions from:
(wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
System.Threading.Thread:StartInternal ()
System.Threading.Timer/Scheduler:SchedulerThread ()
(wrapper unknown) System.Threading.Monitor:FastMonitorEnterV4 (object,bool&)
System.Threading.Monitor:Enter (object,bool&)
System.Threading.Monitor:TryEnter (object,int,bool&)
(wrapper managed-to-native) System.Threading.Monitor:try_enter_with_atomic_var (object,int,bool&)
Lock object 0x7f051910b100: 1 contentions
0.000628 secs total wait time, 0.000628 max, 0.000628 average
1 contentions from:
Ninject.Components.ComponentContainer:Get (System.Type)
Ninject.Components.ComponentContainer:ResolveInstance (System.Type,System.Type)
Ninject.Components.ComponentContainer:CreateNewInstance (System.Type,System.Type)
System.Reflection.ConstructorInfo:Invoke (object[])
System.Reflection.MonoCMethod:Invoke (System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo)
System.Reflection.MonoCMethod:DoInvoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo)
System.Reflection.MonoCMethod:InternalInvoke (object,object[])
(wrapper managed-to-native) System.Reflection.MonoCMethod:InternalInvoke (System.Reflection.MonoCMethod,object,object[],System.Exception&)
(wrapper runtime-invoke) <Module>:runtime_invoke_void__this___object (object,intptr,intptr,intptr)
Ninject.Activation.Caching.ActivationCache:.ctor (Ninject.Activation.Caching.ICachePruner)
Ninject.Activation.Caching.GarbageCollectionCachePruner:Start (Ninject.Activation.Caching.IPruneable)
(wrapper remoting-invoke-with-check) System.Threading.Timer:.ctor (System.Threading.TimerCallback,object,int,int)
System.Threading.Timer:.ctor (System.Threading.TimerCallback,object,int,int)
System.Threading.Timer:Init (System.Threading.TimerCallback,object,long,long)
System.Threading.Timer:Change (long,long,bool)
System.Threading.Timer/Scheduler:Change (System.Threading.Timer,long)
(wrapper unknown) System.Threading.Monitor:FastMonitorEnterV4 (object,bool&)
System.Threading.Monitor:Enter (object,bool&)
System.Threading.Monitor:TryEnter (object,int,bool&)
(wrapper managed-to-native) System.Threading.Monitor:try_enter_with_atomic_var (object,int,bool&)
Lock object 0x7f05190ca000: 1 contentions
0.000347 secs total wait time, 0.000347 max, 0.000347 average
1 contentions from:
(wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
System.Threading.Thread:StartInternal ()
System.Threading.Timer/Scheduler:SchedulerThread ()
(wrapper remoting-invoke-with-check) System.Threading.EventWaitHandle:Reset ()
System.Threading.EventWaitHandle:Reset ()
(wrapper unknown) System.Threading.Monitor:FastMonitorEnterV4 (object,bool&)
System.Threading.Monitor:Enter (object,bool&)
System.Threading.Monitor:TryEnter (object,int,bool&)
(wrapper managed-to-native) System.Threading.Monitor:try_enter_with_atomic_var (object,int,bool&)
Lock contentions: 3
Lock acquired: 3
Lock failures: 0
20-30 , 10 . 3 , 16 .