singrdk/base/Applications/ServiceManager/Benchmark/MultiThreadJob.sg

326 lines
9.1 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Applications\ServiceManager\Benchmark\MultiThreadJob.sg
//
// Note:
//
using System;
using System.Collections;
using System.Text;
using System.Threading;
using Microsoft.SingSharp;
using Microsoft.Singularity;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.ServiceManager;
using Microsoft.Singularity.Services;
namespace Microsoft.Singularity.Applications.ServiceManager
{
internal sealed class RandomJob : Job
{
private readonly int id;
private bool keepAlive;
private ulong messageCount;
private ulong firstHalf;
private Thread thread;
[ Microsoft.Contracts.NotDelayed ]
internal RandomJob(BenchmarkServerInfo! info, int tid)
{
base(info);
this.id = tid;
thread = new Thread(new ThreadStart(this.RunThread));
}
internal override bool Run()
{
thread.Start();
return true;
}
internal void Join()
{
thread.Join();
}
internal void Join(int timeout)
{
thread.Join(new TimeSpan(0, 0, 0, timeout));
}
internal void RunThread()
{
ulong time1;
ulong time2;
DebugStub.Print("RandomJob {0} start\n", __arglist(id));
BenchmarkContract.Imp:Ready! imp;
if (!Bind(out imp)) {
goto exit;
}
messageCount = 0;
keepAlive = true;
while (keepAlive) {
imp.SendNull();
switch receive {
case imp.AckNull():
break;
case unsatisfiable:
goto exit;
break;
}
messageCount += 2;
}
/*
imp.SendEndOfBenchmark();
switch receive {
case imp.AckEnd():
break;
case imp.ChannelClosed():
break;
}
*/
exit:
delete imp;
DebugStub.Print("RandomJob {0} stop\n", __arglist(id));
}
internal void Stop()
{
keepAlive = false;
}
internal void SwitchRecord()
{
firstHalf = messageCount;
}
internal ulong MessageCount
{
get { return messageCount; }
private set {}
}
internal ulong FirstHalf
{
get { return firstHalf; }
private set{}
}
internal ulong SecondHalf
{
get {return messageCount - firstHalf; }
private set{}
}
}
internal sealed class MultiThreadJob : Job
{
private const int Order = 4;
private const int NSamples = 10;
private ulong[,] firstHalf = new ulong[Order, NSamples];
private ulong[,] totalMessages = new ulong[Order, NSamples];
private ArrayList jobList;
private TRef<ServiceControlContract.Imp:Ready> serverRef;
internal MultiThreadJob(BenchmarkServerInfo! info,
TRef<ServiceControlContract.Imp:Ready>! tref)
{
base(info);
this.jobList = new ArrayList();
this.serverRef = tref;
}
internal override bool Run()
{
bool success = false;
Console.WriteLine("MultiThreadJob start");
DebugStub.WriteLine("-- MultiThreadJob start");
for (int i = 0; i < Order; i++) {
for (int j = 0; j < NSamples; j++) {
CreateJobs(1 << i);
StartJobs();
Thread.Sleep(5000);
Start2ndHalf();
if (base.info.Type == ServiceType.Resilient) {
success = RestartService();
}
else {
DummyOperation();
success = true;
}
Thread.Sleep(5000);
DebugStub.WriteLine("Stop jobs...");
StopJobs();
CollectResults(i, j);
DebugStub.WriteLine("Delete jobs...");
DeleteJobs();
if (!success) {
break;
}
Thread.Sleep(2000);
}
}
return success;
}
private void CreateJobs(int numberOfJobs)
{
RandomJob job;
for (int i = 0; i < numberOfJobs; i++) {
job = new RandomJob(base.info, i);
jobList.Add(job);
}
}
private void StartJobs()
{
RandomJob job;
foreach (Object obj in jobList) {
if (obj != null) {
job = obj as RandomJob;
if (job != null) {
job.Run();
}
}
}
}
private void Start2ndHalf()
{
RandomJob job;
foreach (Object obj in jobList) {
if (obj != null) {
job = obj as RandomJob;
if (job != null) {
job.SwitchRecord();
}
}
}
}
private void StopJobs()
{
RandomJob job;
foreach (Object obj in jobList) {
if (obj != null) {
job = obj as RandomJob;
if (job != null) {
job.Stop();
}
}
}
foreach (Object obj in jobList) {
if (obj != null) {
job = obj as RandomJob;
if (job != null) {
job.Join(2000);
}
}
}
}
private void DeleteJobs()
{
jobList.Clear();
}
private bool RestartService()
{
bool success = false;
ServiceControlContract.Imp:Ready! ep;
ep = serverRef.Acquire();
ep.SendRestartService();
switch receive {
case ep.AckRestartService():
{
success = true;
break;
}
case ep.ChannelClosed():
{
success = false;
break;
}
}
serverRef.Release(ep);
return success;
}
private void DummyOperation()
{
ServiceControlContract.Imp:Ready! ep;
ep = serverRef.Acquire();
ep.SendStopPoll();
switch receive {
case ep.AckStopPoll():
break;
case ep.ChannelClosed():
break;
}
serverRef.Release(ep);
}
private void CollectResults(int order, int sample)
{
RandomJob job;
foreach (Object obj in jobList) {
if (obj != null) {
job = obj as RandomJob;
if (job != null) {
firstHalf[order, sample] = job.FirstHalf;
totalMessages[order, sample] = job.MessageCount;
}
}
}
}
public override String! ToString()
{
ulong half, total;
StringBuilder builder = new StringBuilder();
builder.Append("-- MultiThread Test (100 samples for each)");
builder.Append("(5 seconds for each half) --\n");
builder.Append("Client(s) FirstHalf SecondHalf Total\n");
builder.Append("--------- --------- ---------- -------\n");
for (int i = 0; i < Order; i++) {
half = 0;
total = 0;
for (int j = 0; j < NSamples; j++) {
half += firstHalf[i, j];
total += totalMessages[i, j];
}
half /= NSamples;
total /= NSamples;
builder.AppendFormat("{0, -9} {1, 9} {2, 10} {3, 7}\n",
1 << i, half, total - half, total);
}
builder.Append("\n");
return builder.ToString();
}
}
}