是的,这是一个微不足道的问题,但我无法找到专家意见。
我正在使用计算表达式来排序服务器端进程。当我的函数具有相同的签名时,它会给我带来极大的帮助,所以我有一个带有区别的联合,其中定义了不同的组合。我有几个快速,初学者'的问题。
DU可以选择的数量是否有建议的上限?目前我的DU有九个选项,但随着项目的进展,这个数字会增加。如果我在项目结束时达到30或40,该怎么办?
如果某些选项得到" long"可能会出现问题目前,平均选项有大约四到五种基本类型 - 类似于bool * string * XElement * int * string
- 但最长的选项具有以下定义:
bool * int * int * int * string * XElement * XElement * DateTime option * DateTime option * string * Dictionary * Dictionary
我不希望有这么长的选择。但是,我是否会在表现方面让自己陷入痛苦的世界?
提前致谢。
答案 0 :(得分:9)
我认为如果数据类型的大小与F#编译器使用的数据类型的大小相似,我可以放心地认为事情会很好 - F#编译器的性能是F#团队肯定看到的我认为他们也做了一些实验,以确保他们使用的受歧视的工会有效地工作。
至于案件数量,SynExpr
歧视联盟(见source code)有超过50个案例,所以我认为这应该没问题。
通过在整数上使用switch
IL操作码来编译区分联合的模式匹配,因此如果您想确定,可以尝试对其效率进行一些研究。此外,如果您只是使用match
来查找一个特定的案例,那么这应该只是一个整数比较,而不管其他案例的数量。
至于字段数,SynExpr
的最长情况有7个字段,但我想你可以找到长度较长的其他DU。 (我认为这个属性的一个更大的问题是可读性 - 因为属性是未命名的。所以我认为使用逻辑上属于一起的大量属性的记录可能会更好。)
我认为您描述的DU的大小应该没问题,但我自己没有进行任何性能测试 - 所以如果你真的想确定,你需要测量它。 (但正如我所说的,我非常确定这已经作为F#编译器开发的一部分进行了测试)
答案 1 :(得分:6)
如果内存为我服务,我相信在DUs上有很多案例/字段的深层嵌套模式匹配存在一些性能问题,但是这是2.0之前的版本,我相信他们修复了当前的实现这些场景得到了很好的优化,没有明显的性能问题。 (对不起,没有引用)。
但即使经过优化,DUs也会消耗大量的代码。因此,尽管它们可能比任何等效的手动编码控制流表现得更好(并且可能更好),但是 可能会在为函数发出的大量指令上堆叠溢出/方法体(但这可能是一个非常极端的情况,因为.NET默认堆栈大小约为1MB,但是,它肯定会导致比通常的堆尾溢出更早的非尾递归方法/函数涉及大DU的匹配,但再次不太可能你应该真正担心这种情况。)
我不相信它会改变性能特征(因为我们在任何一种情况下都讨论堆分配的对象),但是为了可维护性/可读性,有时可以将DU案例数据包装在记录类型中以便数据字段被命名并且数据字段子集上的模式匹配更容易(例如{Name="Stephen"}
而不是(_,_,_,_,_,_,_,"Stephen",_,_,_,_,_)
)。 (@TomasPetricek打败了我这个建议,在我第一次看到他的答案时没有看到这一点)