成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

GO語言性能問題的發現和解決

云計算
事情起因于公司一位同事在內部郵件組中post了一個問題,一個使用了go1.8.3寫的業務程序跑了一段時間后出現部分goroutine卡在等待一個鎖ForkLock的現象,同事認為這是go1.8.3的bug,升級到go1.10后沒有再重現。

事件起因

事情起因于公司一位同事在內部郵件組中post了一個問題,一個使用了go1.8.3寫的業務程序跑了一段時間后出現部分goroutine卡在等待一個鎖ForkLock的現象,同事認為這是go1.8.3的bug,升級到go1.10后沒有再重現。為了搞清楚這個事情,同事在github上發了issue https://github.com/golang/go/issues/26836,期間也做了很多重現的嘗試,但并未重現。

GO語言性能問題的發現和解決

我瀏覽了一下出現該問題的業務代碼,大概的使用方式是父進程調用os/exec下的Command開子進程執行shell命令。Command后面會調用golang封裝的forkExec來開子進程并執行命令,forkExec使用了ForkLock。

問題分析

ForkLock 的存在是為了避免下面的情況:在有多個goroutine同時fork exec的情況下, 為了子進程只繼承它需要的文件描述符,需要在父進程在創建這些文件描述符的時候加上O_CLOEXEC標志,這樣在子進程中這些描述符是關閉的,子進程按需把自己需要繼承的描述符打開即可。

Linux在2.6.27之后,打開文件或者管道,和設置O_CLOEXEC是一個原子操作,因此問題不大,但golang對內核版本的要求是2.6.23及以上,另外Unix系統中,open和設置O_CLOEXEC是兩個操作,如果在兩個操作之間發生fork, 子進程就可能繼承它不需要的文件描述符,因此需要加鎖。重點看下forkExec時候的源代碼:

GO語言性能問題的發現和解決

從問題的現象看,肯定是某goroutine在forkExecPipe或者forkAndExecInChild這兩步卡住了,鎖沒釋放,因此有些goroutine一直拿不到鎖,饑餓致死。forkExecPipe***調用的是內核pipe2, forkAndExecInChild***調用的是內核clone和exec。

原因猜測

pipe2是一個快速系統調用,因此可能block的系統調用是clone和exec, 加上在go1.10上這個問題沒有重現,對比go1.8代碼和go1.9在forkAndExecInChild函數上的差異:

go1.8

GO語言性能問題的發現和解決

go1.9

GO語言性能問題的發現和解決

go1.9增加了CLONE_VFORK和CLONE_VM 。只帶SIGCHILD的clone可以認為類似于fork(***都是調用do_fork), fork的問題是,在父進程占用內存越大性能越差,具體可以看這個鏈接:https://bugzilla.redhat.com/show_bug.cgi?id=682922

這個case 2011年提出,今年7月還在更新,這個case反饋的問題是,盡管Linux kernel 引入copy-on-write機制,但fork的時候依然要拷貝頁表,進程虛擬內存越大,需要拷貝的頁表項越多,因此fork越慢。Golang的討論組有人測試過,heap size在2G的情況下,fork耗時可以到毫秒級別, 正常是及幾十微秒,上千倍差距。

Go1.9加上這兩個參數是為了讓子進程和父進程共享內存,相當于調用vfork, 不需要拷貝頁表, 加快創建速度,從測試效果看,穩定在幾十微妙。

GO語言性能問題的發現和解決

所以一個合理的猜測是,在低于go1.9版寫的程序中,當程序內存占用足夠大,而且創建進程頻率足夠頻繁,會導致ForkLock長時間等待。

實驗論證

我用go1.8.3寫了一個測試程序,在2核4G的虛擬機(kernel 3.10.0-693.17.1.el7.x86_64)下測試。

GO語言性能問題的發現和解決

在外部每隔10秒,給這個程序發SIGUSR1信號,打印運行時堆棧,運行一段時間后,部分goroutine獲取ForkLock的時間越來越長。見下面兩圖:

