C# String.format速度慢,需要更快的替代方案
我希望得到一些关于如何加速以下功能的建议。具体地说,我希望找到一种更快的方法将数字(大部分是双精度的,IIRC中有一个int)转换成字符串存储为Listview子项。目前,此功能需要9秒来处理16个订单!绝对疯狂,尤其是考虑到除了处理DateTimes的调用之外,这一切都只是字符串转换 我认为listview项目的实际显示很慢,所以我做了一些研究,发现将所有子项目添加到数组并使用Addrange比一次添加一个项目快得多。我实施了改变,但没有得到更好的速度 然后,我在每条生产线周围加上了一些秒表,以缩小导致减速的确切范围;毫不奇怪,对datetime函数的调用速度最慢,但我惊讶地发现string.format调用也非常慢,考虑到它们的数量,占了我大部分时间C# String.format速度慢,需要更快的替代方案,c#,.net,string,string.format,C#,.net,String,String.format,我希望得到一些关于如何加速以下功能的建议。具体地说,我希望找到一种更快的方法将数字(大部分是双精度的,IIRC中有一个int)转换成字符串存储为Listview子项。目前,此功能需要9秒来处理16个订单!绝对疯狂,尤其是考虑到除了处理DateTimes的调用之外,这一切都只是字符串转换 我认为listview项目的实际显示很慢,所以我做了一些研究,发现将所有子项目添加到数组并使用Addrange比一次添加一个项目快得多。我实施了改变,但没有得到更好的速度 然后,我在每条生产线周围加上了一些秒表,
private void ProcessOrders(List<MyOrder> myOrders)
{
lvItems.Items.Clear();
marketInfo = new MarketInfo();
ListViewItem[] myItems = new ListViewItem[myOrders.Count];
string[] mySubItems = new string[8];
int counter = 0;
MarketInfo.GetTime();
CurrentTime = MarketInfo.CurrentTime;
DateTime OrderIssueDate = new DateTime();
foreach (MyOrder myOrder in myOrders)
{
string orderIsBuySell = "Buy";
if (!myOrder.IsBuyOrder)
orderIsBuySell = "Sell";
var listItem = new ListViewItem(orderIsBuySell);
mySubItems[0] = (myOrder.Name);
mySubItems[1] = (string.Format("{0:g}", myOrder.QuantityRemaining) + "/" + string.Format("{0:g}", myOrder.InitialQuantity));
mySubItems[2] = (string.Format("{0:f}", myOrder.Price));
mySubItems[3] = (myOrder.Local);
if (myOrder.IsBuyOrder)
{
if (myOrder.Range == -1)
mySubItems[4] = ("Local");
else
mySubItems[4] = (string.Format("{0:g}", myOrder.Range));
}
else
mySubItems[4] = ("N/A");
mySubItems[5] = (string.Format("{0:g}", myOrder.MinQuantityToBuy));
string IssueDateString = (myOrder.DateWhenIssued + " " + myOrder.TimeWhenIssued);
if (DateTime.TryParse(IssueDateString, out OrderIssueDate))
mySubItems[6] = (string.Format(MarketInfo.ParseTimeData(CurrentTime, OrderIssueDate, myOrder.Duration)));
else
mySubItems[6] = "Error getting date";
mySubItems[7] = (string.Format("{0:g}", myOrder.ID));
listItem.SubItems.AddRange(mySubItems);
myItems[counter] = listItem;
counter++;
}
lvItems.BeginUpdate();
lvItems.Items.AddRange(myItems.ToArray());
lvItems.EndUpdate();
}
private void ProcessOrders(列出myorder)
{
lvItems.Items.Clear();
marketInfo=新的marketInfo();
ListViewItem[]myItems=新ListViewItem[myOrders.Count];
string[]mySubItems=新字符串[8];
int计数器=0;
MarketInfo.GetTime();
CurrentTime=MarketInfo.CurrentTime;
DateTime OrderIssueDate=新的日期时间();
foreach(MyOrder中的MyOrder)
{
字符串orderIsBuySell=“Buy”;
如果(!myOrder.IsBuyOrder)
orderIsBuySell=“Sell”;
var listItem=新的ListViewItem(orderIsBuySell);
mySubItems[0]=(myOrder.Name);
mySubItems[1]=(string.Format(“{0:g}”,myOrder.QuantityRemaining)+“/”+string.Format(“{0:g}”,myOrder.InitialQuantity));
mySubItems[2]=(string.Format(“{0:f}”,myOrder.Price));
mySubItems[3]=(myOrder.Local);
if(myOrder.IsBuyOrder)
{
如果(myOrder.Range==-1)
mySubItems[4]=(“本地”);
其他的
mySubItems[4]=(string.Format(“{0:g}”,myOrder.Range));
}
其他的
mySubItems[4]=(“不适用”);
mySubItems[5]=(string.Format(“{0:g}”,myOrder.MinQuantityToBuy));
字符串IssuedTestRing=(myOrder.DateWhenIssued+“”+myOrder.TimeWhenIssued);
if(DateTime.TryParse(IssuedTestRing,OutOrderIssuedate))
mySubItems[6]=(string.Format(MarketInfo.ParseTimeData(CurrentTime、ordersissueDate、myOrder.Duration));
其他的
mySubItems[6]=“获取日期时出错”;
mySubItems[7]=(string.Format(“{0:g}”,myOrder.ID));
listItem.SubItems.AddRange(mySubItems);
myItems[计数器]=列表项;
计数器++;
}
lvItems.BeginUpdate();
lvItems.Items.AddRange(myItems.ToArray());
lvItems.EndUpdate();
}
以下是示例运行的时间数据:0:166686
1:264779
2:273716
3:136698
4:587902
5:368816
6:955478
7:128981 其中数字等于数组的索引。所有其他的线都是如此低的滴答声,以至于与这些线相比可以忽略不计 虽然我希望能够使用string.format的数字格式进行漂亮的输出,但我希望能够在我的有生之年加载更多的订单列表,因此,如果有一种比string.format快得多但没有铃声和口哨的替代方法,我完全赞成
编辑:感谢所有建议myOrder类使用getter方法的人,而不是像我最初认为的那样实际存储变量。我检查了一下,果然,这就是我减速的原因。虽然我无法访问该类来更改它,但我能够借助方法调用来填充myOrder,并将每个变量复制到同一调用中的列表中,然后在填充Listview时使用该列表。现在几乎立刻就有人来了。再次感谢。我发现很难相信简单的string.Format调用会导致您的速度慢问题-这通常是一个非常快速的调用,特别是对于像您大多数这样的简单调用 但有一件事可能会给你几微秒的时间 替换
string.Format("{0:g}", myOrder.MinQuantityToBuy)
与
当您使用单一值的直接格式时,这将起作用,但对于更复杂的调用则没有任何好处。我将所有string.format调用放入一个循环中,并能够在一秒钟内将它们全部运行100万次,因此您的问题不是string.format…而是代码中的其他地方
也许这些属性中的某些在其getter方法中具有逻辑性?如果你注释掉listview的所有代码,你会得到什么样的时间?这绝对不是字符串格式让你慢下来。怀疑从myOrder访问属性 在其中一个format调用中,尝试声明几个局部变量并将它们设置为您尝试格式化的属性,然后将这些局部变量传递给yoru string.format和retime。您可能会发现string.Format现在以闪电般的速度运行 现在,属性访问通常不需要很多时间来运行。但是,我看到一些类记录了每个属性访问(用于审计跟踪)。检查是否存在这种情况,以及是否有操作阻止您的财产访问权立即返回 如果有某个操作持有属性访问权,请尝试将这些操作排队(例如,将日志调用排队),并让后台线程执行这些操作。立即返回属性访问权限 此外,切勿将运行缓慢的代码(例如,复杂的计算)放入属性访问器/获取器,也不要将具有副作用的代码放入属性访问器/获取器。使用该类的人不会意识到它将被删除
myOrder.MinQuantityToBuy.ToString("g")
private void ProcessOrders(List<MyOrder> myOrders)
{
lvItems.Items.Clear();
marketInfo = new MarketInfo();
ListViewItem[] myItems = new ListViewItem[myOrders.Count];
string[] mySubItems = new string[8];
int counter = 0;
MarketInfo.GetTime();
CurrentTime = MarketInfo.CurrentTime;
// ReSharper disable TooWideLocalVariableScope
DateTime orderIssueDate;
// ReSharper restore TooWideLocalVariableScope
foreach (MyOrder myOrder in myOrders)
{
string orderIsBuySell = myOrder.IsBuyOrder ? "Buy" : "Sell";
var listItem = new ListViewItem(orderIsBuySell);
mySubItems[0] = myOrder.Name;
mySubItems[1] = string.Format("{0:g}/{1:g}", myOrder.QuantityRemaining, myOrder.InitialQuantity);
mySubItems[2] = myOrder.Price.ToString("f");
mySubItems[3] = myOrder.Local;
if (myOrder.IsBuyOrder)
mySubItems[4] = myOrder.Range == -1 ? "Local" : myOrder.Range.ToString("g");
else
mySubItems[4] = "N/A";
mySubItems[5] = myOrder.MinQuantityToBuy.ToString("g");
// This code smells:
string issueDateString = string.Format("{0} {1}", myOrder.DateWhenIssued, myOrder.TimeWhenIssued);
if (DateTime.TryParse(issueDateString, out orderIssueDate))
mySubItems[6] = MarketInfo.ParseTimeData(CurrentTime, orderIssueDate, myOrder.Duration);
else
mySubItems[6] = "Error getting date";
mySubItems[7] = myOrder.ID.ToString("g");
listItem.SubItems.AddRange(mySubItems);
myItems[counter] = listItem;
counter++;
}
lvItems.BeginUpdate();
lvItems.Items.AddRange(myItems.ToArray());
lvItems.EndUpdate();
}