我正在研究一个项目的一部分,它解析Postgres数据库服务器的日志。 该应用程序是在C sharp Framework 4.0中开发的。
生成一个日志,并在DataGridView上显示以下列
resultCode Statement Starttime Duration
XT001 select * from PizzaMade 01-02-2012 03:10:14 00:04:10
我的工作是按照以下格式从Grid中可用的数据生成统计数据
Statement Count countpercent Occurs_on
select * from PizzaMade 3 1.42 01/02 at 03pm [00:04:10], 01/02 at 04 [00:01:04]
select id,qty,table from PizzaMade 12 5.12 ...........
基本上统计数据反映了以下内容
»统计数据首先使用for循环
生成Datatableforeach(DataGridViewRow dr in LogGrid.Rows)
{
// search in the Datatable if the statement is present
// if it is then add count , add starttime and duration to the column
// if not then add a newrow
}
»填充数据表后,我使用循环计算Totalcount
int totalcount = 0;
foreach (DataRow drin StatTable.Rows)
{
totalcount = totalcount + Convert.ToInt32(dr["count"].ToString());
}
»计算计数后,有一个循环来计算百分比
foreach (DataRow dr in StatTable.Rows)
{
int c = Convert.ToInt32(dr["count"].ToString());
dr["countpercent"] = (c/totalcount)*100;
}
虽然一切似乎都没问题,但整个方法都很慢,行数很多。
感谢 Arvind的
答案 0 :(得分:1)
由于您正在解析文本日志,因此可以通过不在网格中而是在对象中操作来提高性能。此外,网格可以绑定到已解析日志列表。它可能是这样的:
public class LogItem
{
public string ResultCode { get;set;}
public string Statement { get;set;}
public DateTime StartTime { get;set;}
public TimeSpan Duration { get;set;}
}
然后您的网格可以绑定到BindingList,其中包含所有已解析的日志项。拥有列表时,您可以更统一的方式访问数据:
foreach (string statement in logItems.Select(x => x.Statement).Distinct())
{
int count = logItems.Count(x => x.Statement == statement);
double percentage = count / logItems.Count();
// any additional data
}
如果您希望获得额外的性能和想象力,可以将所有已解析的日志文件保存到数据库并创建对必要数据的查询。
答案 1 :(得分:1)
我有一些建议,
你可以使用linq在你的循环过程中使用这样的东西。基本上linq使用优化良好的查询,性能很好。
DataTable obj = new DataTable();
obj.Columns.Add("count",typeof(Int32));
DataRow dr = obj.NewRow();
dr[0] = "10";
obj.Rows.Add(dr);
DataRow dr1 = obj.NewRow();
dr1[0] = "5";
obj.Rows.Add(dr1);
obj.Columns.Add("countpercentage");
int intCount = (from DataRow drrow in obj.Rows
select drrow.Field<int>("count")).Sum();
(from DataRow drtemp in obj.Rows
select drtemp).ToList<DataRow>()
.ForEach(x => x.SetField<string>("countpercentage", ((x.Field<Int32>("count")*100) / intCount).ToString()));