-2

[Golang] Leaks In Goroutine And Debug Resource

Ví Dụ Đơn Giản

func leak() {
	doWork := func(strings <-chan string) <-chan interface{} {
		completed := make(chan interface{})
		go func() {
			defer fmt.Println("doWork exited.")
			defer close(completed)
			for s := range strings {
				// Do something interesting
				fmt.Println(s)
			}
		}()
		fmt.Println("end function doWork")
		return completed
	}
	fmt.Println("dowork")
	doWork(nil)
	// Perhaps more work is done here
	fmt.Println("Done.")
}
  • trong func doWork với parameter là một chan string.
  • func sẽ leak vì string channel là một giá trị nil. Có nghĩa là goroutine này không clear tài nguyên, không stop func.
  • ví dụ trên có lẽ là cực kì ngắn, nhưng trong thực tế thì func sẽ tồn tại trong lifetime và ảnh hưởng đến tài nguyên của chương trình.

Debug Resource

Cài package

  • cài package: apt-get install graphviz gv (debian) or brew install graphviz (mac)
  • cài pprof: go get -u github.com/google/pprof
  • import pprof: import _ "net/http/pprof"
  • add server: pprof

source

package main

import (
	"fmt"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"syscall"
)

func leak() {
	doWork := func(strings <-chan string) <-chan interface{} {
		completed := make(chan interface{})
		go func() {
			defer func() {
				fmt.Println("doWork exited.")
			}()
			defer func() {
				close(completed)
			}()
			for s := range strings {
				// Do something interesting
				fmt.Println(s)
			}
		}()
		fmt.Println("end function doWork")
		return completed
	}
	fmt.Println("dowork")
	doWork(nil)
	// Perhaps more work is done here
	fmt.Println("Done.")
}

func main() {
	leak()
	leak()
	leak()
	go func() {
		http.ListenAndServe(":1234", nil)
	}()

	//
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	done := make(chan bool, 1)
	go func() {
		<-sigs
		done <- true
	}()
	<-done
}
  • trong func main, gọi 3 hàm leak() -> trong lifetime sẽ có 3 goroutine bị leak
  • start server với port 1234
  • sau khi start server, mở một terminal khác go tool pprof http://localhost:1234/debug/pprof/goroutine và enter png
  • sẽ có kết quả Generating report in profile001.png
  • Kết quả trong hình sử dụng pprof thì sẽ có 3 leak.

Video https://www.youtube.com/watch?v=e1Aa4d90nzk

Source https://github.com/ducnpdev/open-dev/blob/master/concurrency/leak.go

Liên Hệ


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí