1

[Update]

So I've changed my code to make it more readable. The function dpfsSat has two arguments, klauselMenge is a huge set with elements from X. During the recursion klauselMenge should be reduced through some functions.

import qualified Data.IntSet as Set
import qualified Data.IntMap as IntMap
import qualified Data.Vector as V

data X
    = Xin !(Int,(Set.IntSet)) deriving (Eq,Show,Ord)

type Klausel = [Atom]
type KlauselMenge = [Klausel]

dpfsSat :: Int -> KlauselMenge -> Klausel
dpfsSat fset klauselMenge = dpfsSat' fset klauselMenge []
  where
   dpfsSat' :: Int -> KlauselMenge -> Klausel -> Klausel
   dpfsSat' _ [] l = resolveDuplicateLiterals l
   dpfsSat' f k l
    | f `seq` k `seq` l `seq` False = undefined
    | [] `elem` k = []
    | ok1 = dpfsSat' f rTF l
    | ok2 = dpfsSat' f (substituteSimilarUnits (atomToTupel v2) k) l
    | ok3 = dpfsSat' f (resolveUnit1 v3 k ) ((Xin v3):l)
    | ok4 = dpfsSat' f (resolvePureLiteral v4 k) ((Xin v4):l)
    | otherwise = case (dpfsSat' f (resolveUnit1 minUnit k) ((Xin minUnit): l)) of
          [] -> dpfsSat' f ( resolveUnit1 kompl k)  ((Xin kompl): l)
          xs -> xs
    where
 rTF = resolveTrueFalse f v1 k
 minUnit = findBestLiteral4 k
 kompl   = (fst minUnit,Set.difference (Set.fromList [1..f]) (snd minUnit))
 fTF = findTrueFalse4 f k
 fSU = findSimilarAtomUnits f k
 fU  = findUnit' k
 fP  = findPureLiteral k
 ok1 = maybeToBool fTF
 ok2 = maybeToBool fSU
 ok3 = maybeToBool fU
 ok4 = maybeToBool fP
 v1  = expectJust fTF
 v2  = expectJust fSU
 v3  = expectJust fU
 v4  = expectJust fP

maybeToBool :: Maybe a -> Bool
maybeToBool (Just x) = True
maybeToBool Nothing  = False

expectJust :: Maybe a -> a
expectJust (Just x) = x
expectJust Nothing  = error "Unexpected Nothing" 

Since I'm not allowed to upload images, I do writing the output of the heap profile (-hy). The Heap is full of IntSet's.

tomic84
  • 11
  • 2
  • Are `A`, `B`, `C` and `D` supposed to be functions? Writing them in upper case makes them look like constructors instead. And how is `X` relevant? – dave4420 Feb 07 '12 at 16:29
  • Sorry for that. A, B, C and D are functions. Constructor X is needed for some possible other representation. – tomic84 Feb 07 '12 at 16:36
  • Since `a (c u) f l` is the result, its evaluation can only be forced from outside `a`. To identify the leak, we must see more code. – Daniel Fischer Feb 07 '12 at 16:47
  • now i've posted some more code. What do you mean the evaluation can only force from outside a? – tomic84 Feb 07 '12 at 17:13
  • Are you aware that case constructs like this can be written in a far less awkward fashion using [pattern guards](http://www.haskell.org/haskellwiki/Pattern_guard)? And, in the code example as you have it there now, what is this `a (c u) f l`? – leftaroundabout Feb 07 '12 at 17:58
  • Am I seeing this correctly: in `findTrueFalse` you're casting the list `concat xs` to a `Data.Vector` just to _O_ (1)-search it for an element fulfilling the predicate `fT`?? That's looks incredibly counter-productive, simply doing this search in the list directly should be faster than the casting to `Vector` alone, and it doesn't allocate any space at all like you have to for this vector! – leftaroundabout Feb 07 '12 at 18:20
  • With 'its evaluation can only be forced from outside `a`', I mean that you can't make a function completely evaluate its result from inside the function, it will only be evaluated when something outside the function needs to evaluate the result. You can make it so that it will be completely evaluated if something outside requires only partial evaluation - `let r = foo bar baz in deepseq r r` - if the result type has an `NFData` instance, but that's not necessarily a good idea. A general remark: types help, always put type signature on your function, that helps the compiler and readers ... – Daniel Fischer Feb 07 '12 at 18:43
  • ... And, I have the impression that in the code sample, `k` is the same thing as `klauselMenge`, is that correct? Can we get a compilable example? Without seeing the implementation of things like `substituteSimilarUnits` it's hard to guess where the leak may originate. – Daniel Fischer Feb 07 '12 at 18:48
  • Either `[] \`elem\` klauselMenge` or it isn't. If `[]` is an element of `klauselMenge` then `dpfsSat x y z` evaluates to `[]` irrespective of arguments. If it isn't, then the condition is never met and we always go on to `otherwise`: but unless the ghc can figure this out it has to calculate the truth value of `[] \`elem\` klauselMenge` each time it takes a recursive step. – applicative Feb 07 '12 at 21:48
  • Basicly I have a huge list (named k) with elements of the constructor X. Now there are some functions like substituteSimilarUnits or resolveUnit which tries to simplify (or shrink) k through the recursion. The argument l stores the elements which I removed from k, and represent the result. – tomic84 Feb 08 '12 at 09:29
  • ... all funtions especially findTrueFalse are running in const space – tomic84 Feb 08 '12 at 09:36
  • Does your `resolveUnit1` function forces its first argument `kompl`, and *how deep*? Simple pattern match won't force its constituents, as it is a pair. `kompl` also holds onto a `minUnit` pair, so there it might have a Wadler pair space leak perhaps. – Will Ness Feb 11 '12 at 06:40
  • btw your `maybeToBool` is exactly `isJust` and your `expectJust` is almost the same (up to an error message) as `fromJust` functions from `Data.Maybe`. – Will Ness Feb 11 '12 at 14:10

1 Answers1

1

If c is something like (1+), then this can cause a leak as you build up a chain of thunks (1+(1+(1+...))). The way to avoid this is to use seq:

let k' = c u in k' `seq` a k' f l

seq will force evaluation of k' before a k' f l can be evaluated, so this will handle the space leak in many cases.

However, seq is not a panacea, and you should read up on its proper use and avoid misusing it.

rampion
  • 87,131
  • 49
  • 199
  • 315
  • in this case, function c calculates a new list, probably a smaller one – tomic84 Feb 09 '12 at 14:11
  • @tomic84: this can still cause a chain of thunks to build up `(c (c (c (c (c ... )))))` since the value of `u` is never forced before it's passed along.. – rampion Feb 09 '12 at 14:31
  • This makes sense to me, but trying to force the evaluation with seq is not changing the heap leak. – tomic84 Feb 09 '12 at 14:37