如何提高以下代码的性能?
How to improve the performance of below code?
我编写了一个代码来 ping 网络中的 300 个系统并将状态 (offline/online) 更新到 Access 数据库文件中。
我正在为此使用任务 class。 Ping 300 个系统只用了不到一秒,但将这些状态插入数据库文件需要将近 30 到 40 秒。
它降低了我的应用程序的性能,请查看我的代码。如果
主要方法
private static void Main(string[] args)
{
#region Reading IpAdddress
List<string> address = new List<string>();
Task t = Task.Run(() =>
{
var reader = new StreamReader(File.OpenRead(Environment.CurrentDirectory + @"\address.csv"));
while (!reader.EndOfStream)
{
var lines = reader.ReadLine();
var values = lines.Split(';');
address.Add(values[0]);
}
});
#endregion
Stopwatch timeSpan = Stopwatch.StartNew();
t.Wait();
AsyncPingTask(address).Wait();
Console.WriteLine("Update Completed");
Console.WriteLine(timeSpan.ElapsedMilliseconds);
Console.ReadLine();
}
Ping任务
private static async Task AsyncPingTask(List<string> ipaddress)
{
try
{
Console.WriteLine("Ping Started");
var pingTasks = ipaddress.Select(ip =>
{
return new Ping().SendTaskAsync(ip);
}).ToList();
var replies= await Task.WhenAll(pingTasks);
Console.WriteLine("Ping Completed");
int online, offline;
online = 0;
offline = 0;
Console.WriteLine("Update in progress...");
foreach (var pingReply in replies)
{
var status = "";
if (pingReply.Reply.Status.ToString() == "Success")
{
online++;
status = "Online";
}
else
{
status = "Offline";
offline++;
}
Program p = new Program();
Parallel.Invoke(() =>
{
p.UpdateSystemStatus(pingReply.Address, status);
});
}
Console.WriteLine("Online Systems : {0}", online);
Console.WriteLine("Offline Systems : {0}", offline);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
更新状态方法
private void UpdateSystemStatus(string ipAddr, string status)
{
using (OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\/Topology.accdb"))
{
string query = "UPDATE SystemStatus SET SystemStatus=@SystemStatus WHERE IP='" + ipAddr + "'";
OleDbCommand cmd = new OleDbCommand(query, con);
con.Open();
cmd.Parameters.AddWithValue("@SystemStatus", status);
cmd.ExecuteNonQuery();
}
}
这不是我的专业领域,但我的猜测是,为每条更新的记录创建新的 OleDbConnection
会产生大量开销。我可以想象它至少必须在文件系统中打开访问数据库、检查权限、解析一堆东西等等……一种只创建一次连接的方法可能会更好。我还看到有一些事务机制可能会提高性能。
using (OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\/Topology.accdb"))
{
con.Open();
var trans = con.BeginTransaction();
foreach (var pingReply in replies)
{
var status = "";
if (pingReply.Reply.Status.ToString() == "Success")
{
online++;
status = "Online";
}
else
{
status = "Offline";
offline++;
}
string query = "UPDATE SystemStatus SET SystemStatus=@SystemStatus WHERE IP='" + ipAddr + "'";
OleDbCommand cmd = new OleDbCommand(query, con);
cmd.Transaction = trans;
cmd.Parameters.AddWithValue("@SystemStatus", status);
cmd.ExecuteNonQuery();
}
trans.Commit();
}
我编写了一个代码来 ping 网络中的 300 个系统并将状态 (offline/online) 更新到 Access 数据库文件中。
我正在为此使用任务 class。 Ping 300 个系统只用了不到一秒,但将这些状态插入数据库文件需要将近 30 到 40 秒。
它降低了我的应用程序的性能,请查看我的代码。如果
主要方法
private static void Main(string[] args)
{
#region Reading IpAdddress
List<string> address = new List<string>();
Task t = Task.Run(() =>
{
var reader = new StreamReader(File.OpenRead(Environment.CurrentDirectory + @"\address.csv"));
while (!reader.EndOfStream)
{
var lines = reader.ReadLine();
var values = lines.Split(';');
address.Add(values[0]);
}
});
#endregion
Stopwatch timeSpan = Stopwatch.StartNew();
t.Wait();
AsyncPingTask(address).Wait();
Console.WriteLine("Update Completed");
Console.WriteLine(timeSpan.ElapsedMilliseconds);
Console.ReadLine();
}
Ping任务
private static async Task AsyncPingTask(List<string> ipaddress)
{
try
{
Console.WriteLine("Ping Started");
var pingTasks = ipaddress.Select(ip =>
{
return new Ping().SendTaskAsync(ip);
}).ToList();
var replies= await Task.WhenAll(pingTasks);
Console.WriteLine("Ping Completed");
int online, offline;
online = 0;
offline = 0;
Console.WriteLine("Update in progress...");
foreach (var pingReply in replies)
{
var status = "";
if (pingReply.Reply.Status.ToString() == "Success")
{
online++;
status = "Online";
}
else
{
status = "Offline";
offline++;
}
Program p = new Program();
Parallel.Invoke(() =>
{
p.UpdateSystemStatus(pingReply.Address, status);
});
}
Console.WriteLine("Online Systems : {0}", online);
Console.WriteLine("Offline Systems : {0}", offline);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
更新状态方法
private void UpdateSystemStatus(string ipAddr, string status)
{
using (OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\/Topology.accdb"))
{
string query = "UPDATE SystemStatus SET SystemStatus=@SystemStatus WHERE IP='" + ipAddr + "'";
OleDbCommand cmd = new OleDbCommand(query, con);
con.Open();
cmd.Parameters.AddWithValue("@SystemStatus", status);
cmd.ExecuteNonQuery();
}
}
这不是我的专业领域,但我的猜测是,为每条更新的记录创建新的 OleDbConnection
会产生大量开销。我可以想象它至少必须在文件系统中打开访问数据库、检查权限、解析一堆东西等等……一种只创建一次连接的方法可能会更好。我还看到有一些事务机制可能会提高性能。
using (OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\/Topology.accdb"))
{
con.Open();
var trans = con.BeginTransaction();
foreach (var pingReply in replies)
{
var status = "";
if (pingReply.Reply.Status.ToString() == "Success")
{
online++;
status = "Online";
}
else
{
status = "Offline";
offline++;
}
string query = "UPDATE SystemStatus SET SystemStatus=@SystemStatus WHERE IP='" + ipAddr + "'";
OleDbCommand cmd = new OleDbCommand(query, con);
cmd.Transaction = trans;
cmd.Parameters.AddWithValue("@SystemStatus", status);
cmd.ExecuteNonQuery();
}
trans.Commit();
}