C# 我应该缓存使用密集型的简单类吗?
我在写高频交易软件。我正在尝试优化它。我发现每秒钟我都会创建数千个C# 我应该缓存使用密集型的简单类吗?,c#,C#,我在写高频交易软件。我正在尝试优化它。我发现每秒钟我都会创建数千个Instrument对象,这个类的源代码如下: public class Instrument { public int GateId { get; set; } public string Ticker { get; set; } public override string ToString() { return "GateID: " + GateId + " Ticker:
Instrument
对象,这个类的源代码如下:
public class Instrument
{
public int GateId { get; set; }
public string Ticker { get; set; }
public override string ToString()
{
return "GateID: " + GateId + " Ticker: " + Ticker + '.';
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
Instrument instrument = obj as Instrument;
if (instrument == null)
{
return false;
}
return (GateId.Equals(instrument.GateId)) && (Ticker.Equals(instrument.Ticker));
}
public override int GetHashCode()
{
int hash = 13;
hash = (hash * 7) + GateId;
hash = (hash * 7) + Ticker.GetHashCode();
return hash;
}
}
仪器的实际数量非常有限。总共大约100英镑。但我一直在每秒多次创建相同的仪器对象,如下所示:
new Instrument { GateId = 0, Ticker = "MSFT" }
interface InstrumentFactory {
public Instrument GetInstrument(int GateId, string Ticker);
}
也就是说,我有许多“MSFT”工具的实例,但由于覆盖了Equals
和GetHashCode
方法,我可以在HashSet/HashMap或任何地方使用它们
但现在我认为在运行时使用10或100“MSFT”Instrument
对象(它们彼此相等)是否有意义
所以我想创造这样的东西:
new Instrument { GateId = 0, Ticker = "MSFT" }
interface InstrumentFactory {
public Instrument GetInstrument(int GateId, string Ticker);
}
每次我需要一些仪器时,我只想问问仪器厂。InstrumentFactory将在内部将我的100个仪器存储在HashSet中,并返回缓存副本。此外,我现在可以删除Equals
和GetHashCode
方法,因为对于每个gateId+股票代码对,我只有一个Instrument
问题:
- 有了新的方法,我会有显著的性能改进吗
- 你觉得新设计怎么样?当我经常需要相同的对象时,是否最好使用
,而不是每次使用重写的Equals和GetHashCode方法创建新对象factory
Ticker
和GateID
具有公共设置器
我将使其不可变(并密封该类),但可能保留Equals
和GetHashCode
方法。添加构造函数以获取参数,而不是将其设置为属性
在这一点上,它是一个更好的类(更容易对不可变类型进行推理),并且缓存值是完全合理的。它会使您的应用程序明显更快吗?我们不可能这么说,但假设您已经进行了性能测试,您应该能够这么说。至少这样做是有道理的
编辑:请注意,您不仅能够在工厂中使用HashSet
。您可能需要类似于字典的东西
——从第一本字典中查找gate,然后从gate中查找instrument。如果已知固定数量的门从0开始,则可能需要使用数组。您还应该考虑创建<代码>门< /代码>类型。
使用Dictionary.TryGetValue
检查闸门内是否存在闸门或仪器,然后添加,然后懒洋洋地创建闸门/仪器,如果之前不存在,则将其放入字典中
如果在单个工厂中使用多个线程,则需要使用锁定,或者如果使用.NET 4,则可以使用
ConcurrentDictionary
。当然,这是假设你不知道前面所有的仪器。如果你在开始之前就知道了一切,那就很容易了——只要填充工厂就可以开始了,如果你被要求使用一个不存在的仪器,就会抛出一个异常。你现在不能缓存这些,因为它们是可变的,股票代码
和GateID
都有公共设置器
我将使其不可变(并密封该类),但可能保留Equals
和GetHashCode
方法。添加构造函数以获取参数,而不是将其设置为属性
在这一点上,它是一个更好的类(更容易对不可变类型进行推理),并且缓存值是完全合理的。它会使您的应用程序明显更快吗?我们不可能这么说,但假设您已经进行了性能测试,您应该能够这么说。至少这样做是有道理的
编辑:请注意,您不仅能够在工厂中使用HashSet
。您可能需要类似于字典的东西
——从第一本字典中查找gate,然后从gate中查找instrument。如果已知固定数量的门从0开始,则可能需要使用数组。您还应该考虑创建<代码>门< /代码>类型。
使用Dictionary.TryGetValue
检查闸门内是否存在闸门或仪器,然后添加,然后懒洋洋地创建闸门/仪器,如果之前不存在,则将其放入字典中
如果在单个工厂中使用多个线程,则需要使用锁定,或者如果使用.NET 4,则可以使用
ConcurrentDictionary
。当然,这是假设你不知道前面所有的仪器。如果你在开始之前就知道了一切,那么这真的很容易——只要填充工厂就可以了,如果你需要一个不存在的仪器,就会抛出一个异常。如果你只有100个不同的对象,但你需要数千个这样的实例,那么工厂可能是一个不错的选择,但是,除非你有一些策略来改变建筑的某些方面,否则性能不会改变。我们想到了原型模式,但这些对象似乎很容易创建,因此性能不会受到影响。也许某个对象池可以是一个解决方案。预先创建大量您需要的对象,并从池中取出实例。让你的对象是不可变的,这是先决条件。拥有一个池,您可以轻松获得对象,如果不再需要它们,只需将它们放回池中即可
以下是关于对象池的一些想法:
如果您只有100个不同的对象,但您需要数千个这些对象的实例,那么工厂可能是一条出路,但性能不会改变,除非您有一些策略来改变有关构造的内容。我们想到了原型模式,但这些对象似乎很容易创建,因此性能不会受到影响。也许某个对象池可以是一个解决方案。预处理批次o