<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          golang中降本增效的常規(guī)實(shí)踐

          共 6539字,需瀏覽 14分鐘

           ·

          2023-08-02 21:42


          最近一年各大中小廠都在搞"優(yōu)化",說(shuō)到優(yōu)化,目的還是"降本增效",降低成本,增加效益(效率)。

          技術(shù)層面,也有一些降本增效的常規(guī)操作。

          比如池化、io緩沖區(qū)技術(shù)


          golang C# eg.
          池化技術(shù) snnc.Pool ObjectPool 前端切圖仔,歸入前端資源池 , 隨用隨取
          字節(jié)數(shù)組緩沖區(qū) bytes.Buffer List ---
          io緩沖區(qū) bufio BufferStream 適度超前,賽道埋伏

          池化技術(shù) sync.Pool

          sync.Pool位于標(biāo)準(zhǔn)庫(kù),該文件提供了對(duì)臨時(shí)對(duì)象的重復(fù)使用能力, 避免了頻繁的gc, 對(duì)并發(fā)協(xié)程是安全的。

          該文件只有三個(gè)控制點(diǎn):

          • ? New: 默認(rèn)的臨時(shí)對(duì)象

          • ? Get:從池中哪一個(gè)臨時(shí)對(duì)象

          • ? Put:放回池中,以重用

          下面使用基準(zhǔn)測(cè)試進(jìn)行b.N*1000次運(yùn)算時(shí)的內(nèi)存消耗。

          package main

          import (
              "sync"
              "testing"
          )

          type Person struct {
              Age int
          }

          var (
              personPool = sync.Pool{
                  New: func() interface{} {  // 設(shè)置默認(rèn)值
                      return &Person{}
                  },
              }
          )

          func ExampleObjPool() {
              var p *Person
              for i := 0; i < 1000; i++ {
                  for j := 0; j < 1000; j++ {
                      p = personPool.Get().(*Person)
                      p.Age = i + 1
                      personPool.Put(p)
                  }
              }
              p = personPool.Get().(*Person)
              fmt.Println(p.Age)
              // output:1000
          }

          func BenchmarkWithoutPool(b *testing.B) {
              var p *Person
              b.ReportAllocs()
              b.ResetTimer()

              for i := 0; i < b.N; i++ {
                  for j := 0; j < 1000; j++ {
                      p = new(Person)    // 每次均產(chǎn)生臨時(shí)對(duì)象
                      p.Age = 23
                  }
              }
          }

          func BenchmarkWithPool(b *testing.B) {
              var p *Person
              b.ReportAllocs()
              b.ResetTimer()

              for i := 0; i < b.N; i++ {
                  for j := 0; j < 1000; j++ {
                      p = personPool.Get().(*Person)  // 從池中復(fù)用對(duì)象
                      p.Age = 23
                      personPool.Put(p)     // 放回以重用
                  }
              }
          }

          測(cè)試結(jié)果如下,sync.Pool[重用臨時(shí)對(duì)象]的性能可見(jiàn)一斑。

          bytes.Buffer

          golang很多方法內(nèi)充斥了[]byte, 就連最常規(guī)的序列化/反序列化,返回值/參數(shù)都是[]byte, 但是slice是一個(gè)冷冰冰的數(shù)據(jù)結(jié)構(gòu),沒(méi)有得心趁手的操作行為,還有很多陷阱。

            func Marshal(v any) ([]byte, error)
            func Unmarshal(data []byte, v any) 

          A bytes.Buffer is a variable-sized buffer of bytes with Read and Write methods.
          坦白講bytes.Buffer并非底層優(yōu)化機(jī)制, 實(shí)際提供了一個(gè)友好操作slice的方式。 

          下面的"abcd"字符串,先讀取首字符、后面追加字符"e":

            var b bytes.Buffer
              b.Write([]byte("abcd")) // 寫(xiě)入之后,自動(dòng)擴(kuò)容
              rdbuf := make([]byte, 1)
              _, err := b.Read(rdbuf) // 讀取一個(gè)字節(jié)的數(shù)據(jù),移動(dòng)讀off指針
              if err != nil {
                  panic(err)
              }
              fmt.Println(b.String()) // 上面讀取了一個(gè)字符,讀off已經(jīng)移動(dòng),現(xiàn)從讀off位置轉(zhuǎn)換為string
              b.WriteByte('e')        // 在尾部寫(xiě)字符
              fmt.Println(b.String())
              fmt.Printf("%d, %d \n", b.Len(), b.Cap()) // Len方法返回還能讀取的字符數(shù)量,Cap返回底層buf的容量
            
          //output:
          bcd 
          bcde
          4, 64

          io緩沖區(qū) bufio

          Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer object, creating another object (Reader or Writer) that also implements the interface but provides buffering and some help for textual I/O.

          首先我們需要知道當(dāng)應(yīng)用程序執(zhí)行IO操作(從文件、網(wǎng)絡(luò)和數(shù)據(jù)庫(kù)讀取或?qū)懭霐?shù)據(jù)),它將觸發(fā)底層的系統(tǒng)調(diào)用,從性能角度來(lái)看,這很繁重。

          緩沖IO是一種技術(shù),用于在傳遞之前暫時(shí)積累IO操作的結(jié)果。這種技術(shù)可以通過(guò)減少系統(tǒng)調(diào)用的次數(shù)來(lái)提高程序的速度

          例如,如果您想要逐字節(jié)地從磁盤(pán)讀取數(shù)據(jù),與每次直接從磁盤(pán)讀取每個(gè)字節(jié)相比,使用緩沖區(qū)IO技術(shù),我們可以一次將一個(gè)數(shù)據(jù)塊讀入緩沖區(qū),然后消費(fèi)者可以以任何您想要的方式從緩沖區(qū)讀取數(shù)據(jù)。通過(guò)減少繁重的系統(tǒng)調(diào)用,性能將得到提高。

          磁盤(pán):1.尋址:ms(毫秒) 2.磁盤(pán)帶寬[1]:MB/s
          內(nèi)存:1.尋址:ns(納秒) 2. 內(nèi)存帶寬[2]:GB/s
          磁盤(pán)比內(nèi)存在尋址上慢了10W倍,傳輸帶寬上慢了20倍。

          開(kāi)源的帶緩沖區(qū)的logrus日志寫(xiě)入hook[3],就利用了bufio技術(shù)。

           // 利用bufio針對(duì)原始io.Writer封裝成帶緩沖區(qū)的io.Writer  
           `s.writer = bufio.NewWriterSize(s.Writer, size) 
            ......
            if len(bs) > s.writer.Available() && s.writer.Buffered() > 0 {
                  if err := s.writer.Flush(); err != nil {
                      return err
                  }
              }
              _, err = s.writer.Write(bs)` 

          優(yōu)化總結(jié)

          • sync.Pool 復(fù)用臨時(shí)對(duì)象,減少內(nèi)存分配和gc次數(shù)

          • bufio利用緩沖區(qū),減少笨重的系統(tǒng)調(diào)用

          • 其實(shí)就是“降本增效”的體現(xiàn)。


          • 本文圖文原創(chuàng),歡迎斧正。耗時(shí)3h,有用指數(shù)5顆星

          引用鏈接

          [1] 磁盤(pán)帶寬: https://it.sohu.com/a/580279682_121118998
          [2] 內(nèi)存帶寬: https://baike.baidu.com/item/%E5%86%85%E5%AD%98%E5%B8%A6%E5%AE%BD
          [3] 帶緩沖區(qū)的logrus日志寫(xiě)入hook: https://github.com/zwbdzb/logrus-bufferedWriter-hook



          自古以來(lái),同步/異步都是八股文第一章

          自古以來(lái),反射也是兵家必爭(zhēng)之地

          Go編程快閃之logrus日志庫(kù)

          流量調(diào)度、微服務(wù)可尋址性和注冊(cè)中心

          摸魚(yú)快報(bào):golang net/http中的雕蟲(chóng)小技

          Go語(yǔ)言正/反向代理的姿勢(shì)

          兩將軍問(wèn)題和TCP三次握手

          點(diǎn)“戳“在看


          瀏覽 609
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  先锋AV网址 | 亚洲风情中文字幕 | igao在线 | 好吊妞视频在线观看 | 亚洲字幕网 |