Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _benchplot/benchplot-dict.R
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ groupby.data.exceptions = {list(
"chdb" = {list(
)},
"haskell" = {list(
"Not tested/OOM" = c("G1_1e8_1e2_0_0", "G1_1e8_1e1_0_0", "G1_1e8_2e0_0_0", "G1_1e8_1e2_0_1", "G1_1e8_1e2_5_0", "G1_1e9_1e2_0_0","G1_1e9_1e2_0_1","G1_1e9_1e2_5_0","G1_1e9_1e1_0_0", "G1_1e9_2e0_0_0")
"Not tested/OOM" = c("G1_1e8_1e2_5_0", "G1_1e9_1e2_0_0","G1_1e9_1e2_0_1","G1_1e9_1e2_5_0","G1_1e9_1e1_0_0", "G1_1e9_2e0_0_0")
)}
)}
groupby.exceptions = task.exceptions(groupby.query.exceptions, groupby.data.exceptions)
Expand Down
2 changes: 1 addition & 1 deletion haskell/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.2.0.0
3.6.0.0
1 change: 1 addition & 0 deletions haskell/cabal.project
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
packages: .
allow-newer: all
optimization: 2
19 changes: 19 additions & 0 deletions haskell/exec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,23 @@ fi
source ./haskell/ver-haskell.sh

[ -d "$HOME/.cache/cabal/packages/hackage.haskell.org" ] || cabal update

## Cap GHC's heap at 90% of machine memory so we exit gracefully.
if [ -r /proc/meminfo ]; then
MEM_KB=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo)
else
MEM_KB=$(( $(sysctl -n hw.memsize) / 1024 ))
fi
export GHCRTS="-M$(( MEM_KB * 9 / 10 / 1024 ))m"

## Best-effort THP=always (GHC heap on 2MB pages); skipped when sudo is unavailable.
THP=/sys/kernel/mm/transparent_hugepage
if [ -w "$THP/enabled" ]; then
echo always > "$THP/enabled" || true
echo defer+madvise > "$THP/defrag" || true
elif sudo -n true 2>/dev/null; then
echo always | sudo tee "$THP/enabled" > /dev/null || true
echo defer+madvise | sudo tee "$THP/defrag" > /dev/null || true
fi

cabal --project-dir=./haskell run -O2 "$1-haskell"
58 changes: 32 additions & 26 deletions haskell/groupby-haskell.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import BenchmarkCommon
import Control.Arrow ((>>>))
import Control.Monad (forM_)
import Data.Functor ((<&>))
import qualified Data.List as L
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as VU
import DataFrame.Functions ((.=))
import qualified DataFrame.Functions as F
Expand All @@ -21,12 +19,14 @@ import DataFrame.IO.CSV (
)
import DataFrame.IO.CSV.Fast
import DataFrame.Internal.DataFrame (DataFrame)
import DataFrame.Internal.Expression (AggStrategy (..), Expr (..))
import DataFrame.Schema (schemaType)
import DataFrame.Internal.Expression (Expr (..))
import qualified DataFrame.Operations.Aggregation as D
import qualified DataFrame.Operations.Core as D
-- Semigroup DataFrame (row concat)
import DataFrame.Operations.Merge ()
import qualified DataFrame.Operations.Subset as D
import qualified DataFrame.Operations.Transformations as D
import DataFrame.Schema (schemaType)
import System.Environment (getEnv, lookupEnv)
import System.IO (BufferMode (..), hPutStrLn, hSetBuffering, stderr, stdout)

Expand Down Expand Up @@ -111,7 +111,7 @@ runBenchmark srcFile dataName machineType = do
config
df
"sum v1 by id1"
(D.groupBy [F.name id1] >>> D.aggregate [F.sum v1 `F.as` "v1_sum"])
(D.groupBy [F.name id1] >>> D.aggregate ["v1_sum" .= F.sum v1])
(\res -> [chkSumInt "v1_sum" res])

-- Q2: Sum v1 by id1:id2
Expand Down Expand Up @@ -174,36 +174,43 @@ runBenchmark srcFile dataName machineType = do
(D.groupBy [F.name id3] >>> D.aggregate ["diff" .= F.maximum v1 - F.minimum v2])
(\res -> [chkSumInt "diff" res])

-- Q8: Largest two v3 by id6.
-- Polars takes top_k(2) per group then explodes and sums; the sum of the
-- exploded values equals the sum of (max + 2nd-max) per group, which is
-- what 'top2Sum' computes per group. Checksum parity is preserved.
-- Q8: largest two v3 by id6, exploded to two rows per group
-- (polars reference shape: group_by(id6).agg(v3.top_k(2)).explode(v3)).
-- 'F.topK' returns the pair in descending order; the library has no explode,
-- so we take the two ends and stack the halves.
runQuestion
config
df
"largest two v3 by id6"
(D.groupBy [F.name id6] >>> D.aggregate ["largest2_v3" .= top2Sum v3])
(\res -> [chkSumDbl "largest2_v3" res])
( \d ->
let top2 = F.col @[Double] "top2"
r =
( D.groupBy [F.name id6]
>>> D.aggregate ["top2" .= F.topK 2 v3]
>>> D.derive "v3" (F.fromMaybe nan (F.firstOrNothing top2))
>>> D.derive "v3b" (F.fromMaybe nan (F.lastOrNothing top2))
)
d
in D.select ["id6", "v3"] r
<> D.rename "v3b" "v3" (D.select ["id6", "v3b"] r)
)
(\res -> [chkSumDbl "v3" res])

