diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 3.1.0.1
+
+- Performance improvements
+
 ## 3.1.0
 
 - Overall simplification of library and reduction in boilerplate
diff --git a/bench/Bench.hs b/bench/Bench.hs
--- a/bench/Bench.hs
+++ b/bench/Bench.hs
@@ -16,11 +16,12 @@
     , bench "bigKanji - uniques" $ nf uniques bigKanji
     , bench "level 一" $ nf level (Kanji '一')
     , bench "level 串" $ nf level (Kanji '串')
+    , bench "level 糞" $ nf level (Kanji '糞')
     ]
   ]
 
 testKanji :: [Kanji]
-testKanji = map Kanji "本猫机鉛筆紙帽子包丁床天井壁光電気棚箱靴家階段戸屋根地面"
+testKanji = map Kanji "本猫机鉛筆紙帽子包丁床天井壁光電気棚箱靴家階段戸屋根地面糞"
 
 bigKanji :: [Kanji]
 bigKanji = S.toList $ fold allKanji
diff --git a/kanji.cabal b/kanji.cabal
--- a/kanji.cabal
+++ b/kanji.cabal
@@ -2,10 +2,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: c5331657544f2fd01e194d0fe17da254a4f957bf458c13dca0c5da45ea3566db
+-- hash: dd85eac021144e9cb77104be6e89fd2001a5f484e28787ff26645f99992130e0
 
 name:           kanji
-version:        3.1.0
+version:        3.1.0.1
 synopsis:       Perform 漢字検定 (Japan Kanji Aptitude Test) level analysis on Japanese Kanji
 description:    Perform 漢字検定 (Japan Kanji Aptitude Test) level analysis on Japanese Kanji.
 category:       Data
@@ -27,7 +27,7 @@
       lib
   ghc-options: -fwarn-unused-imports -fwarn-unused-binds -fwarn-name-shadowing -fwarn-unused-matches -fwarn-incomplete-patterns -fwarn-incomplete-uni-patterns
   build-depends:
-      aeson >=1.2 && <1.3
+      aeson >=1.2 && <1.4
     , base >=4.7 && <5
     , containers
     , deepseq
@@ -46,13 +46,13 @@
   default-extensions: NoImplicitPrelude OverloadedStrings
   ghc-options: -fwarn-unused-imports -fwarn-unused-binds -fwarn-name-shadowing -fwarn-unused-matches -fwarn-incomplete-patterns -fwarn-incomplete-uni-patterns -O2
   build-depends:
-      aeson >=1.2 && <1.3
+      aeson >=1.2 && <1.4
     , aeson-pretty
     , base >=4.7 && <5
     , containers
     , kanji
     , microlens >=0.4 && <0.5
-    , microlens-aeson >=2.2 && <2.3
+    , microlens-aeson >=2.2 && <2.4
     , microlens-platform
     , optparse-applicative >=0.14 && <0.15
     , protolude >=0.2 && <0.3
@@ -67,7 +67,7 @@
   ghc-options: -fwarn-unused-imports -fwarn-unused-binds -fwarn-name-shadowing -fwarn-unused-matches -fwarn-incomplete-patterns -fwarn-incomplete-uni-patterns -threaded
   build-depends:
       HUnit-approx >=1.1 && <1.2
-    , aeson >=1.2 && <1.3
+    , aeson >=1.2 && <1.4
     , base >=4.7 && <5
     , containers
     , kanji
@@ -83,10 +83,10 @@
       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:
-      aeson >=1.2 && <1.3
+      aeson >=1.2 && <1.4
     , base >=4.7 && <5
     , containers
-    , criterion >=1.1 && <1.3
+    , criterion >=1.1 && <1.5
     , kanji
     , text
   default-language: Haskell2010
