The official Go Language Pack sync. The implementation principle and application scenario of pool

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Golang has been used for some time, the Go's co-process and GC garbage collection features do improve program development efficiency. But after all, it's a new language, and if it's not understood, it might be used to pop a variety of Pandora's boxes. Let's talk about the use of the pool class of the Sync pack I used in my project to avoid confusion.

As is known to all, go is an automatic garbage collection (garbage collector), which greatly reduces the burden of program programming. But GC is a double-edged sword, which brings the convenience of programming but also increases the runtime overhead, improper use can even seriously affect the performance of the program. So the performance requirements of the scene can not be arbitrarily generated too much garbage (there is a GC but can not completely rely on it is disgusting), how to solve it? That is to reuse objects, we can simply use a Chan to cache these reusable objects, but if a lot of goroutine compete with a Chan performance is definitely a problem ..... As the Golang team realized that the problem was widespread, in order to avoid the re-creation of the wheel, the official unified a package pool. But why put it in the sync bag is also some confusing, do not discuss this issue first.

Let's take a look at how to use a pool:

Package Mainimport (    "FMT"    "Sync") func main () {    p: = &sync. pool{        New:func () interface{} {            return 0        },    }    A: = P.get (). ( int)    p.put (1)    B: = P.get (). ( int)    FMT. Println (A, B)}
The above creates a pool that caches an int object, first getting an object from the pool and then putting it in an object and then fetching an object, the output of the program is 0 1. You can specify a new function when you create it, and how to get objects that are not cached in the pool will create a return using the specified new function, or nil if there is no new function. The usage is not very simple, we do not say more here, the following is the question we are concerned about:

1. Number and duration of cached objects

Above we can see that the pool was created with a size that cannot be specified, all sync. Pool has no limit on the number of cached objects (limited to memory), so using Sync.pool is no way to control the number of cached objects. In addition Sync.pool cache object's term is very strange, first look at src/pkg/sync/pool.go inside a section of implementation code:

Func init () {    runtime_registerpoolcleanup (poolcleanup)}

You can see that the pool package registers a poolcleanup function at Init, which clears all cached objects in the pool, which is called after each GC, so sync. The pool cache is only a period between two GC times. For example, if we change the above example to the following, the result of the output will be 0 0. The cache object is cleared when the GC is being used, and there is no need to worry that the pool will grow indefinitely.

    A: = P.get (). (int)    P.put (1)    runtime. GC ()    B: = P.get (). ( int)    FMT. Println (A, B)

This is where many people mistakenly understand it, and because of this, we are not able to use sync. Pool to implement a socket connection pooling.

2. Cost of Cached objects

How do you use the same pool for efficiency across multiple goroutine? The official practice is to minimize competition, because sync.pool for each p (corresponding to the CPU, do not know the child shoes can go to see Golang scheduling model introduced) are allocated a sub-pool, such as:


When performing a get or put operation of a pool, the current goroutine is pinned to the child pool of a p, and then the child pool is manipulated. Each sub-pool has a private object and a shared list object, and the private object is accessible only to the corresponding p, because a p can only execute one goroutine at a time, so there is no need to lock the private object access operation. Share lists are shared with other p, so the action share list needs to be locked.

The Get object procedure is:

1) fixed to a p, try to get from the private object, if the private object is not empty return the object, and the private object is empty;

2) If the private object is empty, go to the share list of the current child pool (need to lock);

3) If the shared list of the current sub-pool is empty, then try to steal one from the shared list of other P's sub-pools (need to lock);

4) If the other sub-pools are empty, finally a new object is returned with the user-designated new function.

Can see a get operation at least 0 times lock, the maximum n (n equals Maxprocs) times lock.

The process of returning an object:

1) fixed to a p, if the private object is empty then put to the private object;

2) Otherwise added to the share list of the P sub-pool (requires lock).

You can see that a put operation is locked for at least 0 times, up to 1 times.

Since Goroutine is specifically assigned to that P execution is determined by the Golang scheduling system, so in maxprocs>1 case, more goroutine with the same sync. Pool, it is not possible to accurately measure the balance of objects cached between child pools and the cost of each p. But if the number of goroutine and the number of objects cached is much larger than maxprocs, the probability should be relatively balanced.

Overall, sync. Pool positioning is not something like connection pooling, its purpose is only to increase the likelihood of object reuse, reduce the burden of GC, and the cost is not very cheap.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.