婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > go select編譯期的優化處理邏輯使用場景分析

go select編譯期的優化處理邏輯使用場景分析

熱門標簽:百度地圖標注位置網站 上海企業外呼系統排名 如何利用高德地圖標注家 智能語音電銷的機器人 400手機電話免費辦理 武漢百應人工智能電銷機器人 開通400電話申請流程 揚州電銷外呼系統軟件 電腦外呼系統輻射大嗎

前言

select作為Go chan通信的重要監聽工具,有著很廣泛的使用場景。select的使用主要是搭配通信case使用,表面上看,只是簡單的selectcase搭配,實際上根據case的數量及類型,在編譯時select會進行優化處理,根據不同的情況調用不同的底層邏輯。

select的編譯處理

select編譯時的核心處理邏輯如下:

func walkselectcases(cases *Nodes) []*Node {
	ncas := cases.Len()
	sellineno := lineno

	// optimization: zero-case select
	// 針對沒有case的select優化
	if ncas == 0 {
		return []*Node{mkcall("block", nil, nil)}
	}

	// optimization: one-case select: single op.
	// 針對1個case(單個操作)select的優化
	if ncas == 1 {
		cas := cases.First()
		setlineno(cas)
		l := cas.Ninit.Slice()
		if cas.Left != nil { // not default: 非default case
			n := cas.Left // 獲取case表達式
			l = append(l, n.Ninit.Slice()...)
			n.Ninit.Set(nil)
			switch n.Op {
			default:
				Fatalf("select %v", n.Op)

			case OSEND: // Left - Right
				// already ok
				// n中已包含left/right
			
			case OSELRECV, OSELRECV2: // OSELRECV(Left = -Right.Left) OSELRECV2(List = -Right.Left)
				if n.Op == OSELRECV || n.List.Len() == 0 { // 左側有0或1個接收者
					if n.Left == nil { // 沒有接收者
						n = n.Right // 只需保留右側
					} else { // 
						n.Op = OAS // 只有一個接收者,更新Op為OAS
					}
					break
				}

				if n.Left == nil { // 檢查是否表達式或賦值
					nblank = typecheck(nblank, ctxExpr|ctxAssign)
					n.Left = nblank
				}

				n.Op = OAS2 // OSELRECV2多個接收者
				n.List.Prepend(n.Left) // 將left放在前面
				n.Rlist.Set1(n.Right) 
				n.Right = nil
				n.Left = nil
				n.SetTypecheck(0)
				n = typecheck(n, ctxStmt)
			}

			l = append(l, n)
		}

		l = append(l, cas.Nbody.Slice()...) // case內的處理
		l = append(l, nod(OBREAK, nil, nil)) // 添加break
		return l
	}

	// convert case value arguments to addresses.
	// this rewrite is used by both the general code and the next optimization.
	var dflt *Node
	for _, cas := range cases.Slice() {
		setlineno(cas)
		n := cas.Left
		if n == nil {
			dflt = cas
			continue
		}
		switch n.Op {
		case OSEND:
			n.Right = nod(OADDR, n.Right, nil)
			n.Right = typecheck(n.Right, ctxExpr)

		case OSELRECV, OSELRECV2:
			if n.Op == OSELRECV2  n.List.Len() == 0 {
				n.Op = OSELRECV
			}

			if n.Left != nil {
				n.Left = nod(OADDR, n.Left, nil)
				n.Left = typecheck(n.Left, ctxExpr)
			}
		}
	}

	// optimization: two-case select but one is default: single non-blocking op.
	if ncas == 2  dflt != nil {
		cas := cases.First()
		if cas == dflt {
			cas = cases.Second()
		}

		n := cas.Left
		setlineno(n)
		r := nod(OIF, nil, nil)
		r.Ninit.Set(cas.Ninit.Slice())
		switch n.Op {
		default:
			Fatalf("select %v", n.Op)

		case OSEND:
			// if selectnbsend(c, v) { body } else { default body }
			ch := n.Left
			r.Left = mkcall1(chanfn("selectnbsend", 2, ch.Type), types.Types[TBOOL], r.Ninit, ch, n.Right)

		case OSELRECV:
			// if selectnbrecv(v, c) { body } else { default body }
			ch := n.Right.Left
			elem := n.Left
			if elem == nil {
				elem = nodnil()
			}
			r.Left = mkcall1(chanfn("selectnbrecv", 2, ch.Type), types.Types[TBOOL], r.Ninit, elem, ch)

		case OSELRECV2:
			// if selectnbrecv2(v, received, c) { body } else { default body }
			ch := n.Right.Left
			elem := n.Left
			if elem == nil {
				elem = nodnil()
			}
			receivedp := nod(OADDR, n.List.First(), nil)
			receivedp = typecheck(receivedp, ctxExpr)
			r.Left = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), types.Types[TBOOL], r.Ninit, elem, receivedp, ch)
		}

		r.Left = typecheck(r.Left, ctxExpr)
		r.Nbody.Set(cas.Nbody.Slice())
		r.Rlist.Set(append(dflt.Ninit.Slice(), dflt.Nbody.Slice()...))
		return []*Node{r, nod(OBREAK, nil, nil)}
	}

	if dflt != nil {
		ncas--
	}
	casorder := make([]*Node, ncas)
	nsends, nrecvs := 0, 0

	var init []*Node

	// generate sel-struct
	lineno = sellineno
	selv := temp(types.NewArray(scasetype(), int64(ncas)))
	r := nod(OAS, selv, nil)
	r = typecheck(r, ctxStmt)
	init = append(init, r)

	// No initialization for order; runtime.selectgo is responsible for that.
	order := temp(types.NewArray(types.Types[TUINT16], 2*int64(ncas)))

	var pc0, pcs *Node
	if flag_race {
		pcs = temp(types.NewArray(types.Types[TUINTPTR], int64(ncas)))
		pc0 = typecheck(nod(OADDR, nod(OINDEX, pcs, nodintconst(0)), nil), ctxExpr)
	} else {
		pc0 = nodnil()
	}

	// register cases
	for _, cas := range cases.Slice() {
		setlineno(cas)

		init = append(init, cas.Ninit.Slice()...)
		cas.Ninit.Set(nil)

		n := cas.Left
		if n == nil { // default:
			continue
		}

		var i int
		var c, elem *Node
		switch n.Op {
		default:
			Fatalf("select %v", n.Op)
		case OSEND:
			i = nsends
			nsends++
			c = n.Left
			elem = n.Right
		case OSELRECV, OSELRECV2:
			nrecvs++
			i = ncas - nrecvs
			c = n.Right.Left
			elem = n.Left
		}

		casorder[i] = cas

		setField := func(f string, val *Node) {
			r := nod(OAS, nodSym(ODOT, nod(OINDEX, selv, nodintconst(int64(i))), lookup(f)), val)
			r = typecheck(r, ctxStmt)
			init = append(init, r)
		}

		c = convnop(c, types.Types[TUNSAFEPTR])
		setField("c", c)
		if elem != nil {
			elem = convnop(elem, types.Types[TUNSAFEPTR])
			setField("elem", elem)
		}

		// TODO(mdempsky): There should be a cleaner way to
		// handle this.
		if flag_race {
			r = mkcall("selectsetpc", nil, nil, nod(OADDR, nod(OINDEX, pcs, nodintconst(int64(i))), nil))
			init = append(init, r)
		}
	}
	if nsends+nrecvs != ncas {
		Fatalf("walkselectcases: miscount: %v + %v != %v", nsends, nrecvs, ncas)
	}

	// run the select
	lineno = sellineno
	chosen := temp(types.Types[TINT])
	recvOK := temp(types.Types[TBOOL])
	r = nod(OAS2, nil, nil)
	r.List.Set2(chosen, recvOK)
	fn := syslook("selectgo")
	r.Rlist.Set1(mkcall1(fn, fn.Type.Results(), nil, bytePtrToIndex(selv, 0), bytePtrToIndex(order, 0), pc0, nodintconst(int64(nsends)), nodintconst(int64(nrecvs)), nodbool(dflt == nil)))
	r = typecheck(r, ctxStmt)
	init = append(init, r)

	// selv and order are no longer alive after selectgo.
	init = append(init, nod(OVARKILL, selv, nil))
	init = append(init, nod(OVARKILL, order, nil))
	if flag_race {
		init = append(init, nod(OVARKILL, pcs, nil))
	}

	// dispatch cases
	dispatch := func(cond, cas *Node) {
		cond = typecheck(cond, ctxExpr)
		cond = defaultlit(cond, nil)

		r := nod(OIF, cond, nil)

		if n := cas.Left; n != nil  n.Op == OSELRECV2 {
			x := nod(OAS, n.List.First(), recvOK)
			x = typecheck(x, ctxStmt)
			r.Nbody.Append(x)
		}

		r.Nbody.AppendNodes(cas.Nbody)
		r.Nbody.Append(nod(OBREAK, nil, nil))
		init = append(init, r)
	}

	if dflt != nil {
		setlineno(dflt)
		dispatch(nod(OLT, chosen, nodintconst(0)), dflt)
	}
	for i, cas := range casorder {
		setlineno(cas)
		dispatch(nod(OEQ, chosen, nodintconst(int64(i))), cas)
	}

	return init
}