-- Q9: Regression (r^2 of v1 vs v2) by id2, id4.
-- corr(v1,v2)^2 from the per-group sums of v1, v2, v1*v2, v1^2, v2^2 and the
-- group count, then summed. Matches polars pl.corr(...)**2 then .sum().
runQuestion
config
( D.derive
"v2v2"
(dv2 * dv2)
(D.derive "v1v1" (dv1 * dv1) (D.derive "v1v2" (dv1 * dv2) df))
)
df
"regression v1 v2 by id2 id4"
( D.groupBy [F.name id2, F.name id4]
>>> D.aggregate
[ "n" .= F.count v1
, "sx" .= F.sum dv1
, "sy" .= F.sum dv2
, "sxy" .= F.sum (F.col @Double "v1v2")
, "sxx" .= F.sum (F.col @Double "v1v1")
, "syy" .= F.sum (F.col @Double "v2v2")
, "sxy" .= F.sum (dv1 * dv2)
, "sxx" .= F.sum (dv1 * dv1)
, "syy" .= F.sum (dv2 * dv2)
]
>>> D.derive "r2" r2Expr
>>> D.select [F.name id2, F.name id4, "r2"]
Expand Down Expand Up @@ -244,6 +251,12 @@ runQuestion cfg inputDF qLabel transform chkFn = do
writeLog cfg qLabel outRows outCols runNum calcTime memUsage chkValues chkTime
putStrLn $ qLabel ++ " completed."

{- | Stand-in for a group with fewer than two values. The benchmark data has no
size-1 id6 groups, so this never reaches the checksum.
-}
nan :: Double
nan = 0 / 0

chkSumInt :: String -> DataFrame -> Double
chkSumInt col df =
case D.columnAsIntVector (F.col @Int (T.pack col)) df of
Expand All @@ -256,13 +269,6 @@ chkSumDbl col df =
Right vec -> VU.sum vec
Left _ -> 0.0

-- | Per-group sum of the two largest values (top_k(2) then sum, like polars Q8).
top2Sum :: Expr Double -> Expr Double
top2Sum = Agg (CollectAgg "top2Sum" f)
where
f :: V.Vector Double -> Double
f v = Prelude.sum (take 2 (L.sortBy (flip compare) (V.toList v)))

{- | Squared Pearson correlation of v1,v2 from per-group moment sums (polars Q9).
Degenerate groups (zero variance) contribute 0 rather than poisoning the sum
with NaN; the 1e7 data has no such groups so the checksum is unaffected.
Expand Down
18 changes: 6 additions & 12 deletions haskell/haskell-benchmark.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ common df-deps
build-depends: base >= 4.7 && < 5
, bytestring >= 0.11 && < 0.13
, cassava >= 0.1 && < 1
, dataframe-core ^>= 2.1
, dataframe-parsing ^>= 2.1
, dataframe-csv ^>= 2.1
, dataframe-operations ^>= 2.1
, dataframe-fastcsv ^>= 1.3
, dataframe-core ^>= 2.5
, dataframe-parsing ^>= 2.2
, dataframe-csv ^>= 2.3
, dataframe-operations ^>= 2.5
, dataframe-fastcsv ^>= 1.4.1
, text >= 2.1
, vector >= 0.12
, time >= 1.9
, process >= 1.6
, directory >= 1.3
, unix
default-language: Haskell2010
ghc-options: -O2 -threaded -rtsopts "-with-rtsopts=-N8 -c -F1.5 -M30g -Fd1"
ghc-options: -O2 -threaded -rtsopts "-with-rtsopts=-N16 -A64m -n4m -I0 -c -F1.5 -M30g -Fd1"

executable groupby-haskell
import: df-deps
Expand All @@ -32,9 +32,3 @@ executable join-haskell
main-is: join-haskell.hs
hs-source-dirs: .
other-modules: BenchmarkCommon

executable timeq
import: df-deps
main-is: timeq.hs
hs-source-dirs: .
build-depends: deepseq
10 changes: 5 additions & 5 deletions haskell/join-haskell.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ import DataFrame.IO.CSV (
defaultReadOptions,
)
import DataFrame.IO.CSV.Fast (fastReadCsvWithOpts)
import DataFrame.Internal.DataFrame (DataFrame)
import DataFrame.Schema (SchemaType, schemaType)
import DataFrame.Internal.DataFrame (DataFrame, forceDataFrame)
import qualified DataFrame.Operations.Core as D
import qualified DataFrame.Operations.Join as DJ
import DataFrame.Schema (SchemaType, schemaType)
import Numeric (showEFloat)
import System.Environment (getEnv, lookupEnv)
import System.IO (BufferMode (..), hSetBuffering, stdout)
import System.Mem (performGC)

main :: IO ()
main = do
Expand Down Expand Up @@ -148,10 +149,9 @@ runJoin ::
IO ()
runJoin cfg leftDF rightDF qLabel joinFn = do
forM_ [1, 2] $ \runNum -> do
performGC
(resultDF, calcTime) <- timeIt $ do
let res = freshRun runNum (uncurry joinFn) (leftDF, rightDF)
_ <- evaluate res
return res
evaluate (forceDataFrame (freshRun runNum (uncurry joinFn) (leftDF, rightDF)))

memUsage <- getMemoryUsage
let (outRows, outCols) = D.dimensions resultDF
Expand Down
104 changes: 0 additions & 104 deletions haskell/timeq.hs

This file was deleted.

2 changes: 1 addition & 1 deletion haskell/ver-haskell.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ set -e

cd haskell

export HASKELL_DF_VERSION="2.2.0.0"
export HASKELL_DF_VERSION="3.6.0.0"

echo "${HASKELL_DF_VERSION}" > VERSION

Expand Down
20 changes: 0 additions & 20 deletions logs.csv
Original file line number Diff line number Diff line change
Expand Up @@ -7392,23 +7392,3 @@ ip-172-31-18-189,1784046154,duckdb,1.5.4,08e34c447b,groupby,G1_1e9_1e2_5_0,17840
ip-172-31-18-189,1784046154,duckdb,1.5.4,08e34c447b,groupby,G1_1e9_1e2_5_0,1784053271.16982,finish,0,0,c6id.4xlarge
ip-172-31-18-189,1784046154,duckdb,1.5.4,08e34c447b,join,J1_1e9_NA_0_0,1784053286.1849,start,,,c6id.4xlarge
ip-172-31-18-189,1784046154,duckdb,1.5.4,08e34c447b,join,J1_1e9_NA_0_0,1784055922.71045,finish,0,0,c6id.4xlarge
ip-172-31-18-189,1786373405,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e7_1e2_0_0,1786373407.63123,start,,,c6id.4xlarge
ip-172-31-18-189,1786373405,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e7_1e2_0_0,1786373435.22305,finish,7,0,c6id.4xlarge
ip-172-31-18-189,1786373405,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e7_1e1_0_0,1786373450.23815,start,,,c6id.4xlarge
ip-172-31-18-189,1786373405,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e7_1e1_0_0,1786373477.74633,finish,7,0,c6id.4xlarge
ip-172-31-18-189,1786373405,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e7_2e0_0_0,1786373492.76142,start,,,c6id.4xlarge
ip-172-31-18-189,1786373405,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e7_2e0_0_0,1786373527.4555,finish,11,0,c6id.4xlarge
ip-172-31-18-189,1786373405,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e7_1e2_0_1,1786373542.47061,start,,,c6id.4xlarge
ip-172-31-18-189,1786373405,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e7_1e2_0_1,1786373567.22655,finish,7,0,c6id.4xlarge
ip-172-31-18-189,1786373405,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e7_1e2_5_0,1786373582.24164,start,,,c6id.4xlarge
ip-172-31-18-189,1786373405,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e7_1e2_5_0,1786373582.84261,finish,8,0,c6id.4xlarge
ip-172-31-18-189,1786373702,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e8_1e2_0_0,1786373703.5071,start,,,c6id.4xlarge
ip-172-31-18-189,1786373702,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e8_1e2_0_0,1786373734.20329,finish,10,251,c6id.4xlarge
ip-172-31-18-189,1786373702,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e8_1e1_0_0,1786373749.21738,start,,,c6id.4xlarge
ip-172-31-18-189,1786373702,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e8_1e1_0_0,1786373779.22521,finish,10,251,c6id.4xlarge
ip-172-31-18-189,1786373702,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e8_2e0_0_0,1786373794.24029,start,,,c6id.4xlarge
ip-172-31-18-189,1786373702,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e8_2e0_0_0,1786373824.67766,finish,14,251,c6id.4xlarge
ip-172-31-18-189,1786373702,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e8_1e2_0_1,1786373839.69275,start,,,c6id.4xlarge
ip-172-31-18-189,1786373702,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e8_1e2_0_1,1786373869.93667,finish,10,251,c6id.4xlarge
ip-172-31-18-189,1786373702,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e8_1e2_5_0,1786373884.95176,start,,,c6id.4xlarge
ip-172-31-18-189,1786373702,haskell,2.2.0.0,dataframe-2.2.0.0,groupby,G1_1e8_1e2_5_0,1786373885.54634,finish,8,0,c6id.4xlarge
Loading
Loading