2
// MonoMac.CFNetwork.Test.Models.BenchmarkRunner
5
// Martin Baulig (martin.baulig@gmail.com)
7
// Copyright 2012 Xamarin Inc. (http://www.xamarin.com)
10
// Permission is hereby granted, free of charge, to any person obtaining
11
// a copy of this software and associated documentation files (the
12
// "Software"), to deal in the Software without restriction, including
13
// without limitation the rights to use, copy, modify, merge, publish,
14
// distribute, sublicense, and/or sell copies of the Software, and to
15
// permit persons to whom the Software is furnished to do so, subject to
16
// the following conditions:
18
// The above copyright notice and this permission notice shall be
19
// included in all copies or substantial portions of the Software.
21
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
using System.Net.Http;
32
using System.Threading;
33
using System.Threading.Tasks;
34
using MonoMac.Foundation;
35
using MonoMac.CFNetwork;
37
namespace MonoMac.CFNetwork.Test.Models {
41
public class BenchmarkRunner : AsyncTaskRunner {
42
public override bool CanReportProgress {
46
public override bool CanSendResponse {
50
public event EventHandler<MessageEventArgs> DetailedMessageEvent;
52
protected virtual void OnDetailedMessageEvent (object sender, MessageEventArgs args)
54
if (DetailedMessageEvent != null)
55
DetailedMessageEvent (sender, args);
58
void Write (string message, params object[] args)
60
Write (string.Format (message, args));
63
void Write (string message)
65
OnDetailedMessageEvent (this, new MessageEventArgs (message));
68
void WriteLine (string message, params object[] args)
70
Write (string.Format (message, args) + Environment.NewLine);
73
void WriteLine (string message)
75
Write (message + Environment.NewLine);
78
BenchmarkViewController ViewController {
79
get { return AppDelegate.Instance.MainWindowController.BenchmarkController; }
85
BenchmarkViewController.ModeTag mode;
86
CancellationTokenSource cts;
88
internal override async Task<string> Run (Uri uri, CancellationToken cancellationToken)
91
throw new InvalidOperationException ();
94
this.mode = (BenchmarkViewController.ModeTag)ViewController.Mode;
95
this.repeatCount = ViewController.RepeatCount;
96
cts = CancellationTokenSource.CreateLinkedTokenSource (cancellationToken);
98
var message = string.Format (
99
"Running {0} iterations of {1} ({2}).", repeatCount, mode, uri);
100
OnMessageEvent (message);
103
startTime = DateTime.Now;
107
var time = DateTime.Now - startTime;
108
var completed = string.Format ("Benchmark completed in {0}.", time);
109
WriteLine (completed);
110
WriteLine (string.Empty);
118
protected override HttpClient CreateClient (bool defaultHandler)
120
var client = base.CreateClient (defaultHandler);
121
cts.Token.Register (() => client.CancelPendingRequests ());
127
await SingleRequest ();
128
await SerialRequests (true);
129
await SerialRequests (false);
130
await SerialRequestsOnWorker ();
131
// await ParallelRequests (true);
132
// await ParallelRequests (false);
135
async Task SingleRequest ()
137
var start = DateTime.Now;
138
using (var client = CreateClient (false))
139
await CreateTask (client);
140
WriteLine ("Single request done in {0}.", DateTime.Now - start);
143
string GetHandlerName (bool defaultHandler)
145
return defaultHandler ? "default" : "CFNetwork";
148
async Task SerialRequests (bool defaultHandler)
150
WriteLine ("Starting {0} serial requests.", GetHandlerName (defaultHandler));
152
var start = DateTime.Now;
154
for (int i = 0; i < repeatCount; i++) {
155
using (var client = CreateClient (defaultHandler))
156
await CreateTask (client);
159
var time = DateTime.Now - start;
160
var perRequest = (int)(time.TotalMilliseconds / repeatCount);
162
WriteLine ("Serial {0} requests done in {1} ({2}ms/request).",
163
GetHandlerName (defaultHandler), time, perRequest);
166
async Task SerialRequestsOnWorker ()
168
WriteLine ("Starting serial requests on worker thread.");
170
var worker = new WorkerThread ();
171
var handler = new MessageHandler (worker);
172
var client = new HttpClient (handler, true);
174
var start = DateTime.Now;
177
for (int i = 0; i < repeatCount; i++) {
178
await CreateTask (client);
185
var time = DateTime.Now - start;
186
var perRequest = (int)(time.TotalMilliseconds / repeatCount);
188
WriteLine ("Serial requests on worker thread done in {0} ({1}ms/request).",
193
async Task ParallelRequests (bool defaultHandler)
195
WriteLine ("Starting {0} parallel requests.", GetHandlerName (defaultHandler));
197
var start = DateTime.Now;
199
var clients = new HttpClient [repeatCount];
200
var task = new Task [repeatCount];
202
for (int i = 0; i < task.Length; i++) {
203
clients [i] = CreateClient (defaultHandler);
204
task [i] = CreateTask (clients [i]);
207
await Task.WhenAll (task);
209
var time = DateTime.Now - start;
210
var perRequest = (int)(time.TotalMilliseconds / repeatCount);
212
WriteLine ("Parallel {0} requests done in {1} ({2}ms/request).",
213
GetHandlerName (defaultHandler), time, perRequest);
216
Task CreateTask (HttpClient client)
219
case BenchmarkViewController.ModeTag.GetByteArray:
220
return client.GetByteArrayAsync (uri);
222
case BenchmarkViewController.ModeTag.CheckHeaders:
223
return CheckHeaders (client);
226
throw new InvalidOperationException ();
230
async Task CheckHeaders (HttpClient client)
232
var request = new HttpRequestMessage (HttpMethod.Get, uri);
233
var response = await client.SendAsync (
234
request, HttpCompletionOption.ResponseHeadersRead, cts.Token);