美文网首页
sync.pool_test

sync.pool_test

作者: xiaolv17 | 来源:发表于2021-07-18 20:41 被阅读0次

sync.pool_test

Created: July 16, 2021 12:53 AM

上一篇文章简单的聊了一下对于sync.pool的粗浅的理解,如果想要知道sync.pool怎么使用,最简单的方法就是看下官方的test是怎么用的,我们就官方的test来看看。

func TestPool(t *testing.T) {
    // disable GC so we can control when it happens.
    defer debug.SetGCPercent(debug.SetGCPercent(-1))
    var p Pool
    if p.Get() != nil {
        t.Fatal("expected empty")
    }

    // Make sure that the goroutine doesn't migrate to another P
    // between Put and Get calls.
    Runtime_procPin()
    p.Put("a")
    p.Put("b")
    if g := p.Get(); g != "a" {
        t.Fatalf("got %#v; want a", g)
    }
    if g := p.Get(); g != "b" {
        t.Fatalf("got %#v; want b", g)
    }
    if g := p.Get(); g != nil {
        t.Fatalf("got %#v; want nil", g)
    }
    Runtime_procUnpin()

    // Put in a large number of objects so they spill into
    // stealable space.
    for i := 0; i < 100; i++ {
        p.Put("c")
    }
    // After one GC, the victim cache should keep them alive.
    runtime.GC()
    if g := p.Get(); g != "c" {
        t.Fatalf("got %#v; want c after GC", g)
    }
    // A second GC should drop the victim cache.
    runtime.GC()
    if g := p.Get(); g != nil {
        t.Fatalf("got %#v; want nil after second GC", g)
    }
}

在代码中可以看出,在使用的时候将当前的G用Runtime_procPin()将P绑定住,避免在调用call()和put()时,G运行在另一个P上。首先p.Get()判断首先保证了p的local或者victim中都没有数据,随后使用put()存入两个数据,在函数开头的时候关闭了gc,所以现在数据是存在local里面的,然后使用Get()方法取出,因为lcoal是一个双端链表,一边是入另一边是出,所以Get()可以按照放入数据顺序依次取出,随后解绑当前G与P。

调用Put()存入数据,随后手动触发gc,那么依据上篇文章所说原本的数据就会被放到victim中,此时调用Get()也能取到数据,此时再触发gc的话刚刚victim中的数据就会被清除。

func TestPoolNew(t *testing.T) {
    // disable GC so we can control when it happens.
    defer debug.SetGCPercent(debug.SetGCPercent(-1))

    i := 0
    p := Pool{
        New: func() interface{} {
            i++
            return i
        },
    }
    if v := p.Get(); v != 1 {
        t.Fatalf("got %v; want 1", v)
    }
    if v := p.Get(); v != 2 {
        t.Fatalf("got %v; want 2", v)
    }

    // Make sure that the goroutine doesn't migrate to another P
    // between Put and Get calls.
    Runtime_procPin()
    p.Put(42)
    if v := p.Get(); v != 42 {
        t.Fatalf("got %v; want 42", v)
    }
    Runtime_procUnpin()

    if v := p.Get(); v != 3 {
        t.Fatalf("got %v; want 3", v)
    }
}

这个是关于pool的New函数的用例,我们先看下New函数的定义。

type Pool struct {
    noCopy noCopy

    local     unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal
    localSize uintptr        // size of the local array

    victim     unsafe.Pointer // local from previous cycle
    victimSize uintptr        // size of victims array

    // New optionally specifies a function to generate
    // a value when Get would otherwise return nil.
    // It may not be changed concurrently with calls to Get.
    New func() interface{}
}

官方注释是说New()是一个可选项,如果调用Get()方法,如果没有存入的对象,那么就会调用New()方法,并返回New()的返回值,否则的话就会返回nil。调用Get并不会同时调用New()。所以New()的调用只会发生在Get没有值的之后。

测试用例中前两次调用都没有值,所以New()函数内部对i进行了自增,之后存入一个值再取出一个值,再取值,会再次调用New(),此时的i的值就是3.

基本只要掌握以上方法就可以使用sync.pool了,如果有说错的地方,请大家指出,不吝赐教,谢谢。

相关文章

  • sync.pool_test

    sync.pool_test Created: July 16, 2021 12:53 AM 上一篇文章简单的聊了...

网友评论

      本文标题:sync.pool_test

      本文链接:https://www.haomeiwen.com/subject/vgzapltx.html