欢迎光临
梦想从学习开始!

Golang的简单反射性能测试| 小熊测试

本文主要介绍 Golang的简单反射性能测试| 小熊测试,小熊希望对大家的学习或者工作具有一定的参考学习价值,在测试领域有所提升和发展。

  测试用例

  我们对Golang的结构体变量赋值, 以及单参数函数调用进行反射和native操作的测试

package main

import (

"reflect"

"testing"

)

type data struct {

Hp int

}

const AssignTimes = 100000000

func TestNativeAssign(t *testing.T) {

v := data{Hp: 2}

for i := 0; i < AssignTimes; i++ {

v.Hp = 3

}

}

func TestReflectAssign(t *testing.T) {

v := data{Hp: 2}

vv := reflect.ValueOf(&v).Elem()

f := vv.FieldByName("Hp")

for i := 0; i < AssignTimes; i++ {

f.SetInt(3)

}

}

func TestReflectFindFieldAndAssign(t *testing.T) {

v := data{Hp: 2}

vv := reflect.ValueOf(&v).Elem()

for i := 0; i < AssignTimes; i++ {

vv.FieldByName("Hp").SetInt(3)

}

}

func foo(v int) {

}

const CallTimes = 100000000

func TestNativeCall(t *testing.T) {

for i := 0; i < CallTimes; i++ {

foo(i)

}

}

func TestReflectCall(t *testing.T) {

v := reflect.ValueOf(foo)

for i := 0; i < CallTimes; i++ {

v.Call([]reflect.Value{reflect.ValueOf(2)})

}

}

  性能测试数据

=== RUN TestNativeAssign

— PASS: TestNativeAssign (0.03s)

=== RUN TestReflectAssign

— PASS: TestReflectAssign (0.41s)

=== RUN TestReflectFindFieldAndAssign

— PASS: TestReflectFindFieldAndAssign (9.86s)

=== RUN TestNativeCall

— PASS: TestNativeCall (0.03s)

=== RUN TestReflectCall

— PASS: TestReflectCall (21.46s)

  测试评测

  在结构体变量赋值测试用例中, 我们发现TestReflectFindFieldAndAssign赋值格外的耗时. 分析性能点在FieldByName这个函数上, 我们查了下底层如何实现的:

// FieldByName returns the struct field with the given name

// and a boolean to indicate if the field was found.

func (t *structType) FieldByName(name string) (f StructField, present bool) {

// Quick check for top-level name, or struct without anonymous fields.

hasAnon := false

if name != "" {

for i := range t.fields {

tf := &t.fields[i]

if tf.name == nil {

hasAnon = true

continue

}

if *tf.name == name {

return t.Field(i), true

}

}

}

if !hasAnon {

return

}

return t.FieldByNameFunc(func(s string) bool { return s == name })

}

  各位看官必须吐槽用for来遍历获取数据, 但冷静下来分析. 这样做无可厚非.

  试想如果reflect包在我们使用ValueOf时使用map缓冲好一个结构体所有字段的访问数据后, 肯定访问指定字段速度会很快

  但是, 以空间换速度的需求其实最多满足了1%的需求.

  同样的例子是图形API里访问Shader变量的方法, 总是默认使用字符串获取, 速度很慢. 当你想快速访问时, 请提前按需缓存字段

  那么, Golang使用的也是这样的思路. 虽然暴力了一点, 但是能够让程序跑对, 性能优化的东西放在之后来做, 缓冲下就可以解决

  在调用测试用例中, 毫无悬念的, 调用速度很慢

  因此, 我们在平时使用反射时, 尽量偏向于反射变量缓冲存在下的变量赋值或者获取

  而调用的需求尽量减少, 如果有goroutine存在的情况下, 则不必太多担心.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小熊分享邦(www.xxfxb.com),希望大家能坚持软件测试之路,谢谢。

赞(0) 打赏
未经允许不得转载:小熊分享邦 » Golang的简单反射性能测试| 小熊测试

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