gpt4 book ai didi

golang : how to simulate union type efficiently

转载 作者:IT老高 更新时间:2023-10-28 13:07:25 26 4
gpt4 key购买 nike

众所周知,go没有联合类型,只能通过接口(interface)模拟。

我尝试了两种方法来模拟并集,但结果远不如C。

package main

import (
"fmt"
"time"
)

type U interface {
i32() int32
i16() int16
}

type i32 int32

func (u i32) i32() int32 {
return int32(u)
}

func (u i32) i16() int16 {
return int16(u)
}

type i16 int16

func (u i16) i32() int32 {
return int32(u)
}

func (u i16) i16() int16 {
return int16(u)
}

func test() (total int64) {
type A struct {
t int32
u interface{}
}
a := [...]A{{1, int32(100)}, {2, int16(3)}}

for i := 0; i < 5000000000; i++ {
p := &a[i%2]
switch p.t {
case 1:
total += int64(p.u.(int32))
case 2:
total += int64(p.u.(int16))
}
}
return
}

func test2() (total int64) {
type A struct {
t int32
u U
}
a := [...]A{{1, i32(100)}, {2, i16(3)}}

for i := 0; i < 5000000000; i++ {
p := &a[i%2]
switch p.t {
case 1:
total += int64(p.u.i32())
case 2:
total += int64(p.u.i16())
}
}
return
}

type testfn func() int64

func run(f testfn) {
ts := time.Now()
total := f()
te := time.Now()
fmt.Println(total)
fmt.Println(te.Sub(ts))
}

func main() {
run(test)
run(test2)
}

结果:

257500000000
1m23.508223094s
257500000000
34.95081661s

method方式更好,type-cast方式消耗更多CPU时间。

C 版本:

#include <stdio.h>

struct A {
int t;
union {
int i;
short v;
} u;
};

long test()
{
struct A a[2];
a[0].t = 1;
a[0].u.i = 100;
a[1].t = 2;
a[1].u.v = 3;

long total = 0;
long i;
for (i = 0; i < 5000000000; i++) {
struct A* p = &a[i % 2];
switch(p->t) {
case 1:
total += p->u.i;
break;
case 2:
total += p->u.v;
break;
}
}
return total;
}
int main()
{
long total = test();
printf("%ld\n", total);
}

结果:

257500000000

real 0m5.620s
user 0m5.620s
sys 0m0.000s

联合类型对许多应用程序都很有用,例如网络协议(protocol)可能包含变体具体类型。所以也许联合数据的访问可能会成为应用的瓶颈。

有人可以帮忙吗?谢谢。

最佳答案

您可以使用数组将单个 int32 表示为两个 int16,然后用移位组合它们 as Rob Pike recommends :

func test3() (total int64) {
type A struct {
t int32
u [2]int16
}
a := [...]A{
{1, [2]int16{100, 0}},
{2, [2]int16{3, 0}},
}

for i := 0; i < N; i++ {
p := &a[i%2]
switch p.t {
case 1:
total += int64(p.u[0]<<0 | p.u[1]<<8)
case 2:
total += int64(p.u[0])
}
}
return
}

使用原始 Go 编译器,它的运行速度比 C 版本慢约 2 倍,而使用 gccgo (-O3) 它的运行速度与 C 差不多。

请注意,尽管这种方法假定为小端整数。您需要切换大端架构的转换顺序。

另外,如果你需要从 byte slice 中解码结构,你真的应该使用 encoding/binary .创建此库是为了在字节序列和其他类型之间进行转换。

关于golang : how to simulate union type efficiently,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31557539/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com