forked from aristanetworks/nix-serve-ng
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.hs
133 lines (101 loc) · 4.29 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE OverloadedStrings #-}
{-| To benchmark `nix-serve-ng`, run the following commands:
> $ nix build
> $ PATH="./result/bin:${PATH}" cabal v1-bench --benchmark-option=--time-mode=wall
You can compare against the old `nix-serve` by changing the first command
to:
> $ nix build --file '<nixpkgs>' nix-serve
-}
module Main where
import Control.Applicative (empty)
import Data.Foldable (traverse_)
import Data.Vector (Vector)
import Numeric.Natural (Natural)
import Turtle (d)
import qualified Control.Concurrent.Async as Async
import qualified Data.ByteString.Lazy as ByteString
import qualified Data.ByteString.Lazy.Char8 as Char8
import qualified Data.Text as Text
import qualified Data.Vector as Vector
import qualified Network.HTTP.Client as HTTP
import qualified System.IO as IO
import qualified System.IO.Temp as Temp
import qualified Test.Tasty.Bench as Bench
import qualified Turtle
prepareMixed :: Natural -> IO (Vector FilePath)
prepareMixed maxSize =
Temp.withSystemTempFile "zeros" \tempFile handle -> do
IO.hClose handle
let generate i = do
let size =
truncate
( fromIntegral maxSize
** (fromIntegral i / fromIntegral numFiles)
:: Double
)
ByteString.writeFile tempFile (ByteString.replicate size 0)
text <- Turtle.single do
Turtle.inproc "nix-store"
[ "--add", Text.pack tempFile ]
empty
return (Text.unpack (Turtle.lineToText text))
Vector.generateM (fromIntegral numFiles) generate
prepareConstant :: Natural -> IO (Vector FilePath)
prepareConstant size =
Temp.withSystemTempFile "zeros" \tempFile handle -> do
IO.hClose handle
ByteString.writeFile tempFile (ByteString.replicate (fromIntegral size) 0)
text <- Turtle.single do
Turtle.inproc "nix-store"
[ "--add", Text.pack tempFile ]
empty
let path = Text.unpack (Turtle.lineToText text)
return (Vector.replicate (fromIntegral numFiles) path)
port :: Int
port = 8000
numFiles :: Natural
numFiles = 10
runNixServe :: IO ()
runNixServe =
Turtle.procs "nix-serve"
[ "--quiet", "--port", Turtle.format d port ]
empty
host :: String
host = "http://localhost:" <> show port
main :: IO ()
main = do
manager <- HTTP.newManager HTTP.defaultManagerSettings
Async.withAsync runNixServe \_ -> do
let fetchNarInfo file = do
let hash = take 32 (drop 11 file)
request <- HTTP.parseRequest (host <> "/" <> hash <> ".narinfo")
response <- HTTP.httpLbs request manager
return (HTTP.responseBody response)
let fetchNar file = do
bytes <- fetchNarInfo file
let relativePath =
( Char8.unpack
. ByteString.drop 5
. (!! 1)
. Char8.lines
) bytes
request <- HTTP.parseRequest (host <> "/" <> relativePath)
response <- HTTP.httpLbs request manager
return (HTTP.responseBody response)
Bench.defaultMain
[ Bench.env (prepareMixed 10000000) \files -> do
Bench.bench ("fetch present NAR info ×" <> show numFiles)
(Bench.nfAppIO (traverse_ fetchNarInfo) files)
, Bench.bench "fetch absent NAR info ×1"
(Bench.nfAppIO fetchNarInfo "/nix/store/00000000000000000000000000000000")
, Bench.env (prepareConstant 0) \files -> do
Bench.bench ("fetch empty NAR ×" <> show numFiles)
(Bench.nfAppIO (traverse_ fetchNar) files)
, Bench.env (prepareConstant 10000000) \files -> do
Bench.bench ("fetch 10 MB NAR ×" <> show numFiles)
(Bench.nfAppIO (traverse_ fetchNar) files)
, Bench.env (prepareMixed 10000000) \files -> do
Bench.bench ("fetch NARs of mixed sizes up to 10 MB ×" <> show numFiles)
(Bench.nfAppIO (traverse_ fetchNar) files)
]