java测量程序运行时间_测量Go程序中的执行时间

java测量程序运行时间

A common operation when developing a Go application, or benchmarking it to find ways to improve it, is benchmarking a function execution time. I introduced the topic of CPU and memory profiling in Go already, but this is different and more suited to ad-hoc function execution time measurement.

开发Go应用程序或对其进行基准测试以找到改进方法的常见操作是对函数执行时间进行基准测试。 我已经在Go中介绍了CPU和内存配置的主题,但这是不同的,更适合临时功能执行时间的测量。

确定两个表达式之间的时间间隔:使用time.Since (Determine the time interval between two expressions: use time.Since)

time.Since is a function provided by the time standard library package that takes a Time value, computes the difference with the current time, and returns a Duration value, which is an int64 type with a String() method attached, which provides a human friendly notation for the time computed.

time.Sincetime标准库程序包提供的函数,该函数采用Time值,计算与当前时间的差,并返回Duration值, Duration值是附加有String()方法的int64类型,该值提供一个人工值计算时间的友好符号。

import (
    "fmt"
    "time"
)

func main() {
    start := time.Now()

    //... do something

    fmt.Println(time.Since(start))
}

Internally, time.Since is a shorthand for time.Now().Sub(t).

在内部, time.Sincetime.Now().Sub(t)的简写。

使用defer来测量函数内部的时间 (Using defer to measure time inside a function)

You can abstract this by using defer:

您可以使用defer对此进行抽象:

package main

import (
    "log"
    "time"
)

func runningtime(s string) (string, time.Time) {
    log.Println("Start:	", s)
    return s, time.Now()
}

func track(s string, startTime time.Time) {
    endTime := time.Now()
    log.Println("End:	", s, "took", endTime.Sub(startTime))
}

func execute() {
    defer track(runningtime("execute"))
    time.Sleep(3 * time.Second)
}

func main() {
    execute()
}

通过多次运行来对功能性能进行基准测试:使用testing(Benchmark a function performance by running it multiple times: use the testing package)

Here is a simple library I wrote, that counts the number of runes in a string.

这是我编写的一个简单库,该库计算字符串中的符文数。

runecount.go

runecount.go

package runecount

import "unicode/utf8"

func RuneCount(s string) int {
    return len([]rune(s))
}

func RuneCount2(s string) int {
    return utf8.RuneCountInString(s)
}

Which of the two ways to count the runes in a string is faster? We find out by writing a benchmark. Benchmarks live in the *_test.go file, like regular tests, and can stay in live with testing methods, that start with Test*, but they start with Benchmark* instead:

计算字符串中的符文的两种方法中哪一种更快? 我们通过编写基准来找出答案。 基准和常规测试一样,都存在于*_test.go文件中,并且可以保留以Test*开头的测试方法,但是它们以Benchmark*开头:

runecount_test.go

runecount_test.go

package runecount

import "testing"

func BenchmarkRuneCount(b *testing.B) {
    s := "Gophers are amazing 😁"
    for i := 0; i < b.N; i++ {
        RuneCount(s)
    }
}
func BenchmarkRuneCount2(b *testing.B) {
    s := "Gophers are amazing 😁"
    for i := 0; i < b.N; i++ {
        RuneCount2(s)
    }
}

I run this by executing, in the same folder where the files are located:

我通过在文件所在的同一文件夹中执行来运行此命令:

go test -bench=.

This causes all the benchmarks to run. I got just a single file, but in case you have many, you can specify which file to run.

这将导致所有基准测试运行。 我只有一个文件,但如果有多个文件,则可以指定要运行的文件。

Each benchmark runs the loop passing the b.N variable, which is automatically determined by the benchmark runner, until the average is stable enough to determine a result.

每个基准运行通过bN变量的循环,该变量由基准运行程序自动确定,直到平均值足够稳定才能确定结果。

This is the output I get on my Mac:

这是我在Mac上获得的输出:

# flavio @ Flavios-MacBook-Pro in ~/go/src/github.com/flaviocopes/snippets/benchmark on git:master x [18:32:26]
$ go test -bench=.
BenchmarkRuneCount-2            20000000               115 ns/op
BenchmarkRuneCount2-2           30000000                44.1 ns/op
PASS
ok      github.com/flaviocopes/snippets/benchmark       3.812s

20000000 and 30000000 are the number of operations run.

2000000030000000是运行的操作数。

The command returns the benchmark results: it ran 20M times RuneCount(), which took on average 163 nanoseconds, and then it ran 30M times RuneCount2(), which took on average 74.2 nanoseconds per each iteration.

该命令返回基准测试结果:它运行了2000万次RuneCount() ,平均耗时163纳秒,然后运行了3000万次RuneCount2() ,平均每次迭代耗时74.2纳秒。

So Benchmark1, which runs RuneCount(), is 2x slower than RuneCount2(), that uses the built-in utf8.RuneCountInString function. No surprise here, as utf8.RuneCountInString is highly optimized for this specific task.

因此,运行RuneCount() Benchmark1比使用内置utf8.RuneCountInString函数的RuneCount2()慢2 utf8.RuneCountInString 。 这里并不奇怪,因为utf8.RuneCountInString已针对此特定任务进行了高度优化。



Instead of using go test, you can also call testing.Benchmark from a command:

除了使用go test ,您还可以从以下命令调用testing.Benchmark

package main

import (
    "fmt"
    "testing"
    "runecount"
)

func BenchmarkRuneCount(b *testing.B) {
    s := "Gophers are amazing 😁"
    for i := 0; i < b.N; i++ {
        RuneCount(s)
    }
}
func BenchmarkRuneCount2(b *testing.B) {
    s := "Gophers are amazing 😁"
    for i := 0; i < b.N; i++ {
        RuneCount2(s)
    }
}

func main() {
    fmt.Println(testing.Benchmark(BenchmarkRuneCount))
    fmt.Println(testing.Benchmark(BenchmarkRuneCount2))
}

在哪里阅读更多 (Where to read more)

翻译自: https://flaviocopes.com/golang-measure-time/

java测量程序运行时间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值