singrdk/base/Applications/Security/bvt/PerfSnap.sg

287 lines
11 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: PerfSnap.sg
//
// Note: Performance measurer for Singularity Benchmark
//
using System;
using Microsoft.Singularity.V1.Services;
namespace Microsoft.Singularity.Applications
{
public struct PerfSnap
{
// Global options for all instances
static bool xmlOutput = false;
static bool atRing3 = false;
private bool disabled;
private long begCycleCount;
private long endCycleCount;
private long begSwitchCount;
private long endSwitchCount;
private long begInterruptCount;
private long endInterruptCount;
private long begKernelGcCount;
private long endKernelGcCount;
private long begProcessGcCount;
private long endProcessGcCount;
private long iterations;
private ulong begAllocatedCount;
private ulong begAllocatedBytes;
private ulong begFreedCount;
private ulong begFreedBytes;
private ulong endAllocatedCount;
private ulong endAllocatedBytes;
private ulong endFreedCount;
private ulong endFreedBytes;
private ulong begStackGets;
private ulong begStackRets;
private ulong endStackGets;
private ulong endStackRets;
public long Cycles { get { return endCycleCount - begCycleCount; } }
public long Interrupts { get { return endInterruptCount - begInterruptCount; } }
public long Switches { get { return endSwitchCount - begSwitchCount; } }
public long KernelGCs { get { return endKernelGcCount - begKernelGcCount; } }
public long ProcessGCs { get { return endProcessGcCount - begProcessGcCount; } }
public ulong AllocatedCount { get { return endAllocatedCount-begAllocatedCount; } }
public ulong AllocatedBytes { get { return endAllocatedBytes-begAllocatedBytes; } }
public ulong FreedCount { get { return endFreedCount - begFreedCount; } }
public ulong FreedBytes { get { return endFreedBytes - begFreedBytes; } }
public ulong StackGets { get { return endStackGets - begStackGets; } }
public ulong StackRets { get { return endStackRets - begStackRets; } }
public void Start()
{
if (!atRing3) {
disabled = Processor.DisableInterrupts();
}
int collectorCount;
long collectorMillis;
long collectorBytes;
GC.PerformanceCounters(out collectorCount,
out collectorMillis,
out collectorBytes);
ulong stackGets;
ulong stackRets;
StackService.GetUsageStatistics(out stackGets,
out stackRets);
begStackGets = stackGets;
begStackRets = stackRets;
ulong allocatedCount;
ulong allocatedBytes;
ulong freedCount;
ulong freedBytes;
PageTableService.GetUsageStatistics(out allocatedCount,
out allocatedBytes,
out freedCount,
out freedBytes);
begAllocatedCount = allocatedCount;
begAllocatedBytes = allocatedBytes;
begFreedCount = freedCount;
begFreedBytes = freedBytes;
begInterruptCount = ProcessService.GetKernelInterruptCount();
begSwitchCount = ProcessService.GetContextSwitchCount();
begKernelGcCount = ProcessService.GetKernelGcCount();
begProcessGcCount = collectorCount;
#if x64_PERF
// Set up for perf counting
if (!atRing3) {
// Reset the performance counters to what we're interested in.
Reset(0, PerfEvtSel.COUNT | PerfEvtSel.CyclesNotHalted);
Reset(1, PerfEvtSel.COUNT | PerfEvtSel.RetiredInstructions);
Reset(2, PerfEvtSel.COUNT | PerfEvtSel.RetiredBranchInstructions);
Reset(3, PerfEvtSel.COUNT | PerfEvtSel.RequestsToL2Cache | 0x400);
} else {
// We're not allowed to reset the perf counters, so take note
// of their current values; we will subtract from this later.
x64_i0 = Processor.ReadPmc(0);
x64_i1 = Processor.ReadPmc(1);
x64_i2 = Processor.ReadPmc(2);
x64_i3 = Processor.ReadPmc(3);
}
#endif
begCycleCount = unchecked((long)Processor.CycleCount);
}
public void Finish(long iterations)
{
endCycleCount = unchecked((long)Processor.CycleCount);
#if X64_PERF
x64_p0 = Processor.ReadPmc(0);
x64_p1 = Processor.ReadPmc(1);
x64_p2 = Processor.ReadPmc(2);
x64_p3 = Processor.ReadPmc(3);
#endif
endInterruptCount = ProcessService.GetKernelInterruptCount();
endSwitchCount = ProcessService.GetContextSwitchCount();
endKernelGcCount = ProcessService.GetKernelGcCount();
int collectorCount;
long collectorMillis;
long collectorBytes;
GC.PerformanceCounters(out collectorCount,
out collectorMillis,
out collectorBytes);
endProcessGcCount = collectorCount;
ulong allocatedCount;
ulong allocatedBytes;
ulong freedCount;
ulong freedBytes;
PageTableService.GetUsageStatistics(out allocatedCount,
out allocatedBytes,
out freedCount,
out freedBytes);
endAllocatedCount = allocatedCount;
endAllocatedBytes = allocatedBytes;
endFreedCount = freedCount;
endFreedBytes = freedBytes;
ulong stackGets;
ulong stackRets;
StackService.GetUsageStatistics(out stackGets,
out stackRets);
endStackGets = stackGets;
endStackRets = stackRets;
if (!atRing3) {
Processor.RestoreInterrupts(disabled);
}
this.iterations = iterations;
}
public void Display(string name)
{
if (xmlOutput) {
DisplayXml(name);
} else {
DisplayText(name);
}
}
private static void WriteXmlValue(string name, long value)
{
DualWriteLine(
String.Format(" <Measurement> <name> {0} </name> <value> {1:d} </value> </Measurement>", name, value)
);
}
private static void WriteXmlValue(string name, ulong value)
{
DualWriteLine(
String.Format(" <Measurement> <name> {0} </name> <value> {1:d} </value> </Measurement>", name, value)
);
}
private void DisplayXml(string name)
{
DualWriteLine(
String.Format("<Microbenchmark Name=\"{0}\">", name)
);
WriteXmlValue("CyclesPerIteration", Cycles / iterations);
WriteXmlValue("Cycles", Cycles);
WriteXmlValue("Iterations", iterations);
WriteXmlValue("Switches", Switches);
WriteXmlValue("Interrupts", Interrupts);
WriteXmlValue("KernelGCs", KernelGCs);
WriteXmlValue("ProcessGCs", ProcessGCs);
WriteXmlValue("AllocationCount", AllocatedCount);
WriteXmlValue("AllocationBytes", AllocatedBytes);
WriteXmlValue("FreedCount", FreedCount);
WriteXmlValue("FreedBytes", FreedBytes);
WriteXmlValue("StackGetCount", StackGets);
WriteXmlValue("StackReturnCount", StackRets);
DualWriteLine("</Microbenchmark>");
}
private void DisplayText(string name)
{
DualWriteLine(
String.Format("{0,-16} {1,6:d} x{2,8:d} ={3,12:d} " +
"[swi={4,6:d} int={5,3:d} gc={6:d}/{7:d}]",
name,
iterations,
Cycles / iterations,
Cycles,
Switches,
Interrupts,
KernelGCs,
ProcessGCs)
);
if (AllocatedCount > 1 || FreedCount > 1 || StackGets > 1) {
DualWriteLine(
string.Format(
" " +
"[alloc={0,4:d}/{1,8:x} free={2,4:d}/{3,8:x} " +
"stack={4,4:d}/{5,4:d}]",
AllocatedCount,
AllocatedBytes,
FreedCount,
FreedBytes,
StackGets,
StackRets)
);
}
#if x64_PERF
if (!atRing3) {
// Read off the current MSR values and turn them
// into nice labels
ulong e0 = Processor.ReadMsr(0xc0010000);
ulong e1 = Processor.ReadMsr(0xc0010001);
ulong e2 = Processor.ReadMsr(0xc0010002);
ulong e3 = Processor.ReadMsr(0xc0010003);
DualWriteLine(
String.Format("evt: {0,16} {1,16} {2,16} {3,16}",
EvtSelToString(e0),
EvtSelToString(e1),
EvtSelToString(e2),
EvtSelToString(e3)));
} else {
// Subtract from the initial perf-counter values to
// get the delta we want
x64_p0 -= x64_i0;
x64_p1 -= x64_i1;
x64_p2 -= x64_i2;
x64_p3 -= x64_i3;
}
DualWriteLine(
String.Format("pmc: {0:d16} {1:d16} {2:d16} {3:d16} {4:d16}\n\n",
Cycles, x64_p0, x64_p1, x64_p2, x64_p3));
#endif
}
private static void DualWriteLine(string message)
{
Console.WriteLine(message);
DebugStub.WriteLine(message);
}
public static void SetOptions(bool ring3, bool doXmlOutput)
{
PerfSnap.atRing3 = ring3;
PerfSnap.xmlOutput = doXmlOutput;
}
}
}