Reputation: 586
After upgrading from ghc 7.4 to ghc 7.6, I noticed a 40x slowdown in some of my database calls. To investigate, I wrote something simple to test, and my code is basically:
timeFetch :: Pipe -> UUID.UUID -> IO ()
timeFetch pipe uuid' = do
lrResult <- access pipe master "MyDB" $ (findOne (select ["uid" =: ["$in" =: [(uuidToBUUID uuid')]]] "uidCollection") :: Action IO (Maybe Document))
case lrResult of
Right _ -> do
printCrntTm "Right has result"
timeFetch pipe uuid'
Left _ -> printCrntTm "Left err"
printCrntTm
just prints the current time with a description string, and uuidToBUUID
is because the Data.UUID is a different type from Mongo's Data.Bson UUID type. The timeFetch
itself recursively calls itself indefinitely.
So in GHC 7.6, I see:
2013-12-09 09:35:52.307008 UTC Right has result
2013-12-09 09:35:52.348027 UTC Right has result
2013-12-09 09:35:52.389047 UTC Right has result
2013-12-09 09:35:52.430041 UTC Right has result
2013-12-09 09:35:52.471031 UTC Right has result
2013-12-09 09:35:52.512061 UTC Right has result
2013-12-09 09:35:52.553043 UTC Right has result
But in GHC 7.4, I See:
2013-12-09 09:36:38.109144 UTC Right has result
2013-12-09 09:36:38.110297 UTC Right has result
2013-12-09 09:36:38.111248 UTC Right has result
2013-12-09 09:36:38.112398 UTC Right has result
2013-12-09 09:36:38.113185 UTC Right has result
2013-12-09 09:36:38.114248 UTC Right has result
Which is pretty much 1ms vs 40 ms!!! I also need to mention that there was one time for the 7.6 version, I got: *** Exception: thread blocked indefinitely in an MVar operation
(but never again), and that brings me to my main question.
I dug around a bit, and I wonder if these lines of code in Database.MongoDB would be the culprit:
newCursor :: (MonadIO m, MonadBaseControl IO m) => Database -> Collection -> BatchSize -> DelayedBatch -> Action m Cursor
-- ^ Create new cursor. If you don't read all results then close it. Cursor will be closed automatically when all results are read from it or when eventually garbage collected.
newCursor db col batchSize dBatch = do
var <- newMVar dBatch
let cursor = Cursor (db <.> col) batchSize var
mkWeakMVar var (closeCursor cursor)
return cursor
#if !MIN_VERSION_base(4,6,0)
where mkWeakMVar = addMVarFinalizer
#endif
The base
module in GHC 7.6 is 4.6.x.x whereas in GHC 7.4. it is 4.5.x.x.
I am no expert at Haskell nor concurrent programming; can anybody illuminate me whether the 40x slowness I'm seeing can be explained? Does the Database.MongoDB
library code need to be debugged? Thanks in advance!
Upvotes: 4
Views: 307
Reputation: 3428
The MongoDB driver is definitely very slow. There are probably a lot of low-hanging fruit to make it faster like just removing the pipe connection system.
Upvotes: 1