Skip to content

Commit

Permalink
fix space leak by including writing out shrunken images in paralleliz…
Browse files Browse the repository at this point in the history
…ed operation

as discussed in the comment, the old approach would hold all shrunken
images in memory at once, before writing any of them to disk.  the new
approach permits each shrunken image to be written to disk as soon as
it's ready.

this source of the space leak and the solution was suggested by
claude.ai.

fixes jerith666#98
  • Loading branch information
jerith666 committed Nov 14, 2024
1 parent 79ac246 commit a7f015b
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 13 deletions.
1 change: 1 addition & 0 deletions shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ let
extra
JuicyPixels
parallel
parallel-io
regex-compat
safe
tasty
Expand Down
1 change: 1 addition & 0 deletions src/generator/elbum.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ executable elbum
, unix
, bytestring
, parallel
, parallel-io
, extra
, safe
, base >=4.10
Expand Down
25 changes: 12 additions & 13 deletions src/generator/gen-album.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import Codec.Picture.Metadata
import qualified Codec.Picture.Types
import qualified Codec.Picture.Types as M
import Control.Concurrent.Async
import Control.Concurrent.ParallelIO (parallel)
import Control.Monad
import Control.Parallel.Strategies
import Data.Aeson (decode, encode)
import qualified Data.ByteString.Lazy.Char8 as C
import Data.Either
Expand Down Expand Up @@ -472,13 +472,20 @@ procImage s d (f, i) = do

procSrcSet :: FilePath -> FilePath -> FilePath -> DynamicImage -> Int -> Int -> IO (ImgSrc, [ImgSrc])
procSrcSet s d f i w h = do
let shrunkenSrcs = map (shrinkImgSrc s d f i w h) (sizes w) `using` parList rdeepseq
shrunken = map third shrunkenSrcs
rawImg <- copyRawImgSrc s d f w h
-- putStrSameLn $ "processing " ++ show f ++ " "
mapM_ (writeShrunkenImgSrc . fstSnd) shrunkenSrcs
{- note: we combine shrinking the image and writing it out to disk as a single
parallelizable operation. if instead we parallelize all the shrinking
operations first, then parallelize all the writing, we keep all the shrunken
images in memory at once -}
shrunken <- parallel $ map (shrinkAndWrite s d f i w h) (sizes w)
return (rawImg, shrunken)

shrinkAndWrite :: FilePath -> FilePath -> FilePath -> DynamicImage -> Int -> Int -> Int -> IO ImgSrc
shrinkAndWrite s d f i w h maxwidth = do
let (rgbfImgSmall, fsmpath, imgSrc) = shrinkImgSrc s d f i w h maxwidth
writeShrunkenImgSrc (rgbfImgSmall, fsmpath)
return imgSrc

writeShrunkenImgSrc :: (Codec.Picture.Types.Image PixelRGBF, FilePath) -> IO ()
writeShrunkenImgSrc (ism, fsmpath) = do
createDirectoryIfMissing True $ takeDirectory fsmpath
Expand Down Expand Up @@ -580,11 +587,3 @@ maybeTuple (ma, mb) =
Nothing
Nothing ->
Nothing

fstSnd :: (a, b, c) -> (a, b)
fstSnd (a, b, _) =
(a, b)

third :: (a, b, c) -> c
third (_, _, c) =
c
2 changes: 2 additions & 0 deletions src/generator/gen-album.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
, filepath
, JuicyPixels
, parallel
, parallel-io
, regex-compat
, safe
, tasty
Expand All @@ -30,6 +31,7 @@ mkDerivation {
filepath
JuicyPixels
parallel
parallel-io
regex-compat
safe
tasty
Expand Down

0 comments on commit a7f015b

Please sign in to comment.