当前位置 : 主页 > 网络安全 > 测试自动化 >

性能 – 使用UnboxedSums定义的和类型是否比普通枚举更有效?

来源:互联网 收集:自由互联 发布时间:2021-06-22
例如,这里是简单的 Haskell枚举数据类型: data Bool = False | True 自GHC-8.2.1以来,-XUnboxedSums扩展允许以更高内存效率的方式定义和类型.以下是文档引用: In the degenerate case where all the alternat
例如,这里是简单的 Haskell枚举数据类型:

data Bool = False | True

自GHC-8.2.1以来,-XUnboxedSums扩展允许以更高内存效率的方式定义和类型.以下是文档引用:

In the degenerate case where all the alternatives have zero width, such as the Bool-like (# (# #) | (# #) #), the unboxed sum layout only has an Int32 tag field (i.e., the whole thing is represented by an integer).

我想知道,这种表示是否比使用简单的普通Haskell枚举数据类型更有效?

以下是完整的文档:

> https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#unboxed-sums

语义和表征

这两种类型不能互换使用.

类型

data Bool = False | True

是一种提升型.这意味着变量x :: Bool仍然可以不被评估(例如thunk).因此它将表示为指针.

相反

(# (# #) | (# #) #)

是未提升的,实际上只能有两个值,并且只表示为机器整数.

空间效率

但这并不意味着后者更节省空间:因为True和False是nullary构造函数(它们不带参数),它们在程序的静态代码中一劳永逸地存在,并且指针只指向它们.因此,在所有情况下,成本都是一个机器字.

运行时效率

未装箱的变体可能比Bool稍微有效:

>对于Bool,代码首先必须检查是否已经评估过?然后它可以分支在哪个构造函数上.

分支非常有效:代码不必遵循指针:指针地址的低位中的“指针标记”将指示它是哪个构造函数.但是,屏蔽其他位的成本很低.
>在未装箱的变体中,它只是0或1,并且不需要进行thunk检查.

在数据类型中取消装箱

如果您定义这样的数据类型

data Foo = Foo (-# UNBOX #-} !Bool

你应该得到与你写的完全相同的结果

data Foo = Foo (# (# #) | (# #) #)

因为这是未装箱的和扩展的主要目的.

在功能中取消装箱

如果在Bool参数中定义一个严格的函数,例如

foo True = "Hello"
foo False = "World!"

然后我可以想象(但没有检查)编译器将其优化为一个带有(#(##)|(##)#)的工作器和一个负责thunk-check的包装器.然后包装器可能在使用foo的use-sites中内联,并且所有内容都可能以(#(##)|(##)#)结束.

结论

不要打扰.

网友评论