Bryan O'Sullivan avatar Bryan O'Sullivan committed cc5fde1

Benchmark the performance of iconv.

On my Mac, it takes 33ms, vs about 20ms for the Haskell code.

Comments (0)

Files changed (3)

tests/benchmarks/cbits/time_iconv.c

+#include <iconv.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+int time_iconv(char *srcbuf, size_t srcbufsize)
+{
+  uint16_t *destbuf = NULL;
+  size_t destbufsize;
+  static uint16_t *origdestbuf;
+  static size_t origdestbufsize;
+  iconv_t ic = (iconv_t) -1;
+  int ret = 0;
+
+  if (ic == (iconv_t) -1) {
+    ic = iconv_open("UTF-16LE", "UTF-8");
+    if (ic == (iconv_t) -1) {
+      ret = -1;
+      goto done;
+    }
+  }
+  
+  destbufsize = srcbufsize * sizeof(uint16_t);
+  if (destbufsize > origdestbufsize) {
+    free(origdestbuf);
+    origdestbuf = destbuf = malloc(origdestbufsize = destbufsize);
+  } else {
+    destbuf = origdestbuf;
+  }
+
+  iconv(ic, &srcbuf, &srcbufsize, (char**) &destbuf, &destbufsize);
+
+ done:
+  return ret;
+}

tests/benchmarks/src/Data/Text/Benchmarks/DecodeUtf8.hs

+{-# LANGUAGE ForeignFunctionInterface #-}
+
 -- | Test decoding of UTF-8
 --
 -- Tested in this benchmark:
     ( benchmark
     ) where
 
+import Foreign.C.Types (CInt, CSize)
+import Data.ByteString.Internal (ByteString(..))
+import Foreign.Ptr (Ptr, plusPtr)
+import Foreign.ForeignPtr (withForeignPtr)
+import Data.Word (Word8)
 import Criterion (Benchmark, bgroup, bench, nf)
 import qualified Codec.Binary.UTF8.Generic as U8
 import qualified Data.ByteString as B
     lbs <- BL.readFile fp
     return $ bgroup "DecodeUtf8"
         [ bench "Strict" $ nf T.decodeUtf8 bs
+        , bench "IConv" $ iconv bs
         , bench "StrictLength" $ nf (T.length . T.decodeUtf8) bs
         , bench "StrictInitLength" $ nf (T.length . T.init . T.decodeUtf8) bs
         , bench "Lazy" $ nf TL.decodeUtf8 lbs
         , bench "LazyStringUtf8" $ nf U8.toString lbs
         , bench "LazyStringUtf8Length" $ nf (length . U8.toString) lbs
         ]
+
+iconv :: ByteString -> IO CInt
+iconv (PS fp off len) = withForeignPtr fp $ \ptr ->
+                        time_iconv (ptr `plusPtr` off) (fromIntegral len)
+
+foreign import ccall unsafe time_iconv :: Ptr Word8 -> CSize -> IO CInt

tests/benchmarks/text-benchmarks.cabal

 executable text-benchmarks
   hs-source-dirs: src ../..
   c-sources:      ../../cbits/cbits.c
+                  cbits/time_iconv.c
   main-is:        Data/Text/Benchmarks.hs
   ghc-options:    -Wall -O2
   cpp-options:    -DHAVE_DEEPSEQ
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.