/////////////////////////////////////////////////////////////////////////////// // // 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 serverRef; internal MultiThreadJob(BenchmarkServerInfo! info, TRef! 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(); } } }