326 lines
9.1 KiB
Plaintext
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();
|
||
|
}
|
||
|
}
|
||
|
}
|