Reputation: 506
I am trying to send about 20 messages for a given time span. I want to log the time the request is received. Now For this time shown below
var startTime = DateTime.Now;
var timeoutSpan = TimeSpan.FromMilliseconds(1000);
var count = 0;
while ((DateTime.Now - startTime) <= timeoutSpan)
{
foreach (string message in messages)
{
txtRequest.Text = message;
//this sends request to my service that logs a request
sendMessageResult = client.SendMessage("Test", txtRequest.Text);
count++;
}
}
Lets say I send the message around Time = 2014-03-06 09:46:47:334 AM
I want the recieved time of the request of all the messages in a loop to be very similar but right now the gap is as followes
request A Time = 2014-03-06 09:46:47:334 AM
count:1
request B Time = 2014-03-06 09:46:47:385 AM
count:2
request C Time = 2014-03-06 09:46:47:414 AM
App.config
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="meta">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="meta" name="MyService.Operator">
<endpoint address="" binding="basicHttpBinding" contract="MyService.IOperator" />
<host>
<baseAddresses>
<add baseAddress="http://MyService" />
</baseAddresses>
</host>
</service>
</services>
How can I make the milliseconds of the requests to be very close or Equal(if possible) to one another? as you can see request B is has .385 milliseconds how can I make a request which are sent around same time?
Upvotes: 0
Views: 197
Reputation: 42453
If you leverage the TPL in my limited testing (client and server on the same box and client and server on seperate boxes with a GB network connection) I gain better results if I don't reuse the wcf-client but create a new one for every thread. I tested this with the default VS2010 WcfApplication template as a x64 .Net 4.0 executable.
My code looks like this:
// no multi-threading, one client
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
using (var wc = new ServiceReference1.Service1Client())
{
for (int x = 0; x < 200; x++)
{
wc.SendMessage("test", messages[x]);
}
}
sw.Stop();
Console.WriteLine("plain for: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();
// classic Threadpool
sw.Start();
using (var wc = new ServiceReference1.Service1Client())
{
var _countdown = new CountdownEvent(200);
for (int x = 0; x < 200; x++)
{
ThreadPool.QueueUserWorkItem((state) =>
{
// try/catch to guarantee that _countdown.Signal is always called
try
{
wc.SendMessage("Test",messages[(int) state]);
}
finally
{
_countdown.Signal();
}
}, x);
}
_countdown.Wait();
}
sw.Stop();
Console.WriteLine("ThreadPool: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();
// multi-threading, one wcf client
sw.Start();
using (var wc = new ServiceReference1.Service1Client())
{
Parallel.For(0, 200, x =>
{
wc.SendMessage("test", messages[x]);
});
}
sw.Stop();
Console.WriteLine("tpl paralel for: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();
// multi-threading, client per thread
sw.Start();
int cnt = 0;
Parallel.For(
0,
200,
() => { return new ServiceReference1.Service1Client(); },
(x,pls,wc) =>
{
wc.SendMessage("test", messages[x]);
System.Threading.Interlocked.Increment(ref cnt); // for all done check
return wc;
},
client => {client.Close(); ((IDisposable) client).Dispose();}
);
sw.Stop();
Console.WriteLine("tpl wc per thread paralel for: {0} ms ({1})", sw.ElapsedMilliseconds, cnt);
Typical timings in my network environment (release buid):
plain for: 769 ms
threadpool: 609 ms
tpl paralel for: 499 ms
tpl wc per thread paralel for: 225 ms
When running everything on the same box the timings between plain and tpl paralel become a lot closer.
Do notice that now and then timings jump due to network and/or cpu loads. I didn't analyze CPU or memeory loads.
Based on this test and setting you could conclude the Parallel.For with per thread creation of the webclient is the quickest.
When optimizing for performance make sure to keep testing, with release builds on your target hardware and only change one parameter/design choice per run.
Upvotes: 0
Reputation: 1697
You can do:
Parallel.For(0, 20, p =>
{
var sendMessageResult = client.SendUNIMessage("Test", messages[p]);
});
Upvotes: 1