我构建了一个程序来解析Fix消息列表,并将它们存储为引用消息。这些修复消息的形式是超过1.5 in的压缩文本文件。
public class Contract
{
public string ExchangeId { get; set; } = "?";
public string ExchangeSymbol { get; set; } // Setting this property in my code.
// I also group Quote by this property below in my dictionary, see below.
}
public class Quote
{
public Contract Contract = new Contract();
public decimal Ask = 0M;
public decimal Bid = 0M;
// ...
}
public class QuoteMessage
{
public List<Quote> Quotes = new List<Quote>();
// ...
}
每个QuoteMessage
可以有多个引号。我将它们存储在List<QuoteMessage>
中。在这个列表生成之后,我需要根据他们的合同存储报价(而不是报价消息)来分析它们。为此,我运行一个SelectMany
并从每个QuoteMessage
中提取一个引号列表,将它们输入到Dictionary<Contract, List<Quote>>
字典中。在初始化字典时,我要确保有合适的IComparable<Contract>
。
问题是,列表中的每个元素几乎需要半个小时才能遍历,并将它们插入字典中:
public Dictionary<Contract, List<Quote>> SortQuoteByContract(List<Quote> quotes)
{
var contractDict = new Dictionary<Contract, List<Quote>>(new IComparable<Contract>());
foreach (Quote quote in quotes)
{
if (!contractDict.ContainsKey(quote.Contract))
{
contractDict[quote.Contract] = new List<Quote>();
}
contractDict[quote.Contract] = quote; // Line A
return contractDict;
}
有没有办法加快速度呢?据我所知,我并没有创建引用本身的任何副本(在A行上),只是在<Contract, List<Quote>>
字典中存储了一个指向其在内存中位置的指针。这是正确的吗?我想让这个分组尽可能快。一旦报价按合同分组,我就可以在几秒钟内对所有报价进行分析。
谢谢!
发布于 2020-03-02 01:43:25
如果你正在寻找优化,你应该找到发生内存分配的地方。在您的情况下,每次创建新列表时都会发生分配,并且每次向列表中添加项目时都可能发生分配。
采取另一种完全不使用字典的方法:按约定对列表进行排序,然后遍历列表。
假设您有一个单独的批处理处理器类:
interface IContractBatchProcessor
{
void OnContractStart(Contract contract);
void ProcessQuote(Quote quote);
void OnContractEnd()
}
现在,您可以像这样处理列表:
static int CompareByContract(Quote q1, Quote q2)
{
// TODO
}
void Process(List<Quote> quote, IContractBatchProcessor processor)
{
list.Sort(CompareByContract);
Contract lastContract = null;
foreach(var quote in list)
{
if(quote.Contract != lastContract)
{
if(lastContract != null)
{
processor.OnContractEnd();
}
processor.OnContractStart(quote.Contract);
lastContract = quote.Contract;
}
processor.ProcessQuote(quote);
}
processor.OnContractEnd();
}
这是在运行接受委托作为参数的List.Sort method。
这种方法会更快,因为您正在执行列表的就地排序,因此没有额外的内存分配。
发布于 2020-03-02 03:06:17
使用PLINQ
和ToLookup
的代码肯定会比您当前的代码更快。它也很容易阅读,而且从方法使用者的角度来看,也很容易使用。
它将要求您在Contract
类中覆盖Equals
和GetHashCode
,或者编写一个实现IComparer<Contract>
的类,该类只是Equals
和GetHashCode
的外部接口。
public ILookup<Contract, Quote> SortQuoteByContract(List<Quote> quotes) =>
quotes.AsParallel().ToLookup(_ => _.Contract);
public ILookup<Contract, Quote> SortQuoteByContract(List<Quote> quotes) =>
quotes.AsParallel().ToLookup(_ => _.Contract, new ContractComparer());
https://stackoverflow.com/questions/60481258
复制相似问题