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
This commit is contained in:
gdkchan 2018-09-19 12:16:20 -03:00 committed by GitHub
parent fae097408e
commit 99b2692425
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 33 additions and 66 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -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();
}
}
}
}

View file

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

View file

@ -356,7 +356,10 @@ namespace Ryujinx.HLE.HOS
{ {
if (sender is AThread Thread) 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) if (Threads.Count == 0)