diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # lzlib
 
+## 0.3.3.0
+
+  * Add `Exception` instance for `LZError`
+  * Bug fixes
+
 ## 0.3.2.0
 
   * Add `compressBest` and `compressFast`
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -17,6 +17,11 @@
   * Uses `c2hs` instead of `hsc2hs`
   * Provides a high-level (`ByteString`-based) API
 
+### Performance
+
+Performance should be comparable to the
+[lzip](http://download.savannah.gnu.org/releases/lzip/) C++ program.
+
 ## Hacking
 
 Run
diff --git a/lzlib.cabal b/lzlib.cabal
--- a/lzlib.cabal
+++ b/lzlib.cabal
@@ -1,6 +1,6 @@
 cabal-version:      1.18
 name:               lzlib
-version:            0.3.2.0
+version:            0.3.3.0
 license:            BSD3
 license-file:       LICENSE
 copyright:          Copyright: (c) 2019-2020 Vanessa McHale
diff --git a/src/Codec/Lzip.hs b/src/Codec/Lzip.hs
--- a/src/Codec/Lzip.hs
+++ b/src/Codec/Lzip.hs
@@ -63,31 +63,30 @@
 
     let setup = do
             decoder <- lZDecompressOpen
-            maxSz <- lZDecompressWriteSize decoder
-            let bufMax = min (32 * 1024) (fromIntegral maxSz)
             buf <- mallocBytes szOut
-            pure (decoder, buf, bufMax)
+            pure (decoder, buf)
 
-    let cleanup (decoder, buf, _) =
+    let cleanup (decoder, buf) =
             lZDecompressClose decoder *>
             free buf
 
     BSL.fromChunks <$> bracket
         setup
         cleanup
-        (\(decoder, buf, bufMax) -> loop decoder bss bufMax (buf, szOut) mempty)
+        (\(decoder, buf) -> loop decoder bss (buf, szOut) mempty)
 
     where
-        loop :: LZDecoderPtr -> [BS.ByteString] -> Int -> (Ptr UInt8, Int) -> [BS.ByteString] -> IO [BS.ByteString]
-        loop decoder bss maxSz (buf, bufSz) !acc = do
+        loop :: LZDecoderPtr -> [BS.ByteString] -> (Ptr UInt8, Int) -> [BS.ByteString] -> IO [BS.ByteString]
+        loop decoder bss (buf, bufSz) !acc = do
+            maxSz <- fromIntegral <$> lZDecompressWriteSize decoder
             bss' <- case bss of
                 [bs'] -> if BS.length bs' > maxSz
                     then do
                         let (bs'', rest) = BS.splitAt maxSz bs'
-                        BS.useAsCStringLen bs'' $ \(bytes, sz) ->
+                        BS.unsafeUseAsCStringLen bs'' $ \(bytes, sz) ->
                             lZDecompressWrite decoder (castPtr bytes) (fromIntegral sz) $> [rest]
                     else
-                        BS.useAsCStringLen bs' $ \(bytes, sz) -> do
+                        BS.unsafeUseAsCStringLen bs' $ \(bytes, sz) -> do
                             void $ lZDecompressWrite decoder (castPtr bytes) (fromIntegral sz)
                             void $ lZDecompressFinish decoder
                             pure []
@@ -110,7 +109,7 @@
                     when (bytesRead == -1) $
                         error . show =<< lZDecompressErrno decoder
                     bsActual <- BS.packCStringLen (castPtr buf, fromIntegral bytesRead)
-                    loop decoder bss' maxSz (buf, bufSz) (acc ++ [bsActual])
+                    loop decoder bss' (buf, bufSz) (acc ++ [bsActual])
 
 -- | Defaults to 'Six'
 {-# NOINLINE compress #-}
@@ -156,12 +155,26 @@
     where
         loop :: LZEncoderPtr -> [BS.ByteString] -> (Ptr UInt8, Int) -> Int -> [BS.ByteString] -> IO [BS.ByteString]
         loop encoder bss (buf, sz) bytesRead acc = do
+            maxSz <- fromIntegral <$> lZCompressWriteSize encoder
             bss' <- case bss of
-                [bs] -> BS.unsafeUseAsCStringLen bs $ \(bytes, sz') -> do
-                    void $ lZCompressWrite encoder (castPtr bytes) (fromIntegral sz')
-                    lZCompressFinish encoder $> []
-                (bs:bss') -> BS.unsafeUseAsCStringLen bs $ \(bytes, sz') ->
-                    lZCompressWrite encoder (castPtr bytes) (fromIntegral sz') $> bss'
+                [bs] -> if BS.length bs > maxSz
+                    then
+                        let (bs', rest) = BS.splitAt maxSz bs in
+                            BS.unsafeUseAsCStringLen bs' $ \(bytes, sz') -> do
+                                void $ lZCompressWrite encoder (castPtr bytes) (fromIntegral sz')
+                                lZCompressFinish encoder $> [rest]
+                    else
+                        BS.unsafeUseAsCStringLen bs $ \(bytes, sz') -> do
+                            void $ lZCompressWrite encoder (castPtr bytes) (fromIntegral sz')
+                            lZCompressFinish encoder $> []
+                (bs:bss') -> if BS.length bs > maxSz
+                    then
+                        let (bs', rest) = BS.splitAt maxSz bs in
+                        BS.unsafeUseAsCStringLen bs' $ \(bytes, sz') ->
+                            lZCompressWrite encoder (castPtr bytes) (fromIntegral sz') $> (rest:bss')
+                    else
+                        BS.unsafeUseAsCStringLen bs $ \(bytes, sz') ->
+                            lZCompressWrite encoder (castPtr bytes) (fromIntegral sz') $> bss'
                 [] -> pure []
             bytesActual <- lZCompressRead encoder buf (fromIntegral sz)
             res <- lZCompressFinished encoder
diff --git a/src/Codec/Lzip/Raw.chs b/src/Codec/Lzip/Raw.chs
--- a/src/Codec/Lzip/Raw.chs
+++ b/src/Codec/Lzip/Raw.chs
@@ -53,6 +53,7 @@
                       , lZApiVersion
                       ) where
 
+import Control.Exception (Exception)
 import Foreign.C.Types
 import Foreign.Ptr (Ptr)
 
@@ -80,6 +81,8 @@
 
 instance Show LZErrno where
     show = lZStrerror
+
+instance Exception LZErrno where
 
 -- | Abstract data type
 data LZEncoder
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -18,7 +18,7 @@
 compressFileGeneral f fp = parallel $
     it ("decompress . compress should be identity (" ++ fp ++ ")") $ do
         str <- f fp
-        decompress (compress str) `shouldBe` str
+        decompress (compressBest str) `shouldBe` str
 
 compressFileFreaky :: FilePath -> Spec
 compressFileFreaky = compressFileGeneral nonstandardRead
@@ -30,7 +30,7 @@
 decompressFileGeneral f fp = parallel $
     it ("compress . decompress should be identity (" ++ fp ++ ")") $ do
         str <- f fp
-        compress (decompress str) `shouldBe` str
+        compressBest (decompress str) `shouldBe` str
 
 decompressFileFreaky :: FilePath -> Spec
 decompressFileFreaky = decompressFileGeneral nonstandardRead
