{-# LANGUAGE OverloadedStrings #-}
module EL.Private.Cpu where
import qualified Data.Set as Set
import qualified Data.Text as Text
import Data.Text (Text)
import qualified Data.Text.IO as Text.IO
import qualified System.Environment as Environment
import qualified System.Info
import qualified System.Process as Process
import qualified Text.Read as Read
physicalCores :: IO Int
physicalCores = maybe getPhysicalCores return =<< envCores
getPhysicalCores :: IO Int
getPhysicalCores = case System.Info.os of
"darwin" -> read <$>
Process.readProcess "/usr/sbin/sysctl" ["-n", "hw.physicalcpu"] ""
"linux" -> linuxPhysicalCores <$> Text.IO.readFile "/proc/cpuinfo"
_ -> error $ "unknown platform: " ++ System.Info.os
envCores :: IO (Maybe Int)
envCores = (Read.readMaybe =<<) <$> Environment.lookupEnv "CPUS"
linuxPhysicalCores :: Text -> Int
linuxPhysicalCores = length . unique . map cpu . Text.splitOn "\n\n"
where
cpu = filter (\s -> any (`Text.isPrefixOf` s) ["physical id", "core id"])
. Text.lines
unique :: Ord a => [a] -> [a]
unique = Set.toList . Set.fromList