summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bench/Main.hs16
-rw-r--r--network-bittorrent.cabal3
-rw-r--r--src/Network/BitTorrent/PeerWire.hs3
-rw-r--r--src/Network/BitTorrent/PeerWire/Selection.hs64
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
48bitfieldUnion :: Int -> Bitfield 48bitfieldUnion :: Int -> Bitfield
49bitfieldUnion n = BT.empty n `union` BT.empty n 49bitfieldUnion n = BT.empty n `union` BT.empty n
50 50
51selectionStrictFirst :: Int -> Maybe Int
52selectionStrictFirst n = strictFirst (BT.empty n) (BT.empty n) []
51 53
52main :: IO () 54main :: IO ()
53main = do 55main = 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 #-}
9module Network.BitTorrent.PeerWire (module PW) where 9module Network.BitTorrent.PeerWire (module PW) where
10 10
11import Network.BitTorrent.PeerWire.Bitfield as PW
12import Network.BitTorrent.PeerWire.Block as PW 11import Network.BitTorrent.PeerWire.Block as PW
12import Network.BitTorrent.PeerWire.Bitfield as PW
13import Network.BitTorrent.PeerWire.Selection as PW
13import Network.BitTorrent.PeerWire.Message as PW 14import Network.BitTorrent.PeerWire.Message as PW
14import Network.BitTorrent.PeerWire.Handshake as PW 15import 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--
24module Network.BitTorrent.PeerWire.Selection
25 ( Selector
26 , strictFirst, rarestFirst, randomFirst, endGame, autoSelector
27 ) where
28
29import Network.BitTorrent.PeerWire.Block
30import Network.BitTorrent.PeerWire.Message
31import Network.BitTorrent.PeerWire.Bitfield
32
33
34type 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.
41strictFirst :: Selector
42strictFirst h a _ = findMin (difference a h)
43
44
45-- |
46rarestFirst :: Selector
47rarestFirst 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.
55randomFirst :: IO Selector
56randomFirst = do
57-- randomIO
58 error "randomFirst"
59
60endGame :: Selector
61endGame = undefined
62
63autoSelector :: Selector
64autoSelector = undefined