select編譯時會根據case的數量進行優化:

1.沒有case
直接調用block

2.1個case
(1)default case,直接執行body
(2) send/recv case (block為true),按照單獨執行的結果確認,可能會發生block
(3) send調用對應的chansend1
(4) recv調用對應的chanrecv1/chanrecv2

3.2個case且包含一個default case
(1) send/recv case (block為false),按照單獨執行的結果確認case是否ok,!ok則執行default case,不會發生block
(2) send調用對應的selectnbsend
(3) recv調用對應的selectnbrecv/selectnbrecv2

4.一般的case
selectgo

總結

最后,以一張圖進行簡單總結。

以上就是go select編譯期的優化處理邏輯使用場景分析的詳細內容,更多關于go select編譯的資料請關注腳本之家其它相關文章!

您可能感興趣的文章:
  • 詳解Golang并發操作中常見的死鎖情形
  • Go 語言中的死鎖問題解決
  • Go語言死鎖與goroutine泄露問題的解決
  • golang coroutine 的等待與死鎖用法
  • Django實現jquery select2帶搜索的下拉框
  • Go語言使用select{}阻塞main函數介紹
  • matplotlib之多邊形選區(PolygonSelector)的使用
  • golang中的select關鍵字用法總結
  • Go select 死鎖的一個細節

