本文目錄一覽:
golang配製高性能sql.DB
有很多教程是關於Go的sql.DB類型和如何使用它來執行SQL數據庫查詢的。但大多數內容都沒有講述 SetMaxOpenConns() , SetMaxIdleConns() 和 SetConnMaxLifetime()方法, 您可以使用它們來配置sql.DB的行為並改變其性能。
轉自:
整理:go語言中文文檔:
在本文我將詳細解釋這些設置的作用,並說明它們所能產生的(積極和消極)影響。
一個sql.DB對象就是一個數據庫連接池,它包含“正在用”和“空閑的”連接。一個正在用的連接指的是,你正用它來執行數據庫任務,例如執行SQL語句或行查詢。當任務完成連接就是空閑的。
當您創建sql.DB執行數據庫任務時,它將首先檢查連接池中是否有可用的空閑連接。如果有可用的連接,那麼Go將重用現有連接,並在執行任務期間將其標記為正在使用。如果池中沒有空閑連接,而您需要一個空閑連接,那麼Go將創建一個新的連接。
默認情況下,在同一時間打開連接的數量是沒有限制(包含使用中+空閑)。但你可以通過SetMaxOpenConns()方法實現自定義限制,如下所示:
在這個示例代碼中,連接池現在有5個並發打開的連接數。如果所有5個連接都已經被標記為正在使用,並且需要另一個新的連接,那麼應用程序將被迫等待,直到5個連接中的一個被釋放並變為空閑。
為了說明更改MaxOpenConns的影響,我運行了一個基準測試,將最大打開連接數設置為1、2、5、10和無限。基準測試在PostgreSQL數據庫上執行並行的INSERT語句,您可以在這裡找到代碼。測試結果:
對於這個基準測試,我們可以看到,允許打開的連接越多,在數據庫上執行INSERT操作所花費的時間就越少(打開的連接數為1時,執行速度3129633ns/op,而無限連接:531030ns/op——大約快了6倍)。這是因為允許打開的連接越多,可以並發執行的數據庫查詢就越多。
默認情況下,sql.DB允許連接池中最多保留2個空閑連接。你可以通過SetMaxIdleConns()方法改變它,如下所示:
從理論上講,允許池中有更多的空閑連接將提高性能,因為這樣就不太可能從頭開始建立新連接——因此有助於提升數據庫性能。
讓我們來看看相同的基準測試,最大空閑連接設置為none, 1,2,5和10:
當MaxIdleConns設置為none時,必須為每個INSERT從頭創建一個新的連接,我們可以從基準測試中看到,平均運行時和內存使用量相對較高。
只允許保留和重用一個空閑連接對基準測試影響特別明顯——它將平均運行時間減少了大約8倍,內存使用量減少了大約20倍。繼續增加空閑連接池的大小會使性能變得更好,儘管改進並不明顯。
那麼,您應該維護一個大的空閑連接池嗎?答案取決於應用程序。重要的是要意識到保持空閑連接是有代價的—它佔用了可以用於應用程序和數據庫的內存。
還有一種可能是,如果一個連接空閑時間太長,那麼它可能會變得不可用。例如,MySQL的wait_timeout設置將自動關閉任何8小時(默認)內未使用的連接。
當發生這種情況時,sql.DB會優雅地處理它。壞連接將自動重試兩次,然後放棄,此時Go將該連接從連接池中刪除,並創建一個新的連接。因此,將MaxIdleConns設置得太大可能會導致連接變得不可用,與空閑連接池更小(使用更頻繁的連接更少)相比,會佔有更多的資源。所以,如果你很可能很快就會再次使用,你只需保持一個空閑的連接。
最後要指出的是,MaxIdleConns應該總是小於或等於MaxOpenConns。Go強制執行此操作,並在必要時自動減少MaxIdleConns。
現在讓我們看看SetConnMaxLifetime()方法,它設置連接可重用的最大時間長度。如果您的SQL數據庫也實現了最大連接生命周期,或者—例如—您希望方便地在負載均衡器後交換數據庫,那麼這將非常有用。
你可以這樣使用它:
在這個例子中,所有的連接都將在創建後1小時“過期”,並且在過期後無法重用。但注意:
從理論上講,ConnMaxLifetime越短,連接過期的頻率就越高——因此,需要從頭創建連接的頻率就越高。為了說明這一點,我運行了將ConnMaxLifetime設置為100ms、200ms、500ms、1000ms和無限(永遠重用)的基準測試,默認設置為無限打開連接和2個空閑連接。這些時間段顯然比您在大多數應用程序中使用的時間要短得多,但它們有助於很好地說明行為。
在這些特定的基準測試中,我們可以看到,與無限生存期相比,在100ms生存期時內存使用量增加了3倍以上,而且每個INSERT的平均運行時也稍微長一些。
如果您在代碼中設置了ConnMaxLifetime,那麼一定要記住連接將過期(隨後重新創建)的頻率。例如,如果您總共有100個連接,而ConnMaxLifetime為1分鐘,那麼您的應用程序可能每秒鐘殺死和重新創建1.67個連接(平均值)。您不希望這個頻率太大,最終會阻礙性能,而不是提高性能。
最後,如果不說明超過數據庫連接數量的硬限制將會發生什麼,那麼本文就不完整了。 為了說明這一點,我將修改postgresql.conf文件,這樣總共只允許5個連接(默認是100個)…
然後在無限連接的情況下重新運行基準測試……
一旦達到5個連接的硬限制,數據庫驅動程序(pq)立即返回一個太多客戶端連接的錯誤消息,而無法完成INSERT。為了防止這個錯誤,我們需要將sql.DB中打開連接的最大總數(正在使用的+空閑的)設置為低於5。像這樣:
現在,sql.DB在任何時候最多只能創建3個連接,基準測試運行時應該不會出現任何錯誤。但是這樣做需要注意:當達到開放連接數限制,並且所有連接都在使用時,應用程序需要執行的任何新的數據庫任務都將被迫等待,直到連接標記為空閑。例如,在web應用程序的上下文中,用戶的HTTP請求看起來會“掛起”,甚至在等待數據庫任務運行時可能會超時。
為了減輕這種情況,你應該始終在一個上下文中傳遞。在調用數據庫時,啟用上下文的方法(如ExecContext()),使用固定的、快速的超時上下文對象。
總結
1、根據經驗,應該顯式設置MaxOpenConns值。這應該小於數據庫和基礎設施對連接數量的硬性限制。
2、一般來說,更高的MaxOpenConns和MaxIdleConns值將帶來更好的性能。但你應該注意到效果是遞減的,連接池空閑連接太多(連接沒有被重用,最終會變壞)實際上會導致性能下降。
3、為了降低上面第2點帶來的風險,您可能需要設置一個相對較短的ConnMaxLifetime。但你也不希望它太短,導致連接被殺死或不必要地頻繁重建。
4、MaxIdleConns應該總是小於或等於MaxOpenConns。
對於中小型web應用程序,我通常使用以下設置作為起點,然後根據實際吞吐量水平的負載測試結果進行優化。
golang什麼場景設置runtime.GOMAXPROCS=cpu數量會提高性能
這是測試的代碼
// parallel package main
import ( “fmt” “math/rand” “runtime” “sort” “time” )
func testData() [][]int { now := time.Now() src := rand.NewSource(now.UnixNano()) seed := rand.New(src) data := make([][]int, 10000) for i := 0; i len(data); i++ { data[i] = make([]int, 10000) for j := 0; j 10000; j++ { data[i][j] = seed.Intn(100000) } } return data }
func test() { data := testData() ch := make(chan int) for i := 0; i len(data); i++ { go func(ch chan int, data []int) { sort.Ints(data[:]) ch – 1 }(ch, data[i][:]) } for i := 0; i len(data); i++ { -ch } }
func main() { st := time.Now() test() fmt.Println(time.Since(st)) runtime.GOMAXPROCS(2) st = time.Now() test() fmt.Println(time.Since(st)) runtime.GOMAXPROCS(3) st = time.Now() test() fmt.Println(time.Since(st)) runtime.GOMAXPROCS(4) st = time.Now() test() fmt.Println(time.Since(st)) fmt.Println(“Hello World!”) }
該代碼的作用是生成10000個數組,每個數組有10000個int元素,分別調用不同CPU核數進行排序計算。用的是Go內置的排序函數。
中的時間如下
25.6269405s
14.1753705s
10.3508423s
8.5466479s
分別是單核,2核,3核,4核的計算時間。的確用多核後計算速度提升很大。
Golang 新手該怎麼提升能力
新手入門技巧:
1.升級你的角色等級
Pokemon GO 遊戲如果你的目標不是只有 “收集所有神奇寶貝” 的話,而是想用心玩這款遊戲,那角色等級絕對是最重要的一環,甚至比抓到稀有神奇寶貝還重要。
等級高,你才能解鎖與獲得更多道具,如:更強的寶貝球、讓你更好抓神奇寶貝的 Razz Berry、經驗值兩倍的 Lucky Egg、吸引野生神奇寶貝的 Incense 等等。
等級高,你才能抓到 CP (戰鬥力)更強的神奇寶貝。
等級越高,你才能提升更多神奇寶貝的能力(CP 與 HP)。
升級到 5 級才能進到 GYM 里跟其他玩家戰鬥。
2.不要擔心寶貝球不夠
寶貝球是一個非常容易取得的道具,幾乎每一個 PokeStop 都能獲得兩個以上,等你玩久之後一定會嫌寶貝球數量太多(背包預設只能裝 350 個道具),把它丟掉會變成非常平常的事,所以抓神奇寶貝時不用害怕丟歪失手,盡情的試手感與角度吧!不過還是要注意次數,小心神奇寶貝會烙跑走。
3.抓光每一個你所看到的神奇寶貝
跟一開始一樣,如果你的目標不是只有 “收集所有神奇寶貝”,那隻要是地圖中出現的神奇寶貝,就全部都抓光吧!每抓一隻都能獲得經驗值、STARDUST 與 CANDY,而這些都是遊戲中非常重要的元素。
4.先不要提升與進化你的神奇寶貝
剛開始玩時角色等級還太低,因此抓的神奇寶貝 CP 戰鬥力都會很低,幾乎只有 100 以下,所以千萬不要急著提升或進化神奇寶貝,把 STARDUST 與 CANDY 保留下來,等到等級變高開始抓到 CP 200、甚至是 300 以上再決定也不遲,而且你還有機會抓到已經進化過的神奇寶貝。
5.只保留 CP 高與能力強的神奇寶貝(僅限初期)
CP 值(戰鬥力)越高,基本上也代表神奇寶貝越強,因此當你抓到相同的神奇寶貝時,如果 CP 值差 30 以上,就不要猶豫把它 TRANSFER 換成 CANDY 吧!這樣也不佔空間。而等到後期開始專心養育神奇寶貝時,可以參考這篇文章,把素質最好的神奇寶貝找出來。
資訊頁面下方可看到它的攻擊能力,每一位神奇寶貝都有兩種,上面是普通攻擊、下面為絕招,目前還沒有數據表示哪種能力比較強,就筆者經驗來說,數字越高也代表攻擊力越強,因此如果是 CP 很接近的神奇寶貝,就從這邊比較,保留攻擊力強的那隻就對了!
6.慎選使用 Incense 與 Lucky Egg 的時機
當等級升到 5 級以及 7 級時,你會各獲得一個 Incense 道具(30 分鐘內吸引更多的野生神奇寶貝),筆者會建議先使用一個就好,另一個等到 9 級獲得 Lucky Egg(30 分鐘內可兩倍經驗值) 時再用,效果會更好。
Lucky Egg 與 Incense 同時使用的效果非常不錯,30 分鐘內你一定會抓到非常多神奇寶貝,而每抓一個可獲得 100XP,經驗值兩倍之後變 200XP,如果是新的神奇寶貝再加 500XP,兩倍之後變 1000XP,30 分鐘過後你的經驗值絕對是用暴增,連升兩級都有可能,所以說不要急的把 Lucky Egg 或 Incense 用掉,等到兩個都擁有時再用效果是最大的!
7.Pokestops 的更新速度很快
Pokestops 是用來提供玩家道具的物件,因此更新速度非常快,當你翻轉過一次變成紫色後,只要等個 1~2 分鐘 5 分鐘就會再變回藍色,因此如果你缺道具又懶得一直走的話,就找一個翻得到 2~3 Pokestops 的位置待著,不到一小時你絕對能獲得非常多道具。(經實測確定是 5 分鐘,之前筆者邊寫文章邊測才會感覺更新超快的錯覺)
如果你住的地方就能翻到 Pokestops,那真的非常幸運,不僅有無限道具可以取得,待在家也能賺 XP 經驗值,不用走來走去。(每翻一次可獲得 50XP)。
8.捕捉 Pokemon 神奇寶貝時需不需要停下來?
這點筆者相信很多玩家都很好奇,答案是:不用!
只要是進入抓 Pokemon 神奇寶貝的畫面後,即便你離碰到的位置超過 1 公里(誇飾法),都能正常捕捉,唯一要注意是如果你有開啟 AR,那就手機畫面就必須保持碰到神奇寶貝的方向才能看到它,沒開啟 AR 的玩家則怎麼移動都沒關係。
不過安全第一,筆者還是建議抓神奇寶貝時停下來,才不會發生任何意外,除非你目前正在搭車。
9.不用太擔心 Pokemon GO 是不是很耗網路流量
繼 T-Moblie 之後,香港 CSL Mobile 也表示會推出 Pokemon GO 無限網路流量服務,因此很多玩家都誤認為 Pokemon GO 非常耗網路流量,事實上你不用太擔心!
根據筆者玩兩周的經驗,角色等級已升級到 14,收集上百隻神奇寶貝,平時在外也正常使用 F
原創文章,作者:BGZJ,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/141436.html