Kaynağa Gözat

Fix performance regression caused by the new scheduler changes (#422)

* Call interrupt less often, remove some leftovers from the old scheduler code

* Remove unneeded attribute
gdkchan 7 yıl önce
ebeveyn
işleme
99b2692425

+ 0 - 2
ChocolArm64/AThread.cs

@@ -46,8 +46,6 @@ namespace ChocolArm64
                 return false;
             }
 
-            Work.Name = "cpu_thread_" + Work.ManagedThreadId;
-
             Work.Start();
 
             return true;

+ 23 - 7
ChocolArm64/State/AThreadState.cs

@@ -2,6 +2,7 @@ using ChocolArm64.Events;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Runtime.CompilerServices;
 using System.Runtime.Intrinsics;
 
 namespace ChocolArm64.State
@@ -14,6 +15,8 @@ namespace ChocolArm64.State
         internal const int ErgSizeLog2 = 4;
         internal const int DczSizeLog2 = 4;
 
+        private const int MinInstForCheck = 4000000;
+
         internal AExecutionMode ExecutionMode;
 
         //AArch32 state.
@@ -45,6 +48,8 @@ namespace ChocolArm64.State
 
         private bool Interrupted;
 
+        private int SyncCount;
+
         public long TpidrEl0 { get; set; }
         public long Tpidr    { get; set; }
 
@@ -101,13 +106,16 @@ namespace ChocolArm64.State
             TickCounter.Start();
         }
 
-        internal bool Synchronize()
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal bool Synchronize(int BbWeight)
         {
-            if (Interrupted)
-            {
-                Interrupted = false;
+            //Firing a interrupt frequently is expensive, so we only
+            //do it after a given number of instructions has executed.
+            SyncCount += BbWeight;
 
-                OnInterrupt();
+            if (SyncCount >= MinInstForCheck)
+            {
+                CheckInterrupt();
             }
 
             return Running;
@@ -118,9 +126,17 @@ namespace ChocolArm64.State
             Interrupted = true;
         }
 
-        private void OnInterrupt()
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private void CheckInterrupt()
         {
-            Interrupt?.Invoke(this, EventArgs.Empty);
+            SyncCount = 0;
+
+            if (Interrupted)
+            {
+                Interrupted = false;
+
+                Interrupt?.Invoke(this, EventArgs.Empty);
+            }
         }
 
         internal void OnBreak(long Position, int Imm)

+ 2 - 0
ChocolArm64/Translation/AILEmitterCtx.cs

@@ -123,6 +123,8 @@ namespace ChocolArm64.Translation
         {
             EmitLdarg(ATranslatedSub.StateArgIdx);
 
+            EmitLdc_I4(CurrBlock.OpCodes.Count);
+
             EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.Synchronize));
 
             EmitLdc_I4(0);

+ 4 - 6
Ryujinx.HLE/HOS/Kernel/KCoreContext.cs

@@ -28,7 +28,10 @@ namespace Ryujinx.HLE.HOS.Kernel
                 Thread.LastScheduledTicks = (uint)Environment.TickCount;
             }
 
-            ContextSwitchNeeded = true;
+            if (SelectedThread != CurrentThread)
+            {
+                ContextSwitchNeeded = true;
+            }
         }
 
         public void UpdateCurrentThread()
@@ -58,10 +61,5 @@ namespace Ryujinx.HLE.HOS.Kernel
                 CurrentThread.Context.Execute();
             }
         }
-
-        public void RemoveThread(KThread Thread)
-        {
-            //TODO.
-        }
     }
 }

+ 0 - 48
Ryujinx.HLE/HOS/Kernel/SchedulerThread.cs

@@ -1,48 +0,0 @@
-using System;
-using System.Threading;
-
-namespace Ryujinx.HLE.HOS.Kernel
-{
-    class SchedulerThread : IDisposable
-    {
-        public KThread Thread { get; private set; }
-
-        public SchedulerThread Next { get; set; }
-
-        public bool IsActive { get; set; }
-
-        public AutoResetEvent   WaitSync     { get; private set; }
-        public ManualResetEvent WaitActivity { get; private set; }
-        public AutoResetEvent   WaitSched    { get; private set; }
-
-        public SchedulerThread(KThread Thread)
-        {
-            this.Thread = Thread;
-
-            IsActive = true;
-
-            WaitSync  = new AutoResetEvent(false);
-
-            WaitActivity = new ManualResetEvent(true);
-
-            WaitSched = new AutoResetEvent(false);
-        }
-
-        public void Dispose()
-        {
-            Dispose(true);
-        }
-
-        protected virtual void Dispose(bool Disposing)
-        {
-            if (Disposing)
-            {
-                WaitSync.Dispose();
-
-                WaitActivity.Dispose();
-
-                WaitSched.Dispose();
-            }
-        }
-    }
-}

+ 0 - 2
Ryujinx.HLE/HOS/Kernel/SvcThread.cs

@@ -81,8 +81,6 @@ namespace Ryujinx.HLE.HOS.Kernel
             CurrentThread.Exit();
 
             System.Scheduler.StopThread(CurrentThread);
-
-            System.Scheduler.CoreContexts[CurrentThread.CurrentCore].RemoveThread(CurrentThread);
         }
 
         private void SvcSleepThread(AThreadState ThreadState)

+ 4 - 1
Ryujinx.HLE/HOS/Process.cs

@@ -356,7 +356,10 @@ namespace Ryujinx.HLE.HOS
         {
             if (sender is AThread Thread)
             {
-                Threads.TryRemove(Thread.ThreadState.Tpidr, out KThread KernelThread);
+                if (Threads.TryRemove(Thread.ThreadState.Tpidr, out KThread KernelThread))
+                {
+                    Device.System.Scheduler.RemoveThread(KernelThread);
+                }
             }
 
             if (Threads.Count == 0)