いくつかの座標をキーで参照するために、すべての種類の効率的なパターンマッチングを可能にするため、識別された共用体を使用したいと考えました。識別された共用体型のために速いCustomEqualityとCustomComparisonを実装する
はfollwoingコードsnipetを考えてみましょう:
[<CustomEquality; CustomComparison>]
type Coord =
| Spot of AssetKey
| Vol of AssetKey * DateTime option
| Rate of Currency
.....
member this.sortKey =
match this with
| Spot(key) -> (0 , key.toString)
| Vol(key) -> (1 , key.toString)
| Vol(key, Some(t)) -> (2 , key.toString + t.ToShortString())
| Rate(cur) -> (3 , cur.toString)
......
interface IComparable with
member this.CompareTo(obj) =
match obj with
| :? Coord as other -> compare this.sortKey other.sortKey
| _ -> invalidArg "obj" "not a Coord type"
override this.Equals(obj) =
match obj with
| :? Coord as other -> this.sortKey = other.sortKey
| _ -> false
override this.GetHashCode() = this.sortKey.GetHashCode()
私は特定のソート順序を強制する必要があります。例えば、スポット< Vol。 sortKeyメンバ関数でそれを強制します。
AssetKeyのは、再び非常に類似した判別共用体型です:
[<StructuralEqualityAttribute; StructuralComparisonAttribute>]
type AssetKey =
| Equity of string
| EquityIndex of string
.....
だから、これはすべてがうまく動作しますが、それは遅いです。私が見る限り、sortKey関数が呼び出されると、キー全体が再び構築されます。特にtoString関数が再び呼び出されます。
明白な改善点は、ソリューションよりもハックの多いキャッシングレイヤーを追加することです。
さらに最適化するには、文字列にハッシュキーを使用する方法があります。しかし、ここでもハッシュキーをキャッシュする必要があるため、キャッシングを追加する必要があります。すべてを再計算する必要はありません。
私は構造体やクラスを使用する場合、パフォーマンスの最適化が容易になるだろうが、その後、私はよく行われている別のアプローチ、どうなるか例えば
match c with
| Coord.Vol(ak, _) when ak = assetKey -> true
| _ -> false
のようなパターンマッチングの柔軟性を失いますか?いくつかの私のタイミングでは、全体のパフォーマンスの30%以上がsortKey関数で失われています。
ご協力ありがとうございます。あなたは簡単に行うことができ
こんにちは、ありがとうございます。私は最初のバージョンを実装し、それは約100倍高速です。私の実装は次のとおりです。 – Daniel