diff options
-rw-r--r-- | bench/Main.hs | 16 | ||||
-rw-r--r-- | network-bittorrent.cabal | 3 | ||||
-rw-r--r-- | src/Network/BitTorrent/PeerWire.hs | 3 | ||||
-rw-r--r-- | src/Network/BitTorrent/PeerWire/Selection.hs | 64 |
4 files changed, 79 insertions, 7 deletions
diff --git a/bench/Main.hs b/bench/Main.hs index 94341c84..e4f756a3 100644 --- a/bench/Main.hs +++ b/bench/Main.hs | |||
@@ -48,19 +48,25 @@ bitfieldInter n = BT.empty n `intersection` BT.empty n | |||
48 | bitfieldUnion :: Int -> Bitfield | 48 | bitfieldUnion :: Int -> Bitfield |
49 | bitfieldUnion n = BT.empty n `union` BT.empty n | 49 | bitfieldUnion n = BT.empty n `union` BT.empty n |
50 | 50 | ||
51 | selectionStrictFirst :: Int -> Maybe Int | ||
52 | selectionStrictFirst n = strictFirst (BT.empty n) (BT.empty n) [] | ||
51 | 53 | ||
52 | main :: IO () | 54 | main :: IO () |
53 | main = do | 55 | main = do |
54 | let datas = replicate 10000 (Request (BlockIx 0 0 0)) | 56 | let datas = replicate 10000 (Request (BlockIx 0 0 0)) |
57 | let m = 1024 * 1024 | ||
55 | 58 | ||
56 | defaultMain | 59 | defaultMain |
57 | [ datas `deepseq` bench "message/encode" $ nf encodeMessages datas | 60 | [ datas `deepseq` bench "message/encode" $ nf encodeMessages datas |
58 | , let binary = encodeMessages datas in | 61 | , let binary = encodeMessages datas in |
59 | binary `deepseq` bench "message/decode" $ nf decodeMessages binary | 62 | binary `deepseq` bench "message/decode" $ nf decodeMessages binary |
60 | 63 | ||
61 | , bench "bitfield/min" $ nf bitfieldMin 10000000 | 64 | -- ~ 256KiB * 10M = 2.5TiB |
62 | , bench "bitfield/max" $ nf bitfieldMax 10000000 | 65 | , bench "bitfield/min" $ nf bitfieldMin (10 * m) |
63 | , bench "bitfield/difference" $ nf bitfieldDiff 10000000 | 66 | , bench "bitfield/max" $ nf bitfieldMax (10 * m) |
64 | , bench "bitfield/intersection" $ nf bitfieldInter 10000000 | 67 | , bench "bitfield/difference" $ nf bitfieldDiff (10 * m) |
65 | , bench "bitfield/union" $ nf bitfieldUnion 10000000 | 68 | , bench "bitfield/intersection" $ nf bitfieldInter (10 * m) |
69 | , bench "bitfield/union" $ nf bitfieldUnion (10 * m) | ||
70 | |||
71 | , bench "selection/strictFirst" $ nf selectionStrictFirst (10 * m) | ||
66 | ] \ No newline at end of file | 72 | ] \ No newline at end of file |
diff --git a/network-bittorrent.cabal b/network-bittorrent.cabal index 02074287..e3f60869 100644 --- a/network-bittorrent.cabal +++ b/network-bittorrent.cabal | |||
@@ -36,8 +36,9 @@ library | |||
36 | , Network.BitTorrent.Tracker.Scrape | 36 | , Network.BitTorrent.Tracker.Scrape |
37 | 37 | ||
38 | , Network.BitTorrent.PeerWire | 38 | , Network.BitTorrent.PeerWire |
39 | , Network.BitTorrent.PeerWire.Bitfield | ||
40 | , Network.BitTorrent.PeerWire.Block | 39 | , Network.BitTorrent.PeerWire.Block |
40 | , Network.BitTorrent.PeerWire.Bitfield | ||
41 | , Network.BitTorrent.PeerWire.Selection | ||
41 | , Network.BitTorrent.PeerWire.Message | 42 | , Network.BitTorrent.PeerWire.Message |
42 | , Network.BitTorrent.PeerWire.Handshake | 43 | , Network.BitTorrent.PeerWire.Handshake |
43 | 44 | ||
diff --git a/src/Network/BitTorrent/PeerWire.hs b/src/Network/BitTorrent/PeerWire.hs index db9287d8..6d8ff156 100644 --- a/src/Network/BitTorrent/PeerWire.hs +++ b/src/Network/BitTorrent/PeerWire.hs | |||
@@ -8,7 +8,8 @@ | |||
8 | {-# LANGUAGE DoAndIfThenElse #-} | 8 | {-# LANGUAGE DoAndIfThenElse #-} |
9 | module Network.BitTorrent.PeerWire (module PW) where | 9 | module Network.BitTorrent.PeerWire (module PW) where |
10 | 10 | ||
11 | import Network.BitTorrent.PeerWire.Bitfield as PW | ||
12 | import Network.BitTorrent.PeerWire.Block as PW | 11 | import Network.BitTorrent.PeerWire.Block as PW |
12 | import Network.BitTorrent.PeerWire.Bitfield as PW | ||
13 | import Network.BitTorrent.PeerWire.Selection as PW | ||
13 | import Network.BitTorrent.PeerWire.Message as PW | 14 | import Network.BitTorrent.PeerWire.Message as PW |
14 | import Network.BitTorrent.PeerWire.Handshake as PW | 15 | import Network.BitTorrent.PeerWire.Handshake as PW |
diff --git a/src/Network/BitTorrent/PeerWire/Selection.hs b/src/Network/BitTorrent/PeerWire/Selection.hs new file mode 100644 index 00000000..04049812 --- /dev/null +++ b/src/Network/BitTorrent/PeerWire/Selection.hs | |||
@@ -0,0 +1,64 @@ | |||
1 | -- TODO tests | ||
2 | -- | | ||
3 | -- Copyright : (c) Sam T. 2013 | ||
4 | -- License : MIT | ||
5 | -- Maintainer : pxqr.sta@gmail.com | ||
6 | -- Stability : experimental | ||
7 | -- Portability : portable | ||
8 | -- | ||
9 | -- This module provides commonly used piece seletion algorithms | ||
10 | -- which used to find out which one next piece to download. | ||
11 | -- Selectors considered to be used in the following order: | ||
12 | -- | ||
13 | -- * Random first or rarest first selection - at the start. | ||
14 | -- | ||
15 | -- * Rarest first selection - performed to avoid situation when | ||
16 | -- rarest piece is unaccessible. | ||
17 | -- | ||
18 | -- * _End game_ seletion - performed after a peer has requested all | ||
19 | -- the subpieces of the content. | ||
20 | -- | ||
21 | -- Note that BitTorrent applies the strict priority policy for | ||
22 | -- _subpiece_ or _blocks_ selection. | ||
23 | -- | ||
24 | module Network.BitTorrent.PeerWire.Selection | ||
25 | ( Selector | ||
26 | , strictFirst, rarestFirst, randomFirst, endGame, autoSelector | ||
27 | ) where | ||
28 | |||
29 | import Network.BitTorrent.PeerWire.Block | ||
30 | import Network.BitTorrent.PeerWire.Message | ||
31 | import Network.BitTorrent.PeerWire.Bitfield | ||
32 | |||
33 | |||
34 | type Selector = Bitfield -- ^ Indices of client "have" pieces. | ||
35 | -> Bitfield -- ^ Indices of peer "have" pieces. | ||
36 | -> [Bitfield] -- ^ Indices of other peers "have" pieces. | ||
37 | -> Maybe PieceIx -- ^ Zero-based index of piece to request | ||
38 | -- to, if any. | ||
39 | |||
40 | -- | Select the first available piece. | ||
41 | strictFirst :: Selector | ||
42 | strictFirst h a _ = findMin (difference a h) | ||
43 | |||
44 | |||
45 | -- | | ||
46 | rarestFirst :: Selector | ||
47 | rarestFirst h a xs = error "rarestFirst" | ||
48 | -- rarest (frequencies (map (intersection want) xs)) | ||
49 | where | ||
50 | want = difference h a | ||
51 | rarest = undefined | ||
52 | |||
53 | -- | In general random first is faster than rarest first strategy but | ||
54 | -- only if all pieces are available. | ||
55 | randomFirst :: IO Selector | ||
56 | randomFirst = do | ||
57 | -- randomIO | ||
58 | error "randomFirst" | ||
59 | |||
60 | endGame :: Selector | ||
61 | endGame = undefined | ||
62 | |||
63 | autoSelector :: Selector | ||
64 | autoSelector = undefined | ||