diff --git a/lib/Data/Kanji.hs b/lib/Data/Kanji.hs
--- a/lib/Data/Kanji.hs
+++ b/lib/Data/Kanji.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE TupleSections #-}
+
 -- |
 -- Module    : Data.Kanji
 -- Copyright : (c) Colin Woodbury, 2015 - 2018
@@ -31,10 +33,8 @@
        , adultDen
        ) where
 
-import           Control.Applicative ((<|>))
 import           Control.Arrow hiding (second)
-import           Data.Bool (bool)
-import           Data.Foldable (foldl')
+import           Data.Foldable (foldl', fold)
 import           Data.Kanji.Levels
 import           Data.Kanji.Types
 import           Data.List (sort, group)
@@ -45,15 +45,20 @@
 
 ---
 
--- | All Japanese Kanji, grouped by their Level (級).
+-- | All Japanese `Kanji`, grouped by their Level (級).
 allKanji :: M.Map Level (S.Set Kanji)
 allKanji =  M.fromList . zip [ Ten .. ] $ map (S.map Kanji) ks
   where ks = [ tenth, ninth, eighth, seventh, sixth
              , fifth, fourth, third, preSecond, second ]
 
+-- | All Japanese `Kanji` with their `Level`.
+allKanji' :: M.Map Kanji Level
+allKanji' = M.fromList . S.toList . fold $ M.mapWithKey (\k v -> S.map (,k) v) allKanji
+
 -- | What `Level` does a Kanji belong to?
 level :: Kanji -> Maybe Level
-level k = M.foldlWithKey' (\acc l ks -> acc <|> bool Nothing (Just l) (S.member k ks)) Nothing allKanji
+level k = M.lookup k allKanji'
+{-# INLINE level #-}
 
 -- | Given the length of some String-like type and a list of `Kanji` found therein,
 -- what percentage of them were Kanji?
@@ -90,7 +95,7 @@
   where average ns = foldl' (+) 0 ns / fromIntegral (length ns)
 
 -- | How much of each `Level` is represented by a group of Kanji?
--- The distribution values must sum to 1.
+-- The distribution values will sum to <= 1.
 levelDist :: [Kanji] -> M.Map Level Float
 levelDist ks = M.fromList . map percentPair . group . sort . catMaybes $ map level ks
   where percentPair qns = (head qns, fromIntegral (length qns) / totalKs)
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -22,20 +22,21 @@
   [ testGroup "Analysis"
     [
       testCase "percentSpread totals 1.0" $ M.foldl' (+) 0 (percentSpread testKanji) @?~ 1.0
-    , testCase "levelDist totals 1.0"     $ M.foldl' (+) 0 (levelDist testKanji) @?~ 1.0
     , testCase "levelDist == adultDen"    $ M.foldl' (+) 0 (levelDist testKanji) @?~ adultDen (levelDist testKanji)
     ]
   , testGroup "JSON"
     [
-      testCase "Empty String should fail to parse"    $ assert . isError $ fromJSON @Kanji (String "")
-    , testCase "String w/ multiple Kanji should fail" $ assert . isError $ fromJSON @Kanji (String "泥棒猫")
+      testCase "Empty String should fail to parse"
+      $ assertBool "An empty String somehow parsed" . isError $ fromJSON @Kanji (String "")
+    , testCase "String w/ multiple Kanji should fail"
+      $ assertBool "A String of multiple Kanji somehow parsed" . isError $ fromJSON @Kanji (String "泥棒猫")
     , testCase "String w/ one Kanji should succeed"   $ fromJSON (String "猫") @?= Success (Kanji '猫')
     ]
   ]
   where ?epsilon = 0.001
 
 testKanji :: [Kanji]
-testKanji = map Kanji "本猫机鉛筆紙帽子包丁床天井壁光電気棚箱靴家階段戸屋根地面"
+testKanji = map Kanji "本猫机鉛筆紙帽子包丁床天井壁光電気棚箱靴家階段戸屋根地面糞"
 
 isError :: Result a -> Bool
 isError (Error _) = True
