diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Revision history for Z-IO
 
+## 0.7.1.0  -- 2020-03-16
+
+* Use `CPtr` from Z-Data instead of `ForeignPtr`.
+
 ## 0.7.0.0  -- 2020-03-09
 
 * Change resource `Pool` to keyed by default, add `SimplePool`.
diff --git a/Z-IO.cabal b/Z-IO.cabal
--- a/Z-IO.cabal
+++ b/Z-IO.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.4
 name:               Z-IO
-version:            0.7.0.0
+version:            0.7.1.0
 synopsis:           Simple and high performance IO toolkit for Haskell
 description:
   Simple and high performance IO toolkit for Haskell, including
@@ -125,7 +125,7 @@
     , time                  >=1.9   && <=2.0
     , unix-time             >=0.4.7 && <=0.5
     , unordered-containers  ^>=0.2
-    , Z-Data                ^>=0.7
+    , Z-Data                >=0.7.1 && <0.8
 
   default-language:   Haskell2010
   default-extensions:
diff --git a/Z/IO/BIO/Zlib.hsc b/Z/IO/BIO/Zlib.hsc
--- a/Z/IO/BIO/Zlib.hsc
+++ b/Z/IO/BIO/Zlib.hsc
@@ -65,6 +65,7 @@
 import           Z.Data.Text.Print  (Print)
 import           Z.Data.Vector.Base as V
 import           Z.Foreign
+import           Z.Foreign.CPtr
 import           Z.IO.BIO
 import           Z.IO.Exception
 
@@ -125,7 +126,9 @@
         defaultMemLevel V.empty Z_DEFAULT_STRATEGY V.defaultChunkSize
 
 -- | A foreign pointer to a zlib\'s @z_stream_s@ struct.