標簽:張掖 宜賓 新余 黑龍江 江西 嘉峪關 延邊 武漢

巨人網絡通訊聲明:本文標題《go select編譯期的優化處理邏輯使用場景分析》,本文關鍵詞  select,編譯,期,的,優化,處理,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《go select編譯期的優化處理邏輯使用場景分析》相關的同類信息!
  • 本頁收集關于go select編譯期的優化處理邏輯使用場景分析的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    在线观看免费视频综合| 依依成人精品视频| 亚洲桃色在线一区| 国产精品99久久久久久有的能看 | 成人99免费视频| 国产亚洲一区二区在线观看| 国产一区二区三区免费在线观看 | 国产精品青草久久| 成人国产精品视频| 国产精品久久久久一区二区三区| 成人免费高清视频在线观看| 亚洲精品日韩综合观看成人91| 欧美日韩一区中文字幕| 另类小说欧美激情| 一区精品在线播放| 欧美性猛交xxxxxx富婆| 秋霞成人午夜伦在线观看| 欧美成人伊人久久综合网| 国产91露脸合集magnet| 一区二区三区不卡视频在线观看| 91精品国产91久久久久久一区二区| 狠狠色丁香久久婷婷综合丁香| 中文欧美字幕免费| 91精品在线观看入口| 国产精品综合在线视频| 一区二区三区四区在线免费观看| 日韩一级完整毛片| 国产精品中文字幕欧美| 亚洲精品视频在线看| 日韩一区二区中文字幕| 国产伦精一区二区三区| 亚洲精品福利视频网站| 成人免费不卡视频| 日韩手机在线导航| 日本不卡一二三| www.亚洲色图| 中文字幕五月欧美| aaa欧美大片| 丝袜美腿亚洲一区二区图片| 美女精品自拍一二三四| 一本一道综合狠狠老| 麻豆视频观看网址久久| 国产精品国产自产拍在线| 欧美日韩高清在线播放| 不卡大黄网站免费看| 美美哒免费高清在线观看视频一区二区 | a级精品国产片在线观看| 亚洲国产sm捆绑调教视频| 国产精品欧美一级免费| 欧美人伦禁忌dvd放荡欲情| 国产一区啦啦啦在线观看| 视频一区在线视频| 精品一区二区三区视频在线观看| 亚洲人成网站色在线观看| 欧美一卡二卡三卡| 欧美在线高清视频| 99久久99久久精品免费观看| 国产成人啪午夜精品网站男同| 日韩中文欧美在线| 亚洲一区二区不卡免费| 亚洲精选一二三| 亚洲人成网站色在线观看| 成人精品gif动图一区| 一区二区三区四区蜜桃| 日本美女一区二区三区| 一区二区三区国产精品| 国产精品美女久久久久久久久| 久久精品一区二区三区四区| 日韩欧美区一区二| 日韩亚洲欧美高清| 3d动漫精品啪啪1区2区免费 | 蜜芽一区二区三区| 日韩精品三区四区| 蜜臀精品久久久久久蜜臀| 亚洲电影第三页| 午夜电影一区二区| 日韩不卡一二三区| 精品影院一区二区久久久| 天天亚洲美女在线视频| 天堂在线一区二区| 乱一区二区av| 国产成人av一区二区三区在线观看| 韩国中文字幕2020精品| 岛国av在线一区| 91污在线观看| 欧美日韩视频在线第一区| 3d成人h动漫网站入口| 日韩欧美123| 欧美国产禁国产网站cc| 亚洲少妇中出一区| 三级在线观看一区二区| 欧美日韩成人激情| 欧美mv日韩mv国产网站| 国产精品一品视频| 色爱区综合激月婷婷| 欧美猛男男办公室激情| 久久精品夜夜夜夜久久| 最新日韩在线视频| 日本va欧美va瓶| 国产91精品免费| 7777精品伊人久久久大香线蕉完整版 | 国产精品毛片高清在线完整版| 国产精品国产三级国产三级人妇| 亚洲综合在线视频| 激情综合一区二区三区| av男人天堂一区| 欧美一级欧美一级在线播放| 久久精品夜夜夜夜久久| 亚洲成人免费看| 成人午夜又粗又硬又大| 欧美视频一区二区在线观看| 久久综合九色综合97婷婷 | 国产清纯白嫩初高生在线观看91| 亚洲日本在线视频观看| 老司机精品视频一区二区三区| 国产精品亚洲午夜一区二区三区| 欧美天天综合网| 中文字幕乱码久久午夜不卡 | 国产盗摄一区二区| 欧美一区二区三区系列电影| 国产精品久久精品日日| 麻豆中文一区二区| 欧洲视频一区二区| 国产综合久久久久影院| 6080亚洲精品一区二区| 日精品一区二区三区| 精品理论电影在线| 色综合咪咪久久| 亚洲国产精品久久人人爱蜜臀| 91福利国产成人精品照片| 国产精品久久精品日日| 成人激情校园春色| 日韩av在线免费观看不卡| 久久久久9999亚洲精品| 成人精品免费视频| 久久精品99国产精品日本| 亚洲欧洲韩国日本视频| 日韩一区二区在线观看视频播放| 在线观看亚洲精品| 日韩国产精品91| 亚洲福利视频一区| 91官网在线观看| 亚洲国产日韩综合久久精品| 一区二区三区视频在线看| 国产一区二区免费看| av男人天堂一区| 日韩亚洲欧美中文三级| 亚洲18影院在线观看| 色狠狠一区二区| 亚洲女性喷水在线观看一区| 国产传媒欧美日韩成人| 久久综合色8888| 国产精品亚洲专一区二区三区| 久久综合九色综合97婷婷女人| 男男视频亚洲欧美| 国内久久精品视频| 黄色成人免费在线| 久久精品国产秦先生| 视频一区中文字幕| 久久国产尿小便嘘嘘尿| 国产麻豆视频一区| 91在线视频网址| 91香蕉视频mp4| 91.麻豆视频| 日本一二三四高清不卡| 亚洲精品视频免费看| 亚洲色图制服丝袜| 欧美性大战久久| 555www色欧美视频| 三级一区在线视频先锋| 欧美一区二区三区喷汁尤物| 麻豆成人av在线| 久久久777精品电影网影网 | 久久久久久影视| 日精品一区二区| 精品精品欲导航| 国产69精品一区二区亚洲孕妇| 国产精品久久久久久妇女6080| 色呦呦国产精品| 亚洲成av人综合在线观看| 国产一区二区三区香蕉 | 色激情天天射综合网| 视频一区二区中文字幕| 欧美理论在线播放| 日本午夜精品一区二区三区电影| 久久综合九色欧美综合狠狠| 97久久超碰国产精品电影| 美女爽到高潮91| 亚洲欧美成人一区二区三区| 91精品综合久久久久久| 91在线小视频| 国产精品影视在线| 日韩精品三区四区| 亚洲精选视频在线| 国产欧美精品一区| 制服丝袜成人动漫| 成人福利视频网站| 麻豆精品国产91久久久久久| 亚洲国产精品自拍| 一区在线播放视频|