Go:指針能優化性能嗎?【譯】

趁着元旦休假+春節,嘗試把2018年期間讓我受益的一些文章、問答,翻譯一下。
歡迎指正、討論,但願對你也有所幫助。
原文連接:Go: Are pointers a performance optimization?性能優化

如下,開始正文架構

過去幾周時間,我回答了許多關於使用指針優化性能的問題。彷佛不少人在這方面都感到困惑。這也能夠理解,指針確實是個複雜的話題。 但願這篇文章對你有所幫助。函數

簡而言之:不是使用指針就必定表明着性能優化。性能

若是要完全解釋這篇文章涉及的全部細節,那篇幅可能會長到沒人願意看。因此,我精簡了一下,試圖用中等篇幅也能涵蓋想說明的高級概念。測試

閱讀時須要說明一點:本文討論的是微優化,性能優化都是極其細微的。在進行微優化以前,需先進行基準測試,不然極可能看不到明顯的效果。代碼易讀性纔是第一要義。優化

什麼是指針?

指針底層表明的就是內存地址,指針解引用能夠訪問到內存存儲的具體數據值。翻譯

應用指針以後是如何起到性能優化做用的?

函數調用時,變量傳遞其實是將變量從新複製了一份,傳給函數。多數狀況下,指針都要比變量自己佔用更小的空間。指針

一般,指針大小和系統的架構體系保持一致。32位系統就是32bit,64位系統,便是64bit大小。像bool、float等標量類型,佔用的空間都小於等於指針;而多字段的符合類型,指針佔的空間更少。orm

全部,咱們的想法就基於複製指針比複製原值更高效。必定程度上,這樣想沒問題。可是性能問題涉及普遍,除了複製成本以外,還有不少因素要考慮。內存

指針是否會對性能產生負面影響?

會。主要出於兩方面的考量:

  1. 解引用雖然耗能很小,但聚沙成塔,不得不慮。
  2. 經過指針共享的數據,是放在堆上的。堆數據的清理是GC負責的,這也會產生開銷。隨着堆上數據增多,GC的工做量變大,對項目的性能影響也不容忽視。

堆與棧

堆和棧是兩個讓人頭疼的概念,可是咱們不得不直面它們。我在這儘可能用簡短的篇幅討論完。若是沒能快速理解也不要緊,我曾經也沒能很快理解。

棧:函數局部空間

每當函數被調用,都會分配一塊棧空間來存儲函數局部變量。函數佔用的棧空間大小在編譯時已經肯定。函數返回時,這塊空間就給下一個函數調用使用了,也無需馬上清理。雖然這個分配和使用過程要耗費資源,但相對來說,消耗很小。

堆:共享數據空間

如上所述,函數返回後,局部變量會被銷燬(譯者注:空間被複用或者完全回收,局部變量再也不存在)。若是返回是非指針變量,返回值會被複制給調用者,存在於調用者的棧空間中。

可是,若是返回的是指針(譯者注:也就是函數局部空間的地址),指針指向的數據就要保存在棧空間以外,這樣才能保證函數返回後,數據仍然能夠訪問。這就是堆的用處。

與堆相關的性能問題有這些:

  1. 堆空間須要從runtime申請,雖然開銷很小,也不能不考慮;
  2. 若是運行時沒有足夠空間,就須要系統調用了,這是額外的開銷;
  3. 一旦數據佔用了堆空間,就要一直佔用到沒有指針再指向它。這時候,須要GC來清理。GC會找到堆中全部沒有被飲用的值,標記爲空閒(譯者注:請參考Go垃圾回收的三色標記)。垃圾越多,GC耗時越大,系統性能越差。

那爲何還要用指針?

  1. 指針能修改傳參,提供了一種共享數據的方式。
  2. 指針能區分零值,肯定你的變量是否被賦值了。

總結

指針能夠節省複製的開銷,但同時要考慮解引用和垃圾回收帶來的影響。在我看來,性能分析結果顯示覆制是瓶頸以前,不該該考慮把指針做爲優化方案。計算機在複製方面的速度但是極快的。

但願這篇文章可讓你認識到指針是能夠派上用場的,但也不要由於要用而用。

默認仍是使用值而不是地址吧。除非語法知足不了你了。

相關文章
相關標籤/搜索