我想创建一个 struct
mutable struct myStruct
id::string
end
Run Code Online (Sandbox Code Playgroud)
我确实想id成为一个字符串,但我希望它只取 3 个值中的 1 个(例如"a","b"或"c")。我的想法是理论上可以加快操作速度。
我不知道有什么方法可以让ida String,同时将它限制为只有 3 个可能值中的一个,以便编译器可以利用它。
但是,如果离开String域是一种选择,那么您有几种可能性。让我们在这里尝试对其中一些进行基准测试。为了示例,我们假设此id字段用于测试两个MyStruct实例之间的相等性。
这种类型的一个可能的(非常简约的)通用实现如下,其中参数T确定用于 id 的类型。
mutable struct MyType{T}
id :: T
end
# Two MyType instances are equal if their ids are equal
import Base.==
==(a::MyType{T}, b::MyType{T}) where {T} = (a.id == b.id)
Run Code Online (Sandbox Code Playgroud)
现在让我们在各种情况下对相等运算符进行基准测试。首先,使用字符串作为标识符的基本情况:
julia> using BenchmarkTools
julia> a = MyType("apple")
MyType{String}("apple")
julia> b = MyType("banana")
MyType{String}("banana")
julia> @btime $a == $b
4.326 ns (0 allocations: 0 bytes)
false
Run Code Online (Sandbox Code Playgroud)
我们希望整数更快,事实确实如此:
julia> a = MyType(1)
MyType{Int64}(1)
julia> b = MyType(2)
MyType{Int64}(2)
julia> @btime $a == $b
1.882 ns (0 allocations: 0 bytes)
false
Run Code Online (Sandbox Code Playgroud)
但也许 API 不太方便。使用枚举类型可能更具可读性(用户不必记住哪个值对应于“apple”)。它还可以防止使用任何未预定义的值,同时保持相同的性能:
julia> @enum Fruit begin
apple
banana
end
julia> a = MyType(apple)
MyType{Fruit}(apple)
julia> b = MyType(banana)
MyType{Fruit}(banana)
julia> @btime $a == $b
1.816 ns (0 allocations: 0 bytes)
false
Run Code Online (Sandbox Code Playgroud)
可能值得考虑的最后一个选项是使用符号作为键,这样可以保留 (IMO) 的可用性和性能:
julia> a = MyType(:apple)
MyType{Symbol}(:apple)
julia> b = MyType(:banana)
MyType{Symbol}(:banana)
julia> @btime $a == $b
1.883 ns (0 allocations: 0 bytes)
false
Run Code Online (Sandbox Code Playgroud)
没有什么可以阻止任何人构建非法值,例如MyStruct(:cheddar),但它非常适合操作字符串的上下文。例如,如果您在工作流的某处将 id 作为字符串获取,则可以在构造MyStruct实例之前轻松地将其转换为符号:
julia> id = "apple"
"apple"
julia> a = MyType(Symbol(id))
MyType{Symbol}(:apple)
Run Code Online (Sandbox Code Playgroud)