golang 更快版本的http://benchmarksgame.alioth.debian.org/u64q/program.php?test=binarytrees&lang=go&am

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 更快版本的http://benchmarksgame.alioth.debian.org/u64q/program.php?test=binarytrees&lang=go&am相关的知识,希望对你有一定的参考价值。

package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime/debug"
	"runtime/pprof"
	"strconv"
	"sync"
	"time"
)

var minDepth = 4
var n = 0

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

const nodesCount = 1024 * 32

var (
	nodeBuf    []Node
	nodeBufIdx int32
)

type Allocator struct {
	nodes []Node
	idx   int
	cap   int
}

func NewAllocatorWithCapacity(cap int) *Allocator {
	return &Allocator{
		nodes: make([]Node, cap, cap),
		cap:   cap,
		idx:   0,
	}
}

func NewAllocator() *Allocator {
	return NewAllocatorWithCapacity(nodesCount)
}

func (a *Allocator) allocNode(item int, left, right *Node) *Node {
	if a.idx >= a.cap-1 {
		a.nodes = make([]Node, a.cap)
		a.idx = 0
	}
	res := &a.nodes[a.idx]
	a.idx++
	res.item = item
	res.left = left
	res.right = right
	return res
}

func main() {
	//runtime.GOMAXPROCS(runtime.NumCPU() * 2)
	debug.SetGCPercent(-1)
	timeStart := time.Now()

	flag.Parse()
	if flag.NArg() > 0 {
		n, _ = strconv.Atoi(flag.Arg(0))
	}

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	maxDepth := n
	if minDepth+2 > n {
		maxDepth = minDepth + 2
	}
	stretchDepth := maxDepth + 1

	a := NewAllocator()
	check_l := bottomUpTree(a, 0, stretchDepth).ItemCheck()
	fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, check_l)

	longLivedTree := bottomUpTree(a, 0, maxDepth)

	result_trees := make([]int, maxDepth+1)
	result_check := make([]int, maxDepth+1)

	var wg sync.WaitGroup
	for depth_l := minDepth; depth_l <= maxDepth; depth_l += 2 {
		wg.Add(1)
		go func(depth int) {
			iterations := 1 << uint(maxDepth-depth+minDepth)
			check := 0
			a := NewAllocator()
			for i := 1; i <= iterations; i++ {
				check += bottomUpTree(a, i, depth).ItemCheck()
				check += bottomUpTree(a, -i, depth).ItemCheck()
			}
			result_trees[depth] = iterations * 2
			result_check[depth] = check

			wg.Done()
		}(depth_l)
	}
	wg.Wait()

	for depth := minDepth; depth <= maxDepth; depth += 2 {
		fmt.Printf("%d\t trees of depth %d\t check: %d\n",
			result_trees[depth], depth, result_check[depth],
		)
	}
	fmt.Printf("long lived tree of depth %d\t check: %d\n",
		maxDepth, longLivedTree.ItemCheck(),
	)
	fmt.Printf("dur: %s\n", time.Since(timeStart))
}

func bottomUpTree(a *Allocator, item, depth int) *Node {
	if depth <= 0 {
		return a.allocNode(item, nil, nil)
	}
	left := bottomUpTree(a, 2*item-1, depth-1)
	right := bottomUpTree(a, 2*item, depth-1)
	return a.allocNode(item, left, right)
}

type Node struct {
	item        int
	left, right *Node
}

func (self *Node) ItemCheck() int {
	if self.left == nil {
		return self.item
	}
	return self.item + self.left.ItemCheck() - self.right.ItemCheck()
}

哪个版本的“查找出现”功能更快?

【中文标题】哪个版本的“查找出现”功能更快?【英文标题】:Which version of "find an occurence" function is faster? 【发布时间】:2014-03-27 12:20:26 【问题描述】:

我的算法不是很强。有两个版本的函数,如果传递的字符串中有任何大写字母,则返回。 First 不检查每次迭代的条件。第一次出现大写字母后的第二次结束。一般来说哪个更快?

bool isAnyCapLetters(const std::string &s) 
    int flag = 0;
    for (auto el : s)
        flag += isupper(el);
    return static_cast<bool>(flag);

bool isAnyCapLetters(const std::string &s) 
    for (auto el : s)
        if (isupper(el)) return true;
    return false;   

【问题讨论】:

两者似乎都是 O(n),所以时间可能相等 @staticx 最坏情况渐近复杂度并不是衡量性能的唯一有用指标。 @delnan:是的,在这种情况下,虽然它正在迭代一个未知长度的未知字符串。我认为你必须考虑最坏的情况。另外,这些函数是不相等的,因为一个是计数函数,一个是计数函数,另一个是有效性检查。 if 花费少于+=,并且可能会提前打破循环 @Tim: "if 花费少于 +=" - 除非分支预测失败,在这种情况下它可能会慢得多。测量是唯一确定的方法。 【参考方案1】:

第二个返回较早,对于以大写字母开头的长字符串会更快。

【讨论】:

【参考方案2】:

如果你有一个像This_is_a_useless_but_not_so_very_short_string_whooptifriggindoo 这样的字符串,那么第一个函数将循环遍历所有字符,并且必须在最后进行强制转换。第二个函数将看到第一个字符是大写的,并且将立即返回而不进行任何转换。因此第二个函数会更快。

【讨论】:

以上是关于golang 更快版本的http://benchmarksgame.alioth.debian.org/u64q/program.php?test=binarytrees&lang=go&am的主要内容,如果未能解决你的问题,请参考以下文章

node可以用nvm快速切换版本,golang如何快速切换版本?用gvm就行。

如何在 Golang 中更快地进行 api 调用?

Golang 1.9 的新特性

[译]golang 1.8工具链改进

Go:缓冲通道总和更快?

golang protobuf unknown字段透传