Skip to content

Commit

Permalink
Close #66 + Performance improved
Browse files Browse the repository at this point in the history
  • Loading branch information
BornToBeRoot committed Nov 28, 2017
1 parent c442aea commit 8d4bb5f
Showing 1 changed file with 52 additions and 34 deletions.
86 changes: 52 additions & 34 deletions Source/NETworkManager/Models/Network/Traceroute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,18 @@ public void TraceAsync(IPAddress ipAddress, TracerouteOptions traceOptions, Canc
Task.Run(() =>
{
byte[] buffer = new byte[traceOptions.Buffer];
int maximumHops = traceOptions.MaximumHops;
int maximumHops = traceOptions.MaximumHops;
bool maximumHopsReached = false;
int pingCount = 3;
// Get the ttl of the ip
using (System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping())
{
PingReply pingReply;
for (int i = 0; i < 3; i++)
for (int i = 0; i < pingCount; i++)
{
pingReply = ping.Send(ipAddress, traceOptions.Timeout, buffer, new System.Net.NetworkInformation.PingOptions() { Ttl = 64, DontFragment = traceOptions.DontFragement });
Expand All @@ -71,59 +73,75 @@ public void TraceAsync(IPAddress ipAddress, TracerouteOptions traceOptions, Canc
}
}
int threads = (pingCount * maximumHops);
// Modify the ThreadPool for better performance
ThreadPool.GetMinThreads(out int workerThreads, out int completionPortThreads);
ThreadPool.SetMinThreads(workerThreads + threads, completionPortThreads + threads);
// Async check all hops
Parallel.For(1, maximumHops + 1, new ParallelOptions() { CancellationToken = cancellationToken }, i =>
try
{
List<Task<Tuple<PingReply, long>>> tasks = new List<Task<Tuple<PingReply, long>>>();
for (int y = 0; y < 3; y++)
ParallelOptions parallelOptions = new ParallelOptions()
{
tasks.Add(Task.Run(() =>
{
Stopwatch stopwatch = new Stopwatch();
CancellationToken = cancellationToken,
MaxDegreeOfParallelism = threads
};
PingReply pingReply;
Parallel.For(1, maximumHops + 1, parallelOptions, i =>
{
List<Task<Tuple<PingReply, long>>> tasks = new List<Task<Tuple<PingReply, long>>>();
using (System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping())
for (int y = 0; y < 3; y++)
{
tasks.Add(Task.Run(() =>
{
stopwatch.Start();
Stopwatch stopwatch = new Stopwatch();
pingReply = ping.Send(ipAddress, traceOptions.Timeout, buffer, new System.Net.NetworkInformation.PingOptions() { Ttl = i, DontFragment = traceOptions.DontFragement });
PingReply pingReply;
stopwatch.Stop();
}
using (System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping())
{
stopwatch.Start();
return Tuple.Create(pingReply, stopwatch.ElapsedMilliseconds);
}));
}
pingReply = ping.Send(ipAddress, traceOptions.Timeout, buffer, new System.Net.NetworkInformation.PingOptions() { Ttl = i, DontFragment = traceOptions.DontFragement });
Task.WaitAll(tasks.ToArray());
stopwatch.Stop();
}
// Here is a good point to cancel (Don't resolve dns...)
if (cancellationToken.IsCancellationRequested)
return;
return Tuple.Create(pingReply, stopwatch.ElapsedMilliseconds);
}));
}
IPAddress ipAddressHop = tasks.FirstOrDefault(x => x.Result.Item1 != null).Result.Item1.Address;
Task.WaitAll(tasks.ToArray());
string hostname = string.Empty;
IPAddress ipAddressHop = tasks.FirstOrDefault(x => x.Result.Item1 != null).Result.Item1.Address;
try
{
if (ipAddressHop != null)
hostname = Dns.GetHostEntry(ipAddressHop).HostName;
}
catch (SocketException) { } // Couldn't resolve hostname
string hostname = string.Empty;
OnHopReceived(new TracerouteHopReceivedArgs(i, tasks[0].Result.Item2, tasks[1].Result.Item2, tasks[2].Result.Item2, ipAddressHop, hostname, tasks[0].Result.Item1.Status, tasks[1].Result.Item1.Status, tasks[2].Result.Item1.Status));
});
try
{
if (ipAddressHop != null)
hostname = Dns.GetHostEntry(ipAddressHop).HostName;
}
catch (SocketException) { } // Couldn't resolve hostname
if (cancellationToken.IsCancellationRequested)
OnHopReceived(new TracerouteHopReceivedArgs(i, tasks[0].Result.Item2, tasks[1].Result.Item2, tasks[2].Result.Item2, ipAddressHop, hostname, tasks[0].Result.Item1.Status, tasks[1].Result.Item1.Status, tasks[2].Result.Item1.Status));
});
}
catch (OperationCanceledException)
{
OnUserHasCanceled();
else if (maximumHopsReached)
return;
}
if (maximumHopsReached)
OnMaximumHopsReached(new MaximumHopsReachedArgs(traceOptions.MaximumHops));
else
OnTraceComplete();
// Reset the ThreadPool to default
ThreadPool.SetMinThreads(workerThreads, completionPortThreads);
}, cancellationToken);
}
#endregion
Expand Down

0 comments on commit 8d4bb5f

Please sign in to comment.