Skip to content

Commit 583be8f

Browse files
committed
Only read stdout when running with --more-verbose
When not running with `-V` or `--more-verbose`, we now pipe the stdout of the executable under test to /dev/null. This prevents quickbench from running out of memory in case the output is huge (GBs). MINOR REMARK With my version of GHC (9.6.6), all exceptions unfortunately get annoted `withBinaryFile`, see https://gitlab.haskell.org/ghc/ghc/-/issues/20886. For example, when running `quickbench -w doesnotexist`, the error message is: ``` /dev/null: withBinaryFile: does not exist (No such file or directory) ``` When running `quickbench -w doesnotexist --more-verbose`, avoiding the call to `withBinaryFile`, the error message is the much clearer: ``` doesnotexist: readCreateProcess: posix_spawnp: does not exist (No such file or directory) ``` This is not ideal, but I believe using the latest version of GHC will fix it.
1 parent ca3c22e commit 583be8f

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

src/QuickBench.hs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ import Data.Maybe
1313
import Data.Time.Clock
1414
import Data.Time.Format
1515
import Data.Time.LocalTime
16+
import GHC.IO.Exception (IOErrorType(..))
1617
import Safe
1718
import System.Console.Docopt
1819
import System.Directory
1920
import System.Environment
2021
import System.Exit
2122
import System.IO
23+
import System.IO.Error (mkIOError)
2224
import System.Process
2325
import Text.Show.Pretty
2426
import Text.Printf
@@ -198,17 +200,31 @@ replaceExecutable exe cmd = (unwords (exe:args), exe, args) where args = drop 1
198200
time :: Opts -> String -> [String] -> IO Float
199201
time opts exe args = do
200202
t1 <- getCurrentTime
201-
(c, o, e) <- readProcessWithExitCode' exe args ""
203+
maybeOutput <- if (moreVerbose opts)
204+
then Just <$> readCreateProcess (proc exe args) ""
205+
else const Nothing <$> callProcessIgnoreOutput exe args
202206
t2 <- getCurrentTime
203-
when (not $ null o) $ outvv opts $ (if verbose opts then "\n" else "") ++ o
204-
unless (c == ExitSuccess) $ out opts $ " (error: " ++ clean e ++ ") "
207+
case maybeOutput of
208+
Just o -> when (not $ null o) $ outvv opts $ (if verbose opts then "\n" else "") ++ o
209+
Nothing -> return ()
205210
return $ realToFrac $ diffUTCTime t2 t1
206211

207-
-- ^ This variant also returns a failure when the executable is missing.
208-
readProcessWithExitCode' :: FilePath -> [String] -> String -> IO (ExitCode, String, String)
209-
readProcessWithExitCode' exe args inp =
210-
readProcessWithExitCode exe args inp
211-
`catch` \(e :: IOException) -> return (ExitFailure 1, "", show e)
212+
callProcessIgnoreOutput :: FilePath -> [String] -> IO ()
213+
callProcessIgnoreOutput cmd args =
214+
withBinaryFile "/dev/null" WriteMode $ \devNull ->
215+
withCreateProcess (proc cmd args){std_out = UseHandle devNull} $ \_ _ _ ph -> do
216+
exit_code <- waitForProcess ph
217+
case exit_code of
218+
ExitSuccess -> return ()
219+
ExitFailure r -> processFailedException "callProcessIgnoreOutput" cmd args r
220+
where
221+
-- Copy/paste from "process" System.Process.
222+
processFailedException :: String -> String -> [String] -> Int -> IO a
223+
processFailedException fun cmd args exit_code =
224+
ioError (mkIOError OtherError (fun ++ ": " ++ cmd ++
225+
concatMap ((' ':) . show) args ++
226+
" (exit " ++ show exit_code ++ ")")
227+
Nothing Nothing)
212228

213229
printSummary :: Opts -> [String] -> [String] -> Int -> [[[Float]]] -> IO ()
214230
printSummary opts cmds exes cyc results = do

0 commit comments

Comments
 (0)