GO語言性能問題的發現和解決

GO語言性能問題的發現和解決

而在go1.9及以上版本上并未出現上述情況,這個結果我覺得已經可以說明問題。升級版本到go1.9及以上版本可以解決該問題。

寫在***

vfork是為了解決fork拷貝頁表項導致的性能問題, 而且大部分場景fork之后是調用exec,exec要把所有頁表刪除重置新的頁表, 實在沒必要再拷貝頁表項。但由于vfork父子進程共享內存,所以使用要很小心,如果子進程修改某個變量,會影響到父進程,而且kernel會掛起父進程,讓子進程先執行,這些限制基本限制vfork只適合跟exec的場景,不如fork通用。

正因為vfork的使用需要小心,因此go1.9準備加入vfork發布之前,有人提出代碼不夠健壯,因為rawVforkSyscall返回之后,在父進程段還執行指令,這樣子進程有機會破壞雙方的共享棧,因此提了一個commit去讓rawVforkSyscall在返回后,在父進程段什么都不做直接return,解決這個互相影響,如圖所示:

GO語言性能問題的發現和解決

如有興趣深入了解,可以看下這個commit 的review,Rob Pike等人都有發言。

https://go-review.googlesource.com/c/go/+/46173

GO語言性能問題的發現和解決

 

責任編輯:未麗燕 來源: 51CTO.com
相關推薦

2012-11-23 13:09:38

PHP性能

2013-07-31 16:56:08

系統級編程語言語言性能語言

2009-02-17 14:20:01

JavaFX 1.1腳本語言JavaFX Mobi

2017-10-10 15:14:23

BUGiOS 11蘋果

2010-10-13 10:47:52

GoGoogle

2016-06-15 10:08:29

云計算

2022-03-31 10:25:20

物聯網工業 4.0大數據分析

2009-06-29 09:38:50

JSF標簽JSF

2023-10-16 16:08:42

工業 4.0物聯網邊緣計算

2024-06-05 14:35:26

2011-03-31 16:45:39

Redhat配置nagios

2020-08-24 08:34:03

命令性能優化

2023-12-30 18:35:37

Go識別應用程序

2025-03-27 00:45:00

2020-03-16 14:32:08

Git工具開發

2024-10-10 15:32:51

2010-06-09 09:39:42

Opensuse雙系統

2020-03-11 09:57:10

數據安全網絡安全網絡攻擊

2015-01-21 15:40:44

GoRuby

2024-04-28 10:17:30

gnetGo語言
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字字幕在线中文乱码范文 | 午夜激情国产 | 91精品国产91久久久久久吃药 | 欧美黄色绿像 | 尤物在线 | 日韩欧美精品在线 | 日韩成人在线免费观看 | 7777精品伊人久久精品影视 | 亚洲精品中文在线 | 国产成人精品一区二区三区 | 日本成人福利视频 | 天天夜夜人人 | 日韩欧美国产一区二区 | 欧美在线观看网站 | 成人欧美一区二区三区视频xxx | 大象一区| 日本中文在线视频 | 日韩一区二区三区精品 | 国产成人a亚洲精品 | 日韩三片 | 成人综合视频在线 | 中文天堂在线一区 | 中文字幕成人在线 | 国产日韩欧美在线观看 | 欧美精品在线播放 | 久久精品色欧美aⅴ一区二区 | 亚洲国产成人精品女人久久久 | 夏同学福利网 | 精久久久| 国产成人99久久亚洲综合精品 | 国产草草视频 | 欧美日韩视频在线第一区 | 久久精品国产99国产精品亚洲 | 精品福利在线视频 | 国产一区二区三区四区hd | 欧美 日韩 亚洲91麻豆精品 | 久久天堂网 | 一区二区三区亚洲精品国 | 日韩av网址在线观看 | 狠狠综合久久av一区二区老牛 | 成人精品系列 |