diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,14 @@
+# CHANGELOG
+
+### 1.1.1
+
+- `offline` and `online` were given more relaxed inner-Monad parameters:
+  `MonadResource` and `MonadIO` respectively. Usually non-constrained functions
+  perform better, but we maintain performance despite this change via
+  `SPECIALIZE` pragmas.
+
+### 1.1.0
+
+- `attoparsec` support for `streaming` is used to manually parse dump-files
+  in `offline`. This is a vast performance improvement over using
+  `Network.Pcap.offline`.
diff --git a/Network/Pcap/Streaming.hs b/Network/Pcap/Streaming.hs
--- a/Network/Pcap/Streaming.hs
+++ b/Network/Pcap/Streaming.hs
@@ -25,16 +25,23 @@
 
 ---
 
--- | Read `Packet`s from some file dump.
-offline :: FilePath -> Stream (Of Packet) (ResourceT IO) ()
+-- | Read `Packet`s from some file dump. Uses a custom parser, not /libpcap/.
+--
+-- /SPECIALIZE/d for @ResourceT IO@.
+offline :: MonadResource m => FilePath -> Stream (Of Packet) m ()
 offline = void . A.parsed packetP . Q.drop 24 . Q.readFile
+{-# SPECIALIZE offline :: FilePath -> Stream (Of Packet) (ResourceT IO) () #-}
 
 -- | Read `Packet`s from some network device. See `Network.Pcap.openLive`
 -- for a description of each argument.
-online :: String -> Int -> Bool -> Int64 -> Stream (Of Packet) IO ()
-online n s p t = lift (openLive n s p t) >>= packets
+--
+-- /SPECIALIZE/d for @IO@.
+online :: MonadIO m => String -> Int -> Bool -> Int64 -> Stream (Of Packet) m ()
+online n s p t = liftIO (openLive n s p t) >>= packets
+{-# SPECIALIZE online :: String -> Int -> Bool -> Int64 -> Stream (Of Packet) IO () #-}
 
-packets :: PcapHandle -> Stream (Of Packet) IO ()
+packets :: MonadIO m => PcapHandle -> Stream (Of Packet) m ()
 packets h = do
-  (hdr,bs) <- lift (nextBS h)
+  (hdr,bs) <- liftIO (nextBS h)
   if hdrCaptureLength hdr == 0 then pure () else P.yield (Packet hdr bs) *> packets h
+{-# SPECIALIZE packets :: PcapHandle -> Stream (Of Packet) IO () #-}
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# streaming-pcap
+# `streaming-pcap`
 
 A streaming interface to the [pcap](http://hackage.haskell.org/package/pcap-0.4.5.2)
 Haskell library, which itself is a binding to *libpcap*. Humbly adapted from
diff --git a/bench/Bench.hs b/bench/Bench.hs
new file mode 100644
--- /dev/null
+++ b/bench/Bench.hs
@@ -0,0 +1,16 @@
+module Main where
+
+import           Criterion.Main
+import           Streaming (runResourceT)
+import qualified Streaming.Prelude as P
+import           Network.Pcap.Streaming
+
+---
+
+main :: IO ()
+main = defaultMain
+  [ bgroup "Benchmarks"
+    [ bench "Count all entries in stream" . nfIO $ runResourceT (P.length_ $ offline "test/test.pcap")
+    , bench "Sum all timestamps" . nfIO $ runResourceT (P.sum_ . P.map (hdrSeconds . header) $ offline "test/test.pcap")
+    ]
+  ]
diff --git a/streaming-pcap.cabal b/streaming-pcap.cabal
--- a/streaming-pcap.cabal
+++ b/streaming-pcap.cabal
@@ -2,12 +2,12 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 0fd1730d1afb3007c23b227e5d2dad0105c2c0822a6b6a52cbe8649358211a72
+-- hash: f9eb58b0494a5226978946a213672383849ef6447e4052afd869091691f04040
 
 name:           streaming-pcap
-version:        1.1.0
+version:        1.1.1
 synopsis:       Stream packets via libpcap.
-description:    Stream packets via libpcap.
+description:    Stream packets via libpcap. Requires `libpcap` to be installed.
 category:       Web
 homepage:       https://github.com/fosskers/streaming-pcap
 author:         Colin Woodbury
@@ -19,6 +19,7 @@
 cabal-version:  >= 1.10
 
 extra-source-files:
+    CHANGELOG.md
     README.md
     test/test.pcap
     test/tsuru.pcap
@@ -26,7 +27,7 @@
 library
   hs-source-dirs:
       ./.
-  ghc-options: -fwarn-unused-imports -fwarn-unused-binds -fwarn-name-shadowing -fwarn-unused-matches -fwarn-incomplete-patterns -fwarn-incomplete-uni-patterns -O2
+  ghc-options: -fwarn-unused-imports -fwarn-unused-binds -fwarn-name-shadowing -fwarn-unused-matches -fwarn-incomplete-patterns -fwarn-incomplete-uni-patterns
   build-depends:
       attoparsec >=0.13 && <0.14
     , base >=4.7 && <5
@@ -45,7 +46,7 @@
   main-is: Test.hs
   hs-source-dirs:
       test
-  ghc-options: -fwarn-unused-imports -fwarn-unused-binds -fwarn-name-shadowing -fwarn-unused-matches -fwarn-incomplete-patterns -fwarn-incomplete-uni-patterns -O2 -threaded
+  ghc-options: -fwarn-unused-imports -fwarn-unused-binds -fwarn-name-shadowing -fwarn-unused-matches -fwarn-incomplete-patterns -fwarn-incomplete-uni-patterns -threaded
   build-depends:
       attoparsec >=0.13 && <0.14
     , base >=4.7 && <5
@@ -57,4 +58,22 @@
     , streaming-utils >=0.1 && <0.2
     , tasty >=0.11 && <1.1
     , tasty-hunit >=0.9 && <0.11
+  default-language: Haskell2010
+
+benchmark kanji-bench
+  type: exitcode-stdio-1.0
+  main-is: Bench.hs
+  hs-source-dirs:
+      bench
+  ghc-options: -fwarn-unused-imports -fwarn-unused-binds -fwarn-name-shadowing -fwarn-unused-matches -fwarn-incomplete-patterns -fwarn-incomplete-uni-patterns -threaded -O2
+  build-depends:
+      attoparsec >=0.13 && <0.14
+    , base >=4.7 && <5
+    , bytestring
+    , criterion >=1.1 && <1.5
+    , pcap >=0.4 && <0.5
+    , streaming >=0.1 && <0.3
+    , streaming-bytestring >=0.1 && <0.2
+    , streaming-pcap
+    , streaming-utils >=0.1 && <0.2
   default-language: Haskell2010
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -21,7 +21,7 @@
     , testCase "four" $ A.parseOnly four foury @?= Right 1338882754
     ]
   , testGroup "Streaming"
-    [ testCase "Packet Quantity (test)" $ runResourceT (P.length_ $ offline "test/test.pcap") >>= (@?= 4)
+    [ testCase "Packet Quantity (test)"  $ runResourceT (P.length_ $ offline "test/test.pcap") >>= (@?= 4)
     -- , testCase "Packet Quantity (tsuru)" $ runResourceT (P.length_ $ offline "test/tsuru.pcap") >>= (@?= 21273)
     ]
   ]
