Tuesday, June 26, 2018

Skylake "pause" Latency: i tried a Powershell thing, my test wasn't well designed

Motivated by the excellent writeup of a performance concern for recent Intel processors below, I wanted to write a simple test case in Powershell.  A colleague designed a SQL Server workload that was spinlock-heavy, and we wanted some way of ruling in/out changes in "pause" latency for workload timing differences between processors.

Why Skylake CPUs Are Sometimes 50% Slower – How Intel Has Broken Existing Code
https://aloiskraus.wordpress.com/2018/06/16/why-skylakex-cpus-are-sometimes-50-slower-how-intel-has-broken-existing-code/

"Pause Intrinsic" seems to be what I'm after... but will I be able to leverage it without creating something in C++?
Pause Intrinsic

https://software.intel.com/en-us/node/524249

After some digging around, it seems thread.spinwait is what I want to get to the "pause" instruction with minimal overhead.

Thread.SpinWait Method (Int32)
https://msdn.microsoft.com/en-us/library/system.threading.thread.spinwait(v=vs.110).aspx

Okay... that's a little closer.  Then I happened to find this gem.
PowerShell Using Threads in C# to Launch a Process and Read Output Streams
https://blogs.msdn.microsoft.com/donmoore/2011/03/17/powershell-using-threads-in-c-to-launch-a-process-and-read-output-streams/

Well, now.  Putting some C# into a Powershell variable... that seems like something I can do 😇

So I cooked this up.


# want to test pause instruction latency on Windows from Powershell
# spinwait info
# https://www.dotnetperls.com/spinwait
# https://msdn.microsoft.com/en-us/library/system.threading.thread.spinwait(v=vs.110).aspx

# strategy of putting C# source into a Powershell variable
# https://blogs.msdn.microsoft.com/donmoore/2011/03/17/powershell-using-threads-in-c-to-launch-a-process-and-read-output-streams/


$source = @"
using System; 
using System.Diagnostics;
using System.Threading;

public class SpinSome
{
public void Run()
    {
        Stopwatch stopwatch = Stopwatch.StartNew();
        Thread.SpinWait(1000000000);
        Console.WriteLine(stopwatch.Elapsed.TotalMilliseconds);
    }
}
"@

Add-Type -TypeDefinition $source -ReferencedAssemblies ("System.Core")

$runSpinSome = New-Object SpinSome

$runSpinSomeResult = $runSpinSome.Run()

Sample results from my laptop [Intel(R) Core(TM) i5-5300U CPU @ 2.30GHz].





Intel(R) Xeon(R) CPU E7-8890 v4 @ 2.20GHz
5993.7096 ms

Intel(R) Xeon(R) Platinum 8160 CPU @ 2.10GHz
6250.6175 ms

The results I was getting are way too close to simply scaling with clock speed of the processor.   After discussing with some colleagues, we determined that most likely, without thread contention between the logical cores of an Hyperthreaded core, I wasn't likely to see he difference in the maximum pause latency.

Rats.  But it was a fun attempt.


No comments:

Post a Comment