GO语言亿级并发

参考:https://blog.csdn.net/Jeanphorn/article/details/79018205

感谢Handling 1 Million Requests per Minute with Go这篇文章给予的巨大启发。

workerpool.go

package main

import "fmt"

type Job interface {
	Do()
}

type Worker struct {
	JobQueue chan Job
}

func NewWorker() Worker {
	return Worker{JobQueue: make(chan Job)}
}
func (w Worker) Run(wq chan chan Job) {
	go func() {
		for {
			wq <- w.JobQueue
			select {
			case job := <-w.JobQueue:
				job.Do()
			}
		}
	}()
}

// ---------------------------------------------------------

type WorkerPool struct {
	workerlen   int
	JobQueue    chan Job
	WorkerQueue chan chan Job
}

func NewWorkerPool(workerlen, joblen int) *WorkerPool {
	return &WorkerPool{
		workerlen:   workerlen,
		JobQueue:    make(chan Job, joblen),
		WorkerQueue: make(chan chan Job, workerlen),
	}
}
func (wp *WorkerPool) Start() {
	fmt.Println("初始化worker")
	//初始化worker
	for i := 0; i < wp.workerlen; i++ {
		worker := NewWorker()
		worker.Run(wp.WorkerQueue)
	}
	// 循环获取可用的worker,往worker中写job
	go func() {
		for {
			select {
			case job := <-wp.JobQueue:
				worker := <-wp.WorkerQueue
				worker <- job
			}
		}
	}()
}

// ------------------------
/*
func main() {
	workernum := 100 * 100
	jobnum := 100 * 100 * 20
	// debug.SetMaxThreads(num + 1000) //设置最大线程数
	// 注册工作池,传入任务
	// 参数1 worker并发个数
	p := NewWorkerPool(workernum, jobnum)
	p.Start()
	datanum := 100 * 100 * 100 * 100
	go func() {
		for i := 1; i <= datanum; i++ {
			sc := &Score{Num: i}
			p.JobQueue <- sc
		}
	}()

	for {
		fmt.Println("runtime.NumGoroutine() :", runtime.NumGoroutine())
		time.Sleep(2 * time.Second)
	}
}
*/

main.go

package main

import (
	"fmt"
	"runtime"
	"time"
)

type Score struct {
	Num int
}

func (s *Score) Do() {
	fmt.Println("num:", s.Num)
	time.Sleep(1 * 10 * time.Second)
}

func main() {
	workernum := 100 * 100
	jobnum := 100 * 100 * 20
	// debug.SetMaxThreads(num + 1000) //设置最大线程数
	// 注册工作池,传入任务
	// 参数1 worker并发个数
	p := NewWorkerPool(workernum, jobnum)
	p.Start()
	datanum := 100 * 100 * 100 * 100
	go func() {
		for i := 1; i <= datanum; i++ {
			sc := &Score{Num: i}
			p.JobQueue <- sc
		}
	}()

	for {
		fmt.Println("runtime.NumGoroutine() :", runtime.NumGoroutine())
		time.Sleep(2 * time.Second)
	}
}

_test.go

package main

import (
	"strings"
	"testing"
)

// go test -run=xxx -bench=. -benchtime="3s" -cpuprofile profile_cpu.out
/*
https://graphviz.gitlab.io/_pages/Download/Download_windows.html
# go tool pprof -svg profile_cpu.out > profile_cpu.svg
# go tool pprof -pdf profile_cpu.out > profile_cpu.pdf
*/
func BenchmarkStringJoin1(b *testing.B) {
	// 在report中包含内存分配信息    BenchmarkStringJoin1-4 300000 4351 ns/op 32 B/op 2 allocs/op
	/*
		-4表示4个CPU线程执行;
		300000表示总共执行了30万次;
		4531ns/op,表示每次执行耗时4531纳秒;
		32B/op表示每次执行分配了32字节内存;
		2 allocs/op表示每次执行分配了2次对象。
	*/
	b.ReportAllocs()
	input := []string{"Hello", "World"}
	for i := 0; i < b.N; i++ {
		result := strings.Join(input, " ")
		if result != "Hello World" {
			b.Error("Unexpected result: " + result)
		}
	}
}
func BenchmarkStringJoin2(b *testing.B) {
	b.ReportAllocs()
	input := []string{"Hello", "World"}
	join := func(strs []string, delim string) string {
		if len(strs) == 2 {
			return strs[0] + delim + strs[1]
		}
		return ""
	}
	for i := 0; i < b.N; i++ {
		result := join(input, " ")
		if result != "Hello World" {
			b.Error("Unexpected result: " + result)
		}
	}
}
func BenchmarkStringJoin2B(b *testing.B) {
	b.ReportAllocs()
	join := func(strs []string, delim string) string {
		if len(strs) == 2 {
			return strs[0] + delim + strs[1]
		}
		return ""
	}
	for i := 0; i < b.N; i++ {
		input := []string{"Hello", "World"}
		result := join(input, " ")
		if result != "Hello World" {
			b.Error("Unexpected result: " + result)
		}
	}
}

/*
只关心性能最差的那个

go test -run=xxx -bench=BenchmarkStringJoin2B$ -cpuprofile profile_2b.out
go test -run=xxx -bench=BenchmarkStringJoin2$ -cpuprofile profile_2.out
go tool pprof -svg profile_2b.out > profile_2b.svg
go tool pprof -svg profile_2.out > profile_2.svg
*/

 

你可能感兴趣的:(Go项目)