为了用键引用一些坐标,我想使用有区别的联合类型,因为它们允许所有种类的有效模式匹配 .
考虑下面的代码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()
我需要强制执行特定的排序顺序 . 例如Spot <Vol always . 我用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
什么是替代方法,表现良好?在我的一些时间中,sortKey函数中丢失了30%甚至更多的整体性能 .
感谢您的任何建议和改进 .
2 回答
Simple optimization
您可以轻松做的一个基本优化是,当您只能根据
Coord
的类型做出决定时,可以避免调用toString
. 你可以写下:而不是 BuildsortKey
如果要缓存
toString
的结果,则需要使用一些允许存储本地字段的结构 . 我可能会使用一个对象类型(表示为类或简单的结构) .Wrapping the type
在这种情况下,您仍然可以使用活动模式获得良好的模式匹配,但它需要为每个类定义一个活动模式(这可能不是那么糟糕) . 这是一个例子:
给定
AssetKey
类型的值,您现在可以编写k.Key
来获取缓存的字符串表示形式,并且可以使用活动模式对其进行模式匹配:你可以考虑做类似的事情
然后使用签名文件隐藏
CoordRepr
,Coord
的构造函数,sortKey
等 .