SoFunction
Updated on 2025-03-05

Optimization performance of golang concurrency

Introduction

How to implement the cache pooling function of objects in Go? One common implementation is:,It is designed to cache allocated but unused items for later reuse, thereby reducing the pressure on the garbage collector (GC).

Quick use

The structure is also relatively simple, and the commonly used methods are Get and Put

type Pool struct {
    local      // local fixed-size per-P pool, actual type is [P]poolLocal
    localSize uintptr        // size of the local array

    victim      // 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() any
}
func (p *Pool) Get() any  
func (p *Pool) Put(x any) 

Next, let's take a simple example to see how it is used

package main

import (
    "fmt"
    "sync"
)

type Object struct {
    ID int
    // ...
}

func main() {
    // 1. Create an object    pool := &{
       New: func() interface{} {
          ("Creating a new object")
          return &Object{}
       },
    }
    // The () method gets an object from the pool.  If there are objects available in the pool, the Get() method will return one of them; otherwise, it will return a newly created object    obj := ().(*Object)
    // 3. Operation object     = 1
    // 4. Call the() method to put the object back into the pool    (obj)
    objBar := ().(*Object)
    ("Object ID:", )
}

Practical application

The Enjoyment Model mentioned in previous articlesDesign pattern: flyweight (Xianyuan)The case of application of card games. Today we use this solution to optimize. Observing the code in the chess and card game, although it solves the problem of having to New an object every time, there are still several optimization points:

  • You cannot only cache specific chess and card room type objects;
  • Concurrent security issues

It turns out that the Enjoyment Mode is implemented through Factory + Map, and some of the codes are intercepted as follows

package design_mode

import "fmt"

var chessPieceUnit = map[int]*ChessPiece{
	1: {
		Name:  "vehicle",
		Color: "red",
		PositionX: 1,
		PositionY: 11,
	},
	2: {
		Name:  "Horse",
		Color: "black",
		PositionX: 2,
		PositionY: 2,
	},
	// Other chess pieces}

func NewChessPieceUnitFactory() *ChessBoard {
	board := &ChessBoard{Cards: map[int]*ChessPiece{}}
	for id := range chessPieceUnit {
		[id] = chessPieceUnit[id]
	}
	return board
}

1. Refactoring Factory

Next, let’s modify the Factory implementation:

pool := &{
    New: func() interface{} {
       ("Creating a new object")
       return NewChessBoard()
    },
}

game1 := ().(*ChessBoard)
game2 := ().(*ChessBoard)
(game1)
(game2)
([0] == [0]) 

2. Concurrent security issues

2.1 Modify the model

For easy observation, add a creation time to each room (chess and card room)

type ChessBoard struct {
    Cards map[int]*ChessPiece
    Time  
} 

2.2 Concurrent testing

Start multiple goroutines for testing

func main() {
    pool := &{
       New: func() interface{} {
          ("Creating a new object")
          return NewChessBoard()
       },
    }
    var wg 
    for i := 0; i < 10; i++ {
       (1)
       go func(id int) {
          defer ()
          obj := ().(*ChessBoard)
           = ()
          (obj)
          ("Object ID: %v\n", )
       }(i)
    }
    ()
} 

The output is as follows:

Creating a new object
Creating a new object
Object ID: 2023-10-22 15:41:50.309343 +0800 CST m=+0.003511901
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201
Object ID: 2023-10-22 15:41:50.3117423 +0800 CST m=+0.005911201

It can be seen that in the concurrency of multiple goroutines, it is safe. In addition, it can be observed that there are no [Creating a new object] to go to many chess and card rooms in New.

summary

It is a type in the Go language standard library that provides the cache pooling function of objects. Its main purpose is to store temporary objects that can be reused so that they can be quickly retrieved when needed, rather than performing new object allocations every time. And it is safe to use Pool at the same time for multiple goroutines.

This article briefly describes the basic use and how to use it to optimize the case of practical chess and card room games.

The above is the detailed content of the optimization performance of golang concurrency. For more information about go, please follow my other related articles!