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
28 changes: 14 additions & 14 deletions BENCHMARKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@ This runs with 2 concurrent queries, 10 times over:

This benchmark is unfair towards both hpgsql and postgresql-simple because the row decoder is Generically derived for them while it is hand-written for hasql.
```csv
postgresql-simple Record List (100000 rows),12.10,142.65M,120.5
hasql Record List (100000 rows),6.314,142.48M,77.8
hpgsql Record List (100000 rows),4.092,72.07M,119.7
postgresql-simple Record List (100000 rows),12.07,142.59M,99.3
hasql Record List (100000 rows),6.369,142.48M,79.0
hpgsql Record List (100000 rows),3.908,72.07M,119.9
```

### Materializing 100_000 rows with 13 columns each into a List of Tuples

This runs with 2 concurrent queries, 10 times over:
```csv
postgresql-simple Tuple List (100000 rows),14.74,142.52M,144.9
hasql Tuple List (100000 rows),8.263,142.48M,202.2
hpgsql Tuple List (100000 rows),4.648,72.07M,150.4
postgresql-simple Tuple List (100000 rows),14.37,142.54M,137.7
hasql Tuple List (100000 rows),8.305,142.48M,201.3
hpgsql Tuple List (100000 rows),4.541,72.07M,150.5
```

### Streaming 100_000 rows with 13 columns as Records
Expand All @@ -55,9 +55,9 @@ However, Hpgsql's implementation streams directly from the socket while the othe
it might not be a fair comparison in terms of implementation (e.g. you can advance multiple
cursors simultaneously, but not hpgsql's Streamed-from-socket streams).
```csv
streaming-postgresql-simple Record Stream (100000 rows),13.32,73.41M,0.0
postgresql-simple Record fold (100000 rows),13.47,77.81M,0.0
hpgsql Record Stream (100000 rows),1.421,72.07M,0.0
streaming-postgresql-simple Record Stream (100000 rows),13.59,73.34M,0.0
postgresql-simple Record fold (100000 rows),13.37,77.84M,0.0
hpgsql Record Stream (100000 rows),1.307,72.07M,0.0
```

### Streaming 100_000 rows with 13 columns as Tuples
Expand All @@ -67,16 +67,16 @@ Hpgsql's implementation streams directly from the socket while the others use cu
it might not be a fair comparison in terms of implementation (e.g. you can advance multiple
cursors simultaneously, but not hpgsql's Streamed-from-socket streams).
```csv
streaming-postgresql-simple Tuple Stream (100000 rows),14.10,73.26M,0.0
postgresql-simple Tuple fold (100000 rows),13.45,84.42M,0.0
hpgsql Tuple Stream (100000 rows),1.025,72.07M,0.0
streaming-postgresql-simple Tuple Stream (100000 rows),14.04,73.37M,0.0
postgresql-simple Tuple fold (100000 rows),13.53,82.45M,0.0
hpgsql Tuple Stream (100000 rows),880.0,72.07M,0.0
```

### COPY FROM STDIN

This compares hpgsql's binary copy to a `forM` loop writing text rows.

```csv
postgresql-simple text COPY (100000 rows),1.348,72.10M,3.8
hpgsql copyFromS binary COPY (100000 rows),672.1,72.07M,10.8
postgresql-simple text COPY (100000 rows),1.373,72.10M,3.8
hpgsql copyFromS binary COPY (100000 rows),652.0,72.07M,10.8
```
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ You should start by swapping all of "postgresql-simple", "postgresql-libpq", and

## Performance

Some benchmarks show materializing large query results with hpgsql takes 31-34% the time postgresql-simple takes, and 55-65% the time hasql takes (on my computer, Linux x64, GHC 9.10.3, compiled with -O1).
Some benchmarks show materializing large query results with hpgsql takes 28-32% the time postgresql-simple takes, and 55-62% the time hasql takes (on my computer, Linux x64, GHC 9.10.3, compiled with -O1).

When comparing hpgsql's Stream querying, hpgsql takes 9-11% the time of both [streaming-postgresql-simple](https://hackage.haskell.org/package/streaming-postgresql-simple) and postgresql-simple's cursor folding functions, although this might not be a fair comparison for some use cases.
When comparing hpgsql's Stream querying, hpgsql takes 7-11% the time of both [streaming-postgresql-simple](https://hackage.haskell.org/package/streaming-postgresql-simple) and postgresql-simple's cursor folding functions, although this might not be a fair comparison for some use cases.

hpgsql's binary COPY runs in ~50% the time of postgresql-simple's textual COPY.

Expand Down
1 change: 1 addition & 0 deletions hpgsql/src/Hpgsql/Encoding.hs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ data RowDecoder a = RowDecoder

instance Applicative RowDecoder where
pure v = RowDecoder (const $ pure v) (map (,True)) 0
{-# INLINE (<*>) #-} -- This is crucial for performance. It makes our CPS Parser truly compile to CPS row decoders.
RowDecoder p1 tc1 nc1 <*> RowDecoder p2 tc2 nc2 = RowDecoder (\colTypes -> let (cols1, cols2) = List.splitAt nc1 colTypes in p1 cols1 <*> p2 cols2) (\colTypes -> let (cols1, cols2) = List.splitAt nc1 colTypes in tc1 cols1 ++ tc2 cols2) (nc1 + nc2)

instance (TypeError (TypeLits.Text "RowDecoder does not have a Monad instance in Hpgsql because Hpgsql type-checks the result types of queries before having access to even the first data row. Use the Applicative class to write your instances or use the Monadic decoding variants.")) => Monad RowDecoder where
Expand Down
8 changes: 6 additions & 2 deletions hpgsql/src/Hpgsql/SimpleParser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
-- and perform better than attoparsec, at least the way we use it in
-- hpgsql.
--
-- In benchmarks, this can improve performance by 12-15% materializing
-- query results.
-- In benchmarks, this improved performance by 12-15% materializing
-- query results when it was introduced.
-- With the INLINE pragma in RowDecoder's Applicative's (<*>), GHC's
-- inliner was finally able to make full use of continuation passing,
-- and performance was improved by another ~14.3%, with total memory
-- allocations reduced by ~6%.
module Hpgsql.SimpleParser
( Parser (..),
ParseResult (..),
Expand Down