I have a specific problem with a bottleneck in my code that I would like to iron out, but I would like to know generally, for the future, how I would go about finding quickly where a bottleneck occurs without having to re-invent the wheel.
Here is my method's code but like I said, I'd like to know how to generally find out how long the linq query is taking or how long the datatable is taking to build, etc....
public static DataTable GetPivotDataTable(this IQueryable<WbsNumber> table, Months month)
{
FmToolDataContext dataContext = new FmToolDataContext();
DataTable dt = new DataTable();
dt.Columns.Add("id", typeof(string));
dt.Columns.Add("wbsNumber", typeof(string));
dt.Columns.Add("wbsTitle", typeof(string));
dt.Columns.Add("number", typeof(string));
dt.Columns.Add("vendor", typeof(string));
dt.Columns.Add("programFund", typeof(string));
dt.Columns.Add("committedAmount", typeof(decimal));
dt.Columns.Add("obligatedAmount", typeof(decimal));
dt.Columns.Add("costedAmount", typeof(decimal));
dt.Columns.Add("costOverObligationsAmount", typeof(decimal));
foreach (WbsNumber wbs in table)
{
// Get PRs for this Project Detail
var prAmounts = dataContext.PrAmounts.Where(_pra => _pra.isCurrent && !_pra.requiresAudit
&& _pra.PrDetail.isActive && _pra.PrDetail.WbsNumber == wbs
&& _pra.Import.fiscalYear == (int)HttpContext.Current.Session["FiscalYear"]);
foreach(PrAmount pra in prAmounts)
{
DataRow row = dt.NewRow();
row["id"] = wbs.id;
row["wbsNumber"] = wbs.displayString;
row["wbsTitle"] = wbs.wbsTitlesId != null ? wbs.WbsTitle.name : "(blank)";
row["number"] = pra.PrDetail.Pr.number;
row["vendor"] = pra.PrDetail.Pr.GetPrVendorName();
row["programFund"] = pra.PrDetail.ProgramFund.name;
row["committedAmount"] = pra.CommittedMonthlyRecord.GetMonth(month);
row["obligatedAmount"] = pra.ObligatedMonthlyRecord.GetMonth(month);
row["costedAmount"] = pra.CostedMonthlyRecord.GetMonth(month);
row["costOverObligationsAmount"] = pra.CostOverObligationsMonthlyRecord.GetMonth(month);
dt.Rows.Add(row);
}
// Get the P-Cards for this Project Detail
var pCardAmounts = dataContext.PCardAmounts.Where(_pca => _pca.isCurrent && !_pca.requiresAudit
&& _pca.PCardTransaction.isActive && _pca.PCardTransaction.WbsNumber == wbs
&& _pca.Import.fiscalYear == (int)HttpContext.Current.Session["FiscalYear"]);
foreach (PCardAmount pca in pCardAmounts)
{
DataRow row = dt.NewRow();
row["id"] = wbs.id;
row["wbsNumber"] = wbs.displayString;
row["wbsTitle"] = wbs.wbsTitlesId != null ? wbs.WbsTitle.name : "(blank)";
row["number"] = pca.PCardTransaction.number;
row["vendor"] = pca.PCardTransaction.bwVendorsId != null ? pca.PCardTransaction.BwVendor.name : "(blank)";
row["programFund"] = pca.PCardTransaction.ProgramFund.name;
row["committedAmount"] = pca.CommittedMonthlyRecord.GetMonth(month);
row["obligatedAmount"] = pca.ObligatedMonthlyRecord.GetMonth(month);
row["costedAmount"] = pca.CostedMonthlyRecord.GetMonth(month);
row["costOverObligationsAmount"] = pca.CostOverObligationsMonthlyRecord.GetMonth(month);
dt.Rows.Add(row);
}
}
return dt;
}
I'm not sure if there's some magic solution to this, aside from maybe using a profiler or some other tool. Without a tool, typically I would start by looking at what clearly couldn't be a bottleneck - you should have some idea of what takes no time at all (mathematical operations, assignments, etc.) and what might take a lot of time (loops, image operations, etc.). Then all you need to do to confirm your guess is to get the time before the operation and the time after the operation, then subtract them to see how many ms each thing took. Chances are the differences will be very very small except for one or two code blocks. Then you have your answer.
You should utilize a performance tool to help find the bottleneck. JetBrains dotTrace is one such example. These types of tools can help with both memory and timing analysis
A Profiler is the tool that could help you.
Microsoft has a choice of profiler tools in msdn. The red gate profiler is not listed but it worth to use too.
Your best bet is to download a profiling application like Red Gate ANTS Performance Profiler
It'll help you pinpoint the real problem (performance issues aren't always what they seem on the surface).