-data ZStream = ZStream (ForeignPtr ZStream) (IORef Bool)
+data ZStream = ZStream 
+    {-# UNPACK #-} !(CPtr ZStream) 
+    {-# UNPACK #-} !(IORef Bool)
 
 -- | Make a new compress node.
 --
@@ -134,17 +137,19 @@
             => CompressConfig
             -> IO (ZStream, BIO V.Bytes V.Bytes)
 newCompress (CompressConfig level windowBits memLevel dict strategy bufSiz) = do
-    zs <- mask_ (newForeignPtr free_z_stream_deflate =<< create_z_stream)
-    buf <- A.newPinnedPrimArray bufSiz
-    set_avail_out zs buf bufSiz
-    bufRef <- newIORef buf
+    (zs, _) <- newCPtrUnsafe 
+        (\ mba## -> do
+            ps <- throwOOMIfNull (create_z_stream mba##)
+            throwZlibIfMinus_ $ deflate_init2 ps level windowBits memLevel strategy)
+        free_z_stream_deflate
 
-    withForeignPtr zs $ \ ps -> do
-        throwZlibIfMinus_ $ deflate_init2 ps level windowBits memLevel strategy
-        unless (V.null dict) $
-            throwZlibIfMinus_ . withPrimVectorUnsafe dict $ \ pdict off len ->
+    unless (V.null dict) .  withCPtr zs $ \ ps -> do
+        throwZlibIfMinus_ . withPrimVectorUnsafe dict $ \ pdict off len ->
             deflate_set_dictionary ps pdict off (fromIntegral $ len)
 
+    buf <- A.newPinnedPrimArray bufSiz
+    set_avail_out zs buf bufSiz
+    bufRef <- newIORef buf
     finRef <- newIORef False
     return (ZStream zs finRef, BIO (zwrite zs bufRef) (zflush finRef zs bufRef []))
   where
@@ -153,7 +158,7 @@
         zloop zs bufRef []
 
     zloop zs bufRef acc = do
-        oavail :: CUInt <- withForeignPtr zs $ \ ps -> do
+        oavail :: CUInt <- withCPtr zs $ \ ps -> do
             throwZlibIfMinus_ (deflate ps (#const Z_NO_FLUSH))
             (#peek struct z_stream_s, avail_out) ps
         if oavail == 0
@@ -174,7 +179,7 @@
         then return Nothing
         else do
             buf <- readIORef bufRef
-            (r, osiz) <- withForeignPtr zs $ \ ps -> do
+            (r, osiz) <- withCPtr zs $ \ ps -> do
                 r <- throwZlibIfMinus (deflate ps (#const Z_FINISH))
                 oavail :: CUInt <- (#peek struct z_stream_s, avail_out) ps
                 return (r, bufSiz - fromIntegral oavail)
@@ -195,7 +200,7 @@
 -- | Reset compressor's state so that related 'BIO' can be reused.
 compressReset :: ZStream -> IO ()
 compressReset (ZStream fp finRef) = do
-    throwZlibIfMinus_ (withForeignPtr fp deflateReset)
+    throwZlibIfMinus_ (withCPtr fp deflateReset)
     writeIORef finRef False
 
 -- | Compress some bytes.
@@ -221,12 +226,15 @@
 -- The returned 'BIO' node can be reused only if you call 'decompressReset' on the 'ZStream'.
 newDecompress :: DecompressConfig -> IO (ZStream, BIO V.Bytes V.Bytes)
 newDecompress (DecompressConfig windowBits dict bufSiz) = do
-    zs <- newForeignPtr free_z_stream_inflate =<< create_z_stream
+    (zs, _) <- newCPtrUnsafe 
+        (\ mba## -> do
+            ps <- throwOOMIfNull (create_z_stream mba##)
+            throwZlibIfMinus_ $ inflate_init2 ps windowBits)
+        free_z_stream_inflate
+
     buf <- A.newPinnedPrimArray bufSiz
     set_avail_out zs buf bufSiz
     bufRef <- newIORef buf
-    withForeignPtr zs $ \ ps -> do
-        throwZlibIfMinus_ $ inflate_init2 ps windowBits
     finRef <- newIORef False
     return (ZStream zs finRef, BIO (zwrite zs bufRef) (zflush finRef zs bufRef []))
   where
@@ -235,7 +243,7 @@
         zloop zs bufRef []
 
     zloop zs bufRef acc = do
-        oavail :: CUInt <- withForeignPtr zs $ \ ps -> do
+        oavail :: CUInt <- withCPtr zs $ \ ps -> do
             r <- throwZlibIfMinus (inflate ps (#const Z_NO_FLUSH))
             when (r == (#const Z_NEED_DICT)) $
                 if V.null dict
@@ -263,7 +271,7 @@
         then return Nothing
         else do
             buf <- readIORef bufRef
-            (r, osiz) <- withForeignPtr zs $ \ ps -> do
+            (r, osiz) <- withCPtr zs $ \ ps -> do
                 r <- throwZlibIfMinus (inflate ps (#const Z_FINISH))
                 r' <- if r == (#const Z_NEED_DICT)
                 then if V.null dict
@@ -292,7 +300,7 @@
 -- | Reset decompressor's state so that related 'BIO' can be reused.
 decompressReset :: ZStream -> IO ()
 decompressReset (ZStream fp finRef) = do
-    throwZlibIfMinus_ (withForeignPtr fp inflateReset)
+    throwZlibIfMinus_ (withCPtr fp inflateReset)
     writeIORef finRef False
 
 -- | Decompress some bytes.
@@ -334,7 +342,7 @@
 throwZlibIfMinus_ = void . throwZlibIfMinus
 
 foreign import ccall unsafe
-    create_z_stream :: IO (Ptr ZStream)
+    create_z_stream :: MBA## (Ptr ZStream) -> IO (Ptr ZStream)
 
 foreign import ccall unsafe "hs_zlib.c &free_z_stream_inflate"
     free_z_stream_inflate :: FunPtr (Ptr ZStream -> IO ())
@@ -366,16 +374,16 @@
 foreign import ccall unsafe
     inflateReset :: Ptr ZStream -> IO CInt
 
-set_avail_in :: ForeignPtr ZStream -> V.Bytes -> Int -> IO ()
+set_avail_in :: CPtr ZStream -> V.Bytes -> Int -> IO ()
 set_avail_in zs buf buflen = do
     withPrimVectorSafe buf $ \ pbuf _ ->
-        withForeignPtr zs $ \ ps -> do
+        withCPtr zs $ \ ps -> do
             (#poke struct z_stream_s, next_in) ps pbuf
             (#poke struct z_stream_s, avail_in) ps (fromIntegral buflen :: CUInt)
 
-set_avail_out :: ForeignPtr ZStream -> MutablePrimArray RealWorld Word8 -> Int -> IO ()
+set_avail_out :: CPtr ZStream -> MutablePrimArray RealWorld Word8 -> Int -> IO ()
 set_avail_out zs buf bufSiz = do
     withMutablePrimArrayContents buf $ \ pbuf ->
-        withForeignPtr zs $ \ ps -> do
+        withCPtr zs $ \ ps -> do
             (#poke struct z_stream_s, next_out) ps pbuf
             (#poke struct z_stream_s, avail_out) ps (fromIntegral bufSiz :: CUInt)
diff --git a/Z/IO/LowResTimer.hs b/Z/IO/LowResTimer.hs
--- a/Z/IO/LowResTimer.hs
+++ b/Z/IO/LowResTimer.hs
@@ -62,7 +62,7 @@
 data TimerList = TimerItem {-# UNPACK #-} !Counter (IO ()) TimerList | TimerNil
 
 data LowResTimerManager = LowResTimerManager
-    (Array (IORef TimerList))
+    (SmallArray (IORef TimerList))
     -- timer queue
     (MVar Int)
     -- current time wheel's index
@@ -82,7 +82,7 @@
     iqueue <- unsafeFreezeArr queue
     return (LowResTimerManager iqueue indexLock regCounter runningLock)
 
-lowResTimerManager :: IORef (Array LowResTimerManager)
+lowResTimerManager :: IORef (SmallArray LowResTimerManager)
 {-# NOINLINE lowResTimerManager #-}
 lowResTimerManager = unsafePerformIO $ do
     numCaps <- getNumCapabilities
diff --git a/Z/IO/Network/TCP.hs b/Z/IO/Network/TCP.hs
--- a/Z/IO/Network/TCP.hs
+++ b/Z/IO/Network/TCP.hs
@@ -144,7 +144,7 @@
 --
 startServerLoop :: HasCallStack
                 => Int -- ^ backLog
-                -> (UVManager -> Resource UVStream) -- ^ uv_tream_t initializer
+                -> (UVManager -> Resource UVStream) -- ^ uv_stream_t initializer
                 -> (Ptr UVHandle -> IO ())          -- ^ bind function
                 -> (FD -> (UVStream -> IO ()) -> IO ()) -- ^ thread spawner
                 -> (UVStream -> IO ())                  -- ^ worker
diff --git a/cbits/hs_zlib.c b/cbits/hs_zlib.c
--- a/cbits/hs_zlib.c
+++ b/cbits/hs_zlib.c
@@ -32,8 +32,9 @@
 #include <stdlib.h>
 #include <HsFFI.h>
 
-z_stream * create_z_stream(void){
-    z_stream *stream = malloc(sizeof(z_stream));
+z_stream* create_z_stream(z_stream** streamp){
+    z_stream* stream = malloc(sizeof(z_stream));
+    *streamp = stream;
     if (stream) {
         stream->zalloc = Z_NULL;
         stream->zfree = Z_NULL;
