0

我正在编写高频交易软件。我正在尝试优化它。我发现每一秒我都会创建几千个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个。但我每秒多次创建相同的 Instrument 对象,如下所示:

new Instrument { GateId = 0, Ticker = "MSFT" }

即我有许多“MSFT”仪器实例,但我可以在 HashSet/HashMap 或任何地方使用它们,这要归功于覆盖EqualsGetHashCode方法。

Instrument但现在我认为在运行时拥有 10 或 100 个“MSFT”对象(它们彼此相等)是否有意义。

所以我想创建这样的东西:

interface InstrumentFactory {

    public Instrument GetInstrument(int GateId, string Ticker);

}

每次我需要一些乐器时,我只想问问 InstrumentFactory。InstrumentFactory 将在内部将我的 100 个仪器存储在 HashSet 中,并且只会返回缓存的副本。此外,我现在可以删除EqualsGetHashCode方法,因为Instrument每个 gateId + 股票代码对都有一个。

问题:

  • 采用新方法,我的性能会有显着提升吗?
  • 你对新设计有什么看法?当我经常需要相同的对象时,最好使用factory而不是每次使用重写的 Equals 和 GetHashCode 方法创建新对象?
4

2 回答 2

2

您目前无法缓存这些,因为它们是可变的 -Ticker并且GateID具有公共设置器。

我会让它不可变(并密封类),但可能保留EqualsandGetHashCode方法。添加一个构造函数来获取参数,而不是将它们设置为属性。

在这一点上,无论如何,它是一个更好的类IMO(更容易推理不可变类型)并且缓存值是完全合理的。它会让您的应用程序明显更快吗?我们不可能说出来——但你应该能够说出来,假设你已经进行了性能测试。至少这样做是有意义的。

编辑:请注意,您不仅可以HashSet在工厂中使用 a 。您可能需要类似的东西Dictionary<int, Dictionary<string, Instrument>>- 从第一本字典中查找门,然后从门中查找乐器。如果你有一个从 0 开始的已知的、固定数量的门,你甚至可能想要使用一个数组。您还应该考虑创建一个Gate类型。

用于Dictionary.TryGetValue检查门或门内是否存在仪器,然后添加然后懒惰地创建门/仪器,如果之前不存在,则将其放入字典中。

如果您在单个工厂中使用多个线程,则需要使用锁定,或者如果您使用的是 .NET 4,则可以使用ConcurrentDictionary. 当然,这是假设您事先并不了解所有仪器。如果您在开始之前知道一切,那真的很容易 - 只需填充工厂以开始,如果您被要求提供不存在的仪器,则抛出异常。

于 2012-06-23T08:44:03.227 回答
1

如果您只有 100 个不同的对象,但需要数千个实例,那么工厂可能是一种可行的方法,但性能不会改变,除非您有一些策略来改变构造。想到原型模式,但这些对象似乎很容易创建,因此性能不会受到影响。也许一些对象池可以成为一个解决方案。预先创建大量您需要的对象,然后从池中取出实例。让你的对象是不可变的,这是先决条件。拥有一个池,您可以轻松获得对象,如果您不再需要它们,只需将它们放回池中即可。

以下是关于对象池的一些想法: CodeProject on object pooling

于 2012-06-23T09:05:01.853 回答