第26章:高效字串處理

夢飛發表於2017-03-17

base——String [Char],bytestring——ASCII,test——Unicode字串

1.bytestring函式庫

  • 處理二進位制資料
  • vector函式庫中Vector表示這樣的型別
  • Char預設表示Unicode編碼的字元,所以用Word8來代替C語言裡的Char

    --適合大量的連續資料處理
    --Data.Vector.Mutable
    IOVector Word8
    --Data.Vector.Unboxed
    Vector Word8
    --Data.Vector
    Vector Word8
    
  • bytestring函式庫ByteString型別(也常稱strict ByteString)

    import qualified Data.ByteString as BS
    data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload
                         {-# UNPACK #-} !Int                -- offset
                         {-# UNPACK #-} !Int                -- length
    

    +ByteString包含一個指向Word8的指標,一個偏移量和一個長度

    +ForeignPtr可以方便讓外部C呼叫的指標型別

    +偏移量和長度的資料可以用來實現快速的字串分割等操作

    +函式庫中提供的各種操作函式:head,length,map,foldl,reverse等

  • Lazy ByteString

    使用連續區域儲存資料的問題,拼接操作申請記憶體有可能失敗而不得不把整個資料複製到新區域,且拼接ByteString的操作需要複製整個陣列的資料導致效率低;另一方面,連結串列資料結構是分散在記憶體中,但拼接操作只是對指標的操作,所以效率高,但訪問效能又低下。——Data.ByteString.Lazy中的Lazy ByteString能兼顧這兩種資料結構的優點。

    +Lazy ByteString基本思路是分段表示一個字串,每一個子段內部是Strict ByteString,子段間通過指標相連

    data ByteString = Empty | Chunk {-# UNPACK #-} !S.ByteString ByteString
    

    +Data.ByteString.Streaming 流處理 streaming

  • ByteString Builder

    +局域性優化——通過改造程式使用的資料結構,使之充分利用CPU快取記憶體實現加速

    --預設返回Chunk尺寸是32KB的Lazy ByteString
    hGetContents :: Handle -> IO ByteString
    readFile :: FilePath -> IO ByteString
    ...
    

    +為了自適應Chunk尺寸,尺寸小時使用記憶體複製的方式進行拼接,否則自動轉換為使用指標相連 +Data.ByteString.Builder Builder型別

    data BufferRange = BufferRange {-# UNPACK #-} !(Ptr Word8)  -- First byte of range
                                   {-# UNPACK #-} !(Ptr Word8)  -- First byte /after/ range
    
    
    data Buffer = Buffer {-# UNPACK #-} !(ForeignPtr Word8)
                         {-# UNPACK #-} !BufferRange
    
    
    data BuildSignal a =
        Done {-# UNPACK #-} !(Ptr Word8) a
      | BufferFull
          {-# UNPACK #-} !Int
          {-# UNPACK #-} !(Ptr Word8)
                         (BuildStep a)
      | InsertChunk
          {-# UNPACK #-} !(Ptr Word8)
                         S.ByteString
                         (BuildStep a)
    
    
    type BuildStep a = BufferRange -> IO (BuildSignal a)
    
    
    newtype Builder = Builder (forall r. BuildStep r -> BuildStep r)
    

    +操作Builder型別的函式

2.text和utf8-string函式庫

  • UTF8 UTF16 UTF32
  • 基於UTF16的text函式庫,處理文字

    data Text = Text
        {-# UNPACK #-} !A.Array          -- payload (Word16 elements)
        {-# UNPACK #-} !Int              -- offset (units of Word16, not Char)
        {-# UNPACK #-} !Int              -- length (units of Word16, not Char)
    
  • 在處理Text型別時,通過組合基於Char的操作,在底層操作時text函式庫會自動完成UTF16和UTF32的轉換

  • text函式庫的模組結構和bytestring類似
  • 處理UTF8編碼字串的 utf8-string函式庫
  • 一個統一的型別類

    class IsString a where
        fromString :: String -> a
    

3. mono-traversable 函式庫

  • 為了抽象上面介紹的關於字串 ByteString、Text 型別
  • Data.MonoTraversable
  • Element型別家族

    type family Element mono
    
  • 推薦使用這個模組去處理一些和底層資料型別無關的計算模組,使得編寫的演算法和底層容器資料型別無關

相關文章