singrdk/base/Applications/Tests/IoTestApp/IoTestApp.sg

247 lines
9.2 KiB
Plaintext
Raw Permalink Normal View History

2008-11-17 18:29:00 -05:00
////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Note:
//
// This is the top level unit/iotest driver that sends and receives I/O
// on the IoTest device drivers contract.
//
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using Microsoft.Singularity;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.V1.Services;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Channels;
using Microsoft.Contracts;
using Microsoft.SingSharp.Reflection;
using Microsoft.Singularity.Applications;
using Microsoft.Singularity.Configuration;
[assembly: Transform(typeof(ApplicationResourceTransform))]
namespace Microsoft.Singularity.Applications
{
[ConsoleCategory(HelpMessage="IoTest Application for IoTest driver", DefaultAction=true)]
internal class Parameters
{
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
[Endpoint]
public readonly TRef<DirectoryServiceContract.Imp:Start> nsRef;
//[StringParameter( "device", Mandatory=true, Position=0 , HelpMessage="Device name for test (usually /dev/iotest0)")]
[StringParameter( "device", Default="/dev/iotest0", Position=0 , HelpMessage="Device name for test (usually /dev/iotest0)")]
internal string deviceName;
[LongParameter( "size", Default=4096, HelpMessage="Size for each I/O Transaction")]
internal long chunksize;
[LongParameter( "count", Default=50000, HelpMessage="Repetition count.")]
internal long count;
reflective internal Parameters();
internal int AppMain() {
return IoTest.AppMain(this);
}
}
public class IoTest
{
public static IoTestContract.Imp:Ready OpenDevice(String! devname)
{
IoTestContract.Exp! exp;
IoTestContract.Imp! imp;
IoTestContract.NewChannel(out imp, out exp);
DirectoryServiceContract.Imp ns;
// get NS endpoint
ns = DirectoryService.NewClientEndpoint();
bool success = false;
ErrorCode error;
success = SdsUtils.Bind(devname, ns, exp, out error);
if (!success) {
Console.WriteLine("Bind of {0} failed\n", devname);
delete imp;
delete ns;
return null;
}
switch receive {
case imp.Success():
break;
case imp.ContractNotSupported():
Console.WriteLine("{0} does not support IoTestDevice", devname);
delete imp;
delete ns;
return null;
case imp.ChannelClosed():
Console.WriteLine("IoTestDevice channel to {0} closed unexpectedly", devname);
delete imp;
delete ns;
return null;
}
delete ns;
return imp;
}
private static void DisplayPerf(long ticksDelta, long ticksPerSecond, long iters, long chunkSize)
{
long numBytes = iters * chunkSize;
long opsPerSec = ticksDelta == 0 ? long.MaxValue : iters * ticksPerSecond / ticksDelta;
long bytesPerSec = ticksDelta == 0 ? long.MaxValue : numBytes * ticksPerSecond / ticksDelta;
long mbPerSec = bytesPerSec / (1024*1024);
long elapsedSeconds = ticksDelta / ticksPerSecond;
Console.WriteLine("Ops/s: {0} MB/s: {1} Bytes/Sec {2} Elapsed: {3}",
opsPerSec, mbPerSec, bytesPerSec, elapsedSeconds);
}
internal static int AppMain(Parameters! config)
{
long chunkSize = config.chunksize;
long iters = config.count;
IoTestContract.Imp imp;
string! devName = (!)config.deviceName;
imp = OpenDevice(devName);
if (null == imp) {
return 1;
}
DateTime startDateTime = ProcessService.GetUtcTime();
long startIrqCount = ProcessService.GetKernelInterruptCount();
long startSwitchCount = ProcessService.GetContextSwitchCount();
long startKernelGcCount = ProcessService.GetKernelGcCount();
int startGcCount;
long startGcMillis;
long startGcBytes;
GC.PerformanceCounters(out startGcCount,
out startGcMillis,
out startGcBytes);
// Allocate an exchange heap buffer for write
byte[] in ExHeap writeBuffer = new [ExHeap] byte [chunkSize];
// Set a known pattern for comparison on readback
for (int i = 0; i < writeBuffer.Length; i++) {
writeBuffer[i] = (byte)i;
}
// Allocate an exchange heap buffer for read
byte[] in ExHeap readBuffer = new [ExHeap] byte [chunkSize];
// Clear the read buffer
for (int i = 0; i < readBuffer.Length; i++) {
readBuffer[i] = 0;
}
for (long count = 0; count < iters; count++) {
ulong lengthWritten;
ulong lengthRead;
// Declare a reference to an output buffer from the exchange heap
byte[]! in ExHeap outWriteBuffer;
byte[]! in ExHeap outReadBuffer;
// First do a write, we lose ownership of buffer
imp.SendWrite(writeBuffer, 0, (ulong)chunkSize);
// Receive the write ack, we receive ownership of outBuffer
imp.RecvAckWrite(out outWriteBuffer, out lengthWritten); // Fix writeOut, not needed???
// What happens if the real response is RecvNakWrite()?
// (an exception occurs)
if (lengthWritten != (ulong)chunkSize) {
Console.WriteLine("Error: lengthWritten {0} does not match request size {1}",
lengthWritten, chunkSize);
}
// Compare the pattern
for (int i = 0; i < outWriteBuffer.Length; i++) {
if (outWriteBuffer[i] != (byte)i) {
Console.WriteLine("Error: returned buffer pattern mismatch on Write! index={0}, value={1}, sb={2}",
i, outWriteBuffer[i], (byte)i);
}
}
writeBuffer = outWriteBuffer;
// Clear the read buffer
for (int i = 0; i < readBuffer.Length; i++) {
readBuffer[i] = 0;
}
// Send the Read
imp.SendRead(readBuffer, 0, (ulong)chunkSize);
// Receive the Ack for the read
imp.RecvAckRead(out outReadBuffer, out lengthRead);
// What happens if the real response is RecvNakRead()?
// (an exception occurs)
if (lengthRead != (ulong)chunkSize) {
Console.WriteLine("Error: lengthRead {0} does not match request size {1}",
lengthRead, chunkSize);
}
// Compare the pattern
for (int i = 0; i < outReadBuffer.Length; i++) {
if (outReadBuffer[i] != (byte)i) {
Console.WriteLine("Error: returned buffer pattern mismatch on Read! index={0}, value={1}, sb={2}",
i, outReadBuffer[i], (byte)i);
}
}
readBuffer = outReadBuffer;
}
int endGcCount;
long endGcMillis;
long endGcBytes;
long endCycleCount;
DateTime endDateTime = ProcessService.GetUtcTime();
GC.PerformanceCounters(out endGcCount,
out endGcMillis,
out endGcBytes);
long ticksDelta = endDateTime.Ticks - startDateTime.Ticks;
double elapsedSeconds;
DisplayPerf(ticksDelta, DateTime.TicksPerSecond, iters, chunkSize);
Console.WriteLine("[AppGC :- cnt {0} bytes {1} Kern: ints {2} swi {3} gcs {4}]",
endGcCount - startGcCount,
endGcBytes - startGcBytes,
ProcessService.GetKernelInterruptCount() - startIrqCount,
ProcessService.GetContextSwitchCount() - startSwitchCount,
ProcessService.GetKernelGcCount() - startKernelGcCount);
// Rundown exchange heap buffers
delete readBuffer;
delete writeBuffer;
// Rundown endpoints
delete imp;
return 0;
}
}
}