This repository has been archived by the owner on Feb 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 112
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(sessionrequestsplitter): psuedo-randomization
Move requests around between peers by a randomization algorithm so requests get spread out
- Loading branch information
1 parent
5204f40
commit 5aa87d9
Showing
7 changed files
with
184 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ import ( | |
) | ||
|
||
const ( | ||
newLatencyWeight = 0.5 | ||
newLatencyWeight = 0.3 | ||
) | ||
|
||
type peerData struct { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package sessionrequestsplitter | ||
|
||
import ( | ||
"math/rand" | ||
"sync" | ||
|
||
bssd "github.com/ipfs/go-bitswap/sessiondata" | ||
"github.com/libp2p/go-libp2p-core/peer" | ||
) | ||
|
||
type skipMap struct { | ||
skips [bssd.MaxOptimizedPeers]int | ||
start int | ||
previousIndex int | ||
currentIndex int | ||
} | ||
|
||
var skipMapPool = sync.Pool{ | ||
New: func() interface{} { | ||
return new(skipMap) | ||
}, | ||
} | ||
|
||
func newSkipMap(length int) *skipMap { | ||
sm := skipMapPool.Get().(*skipMap) | ||
sm.Reset(length) | ||
return sm | ||
} | ||
|
||
func returnSkipMap(sm *skipMap) { | ||
skipMapPool.Put(sm) | ||
} | ||
|
||
func (sm *skipMap) Reset(length int) { | ||
for i := 0; i < length; i++ { | ||
sm.skips[i] = i + 1 | ||
} | ||
sm.start = 0 | ||
sm.currentIndex = 0 | ||
sm.previousIndex = -1 | ||
} | ||
|
||
func (sm *skipMap) BeginTraverse() { | ||
sm.currentIndex = sm.start | ||
sm.previousIndex = -1 | ||
} | ||
|
||
func (sm *skipMap) Advance() { | ||
sm.previousIndex = sm.currentIndex | ||
sm.currentIndex = sm.skips[sm.currentIndex] | ||
} | ||
|
||
func (sm *skipMap) RemoveCurrent() { | ||
if sm.currentIndex == sm.start { | ||
sm.start = sm.skips[sm.currentIndex] | ||
} else { | ||
sm.skips[sm.previousIndex] = sm.skips[sm.currentIndex] | ||
} | ||
} | ||
|
||
func (sm *skipMap) CurrentIndex() int { | ||
return sm.currentIndex | ||
} | ||
|
||
func transformOptimization(optimizationRating float64) float64 { | ||
return optimizationRating * optimizationRating | ||
} | ||
|
||
func getOptimizationTotal(optimizedPeers []bssd.OptimizedPeer) float64 { | ||
optimizationTotal := 0.0 | ||
for _, optimizedPeer := range optimizedPeers { | ||
optimizationTotal += transformOptimization(optimizedPeer.OptimizationRating) | ||
} | ||
return optimizationTotal | ||
} | ||
|
||
func peersFromOptimizedPeers(optimizedPeers []bssd.OptimizedPeer) []peer.ID { | ||
optimizationTotal := getOptimizationTotal(optimizedPeers) | ||
sm := newSkipMap(len(optimizedPeers)) | ||
peers := make([]peer.ID, 0, len(optimizedPeers)) | ||
for range optimizedPeers { | ||
randValue := rand.Float64() | ||
randTarget := randValue * optimizationTotal | ||
targetSoFar := 0.0 | ||
sm.BeginTraverse() | ||
for { | ||
currentPeer := optimizedPeers[sm.CurrentIndex()] | ||
currentRating := transformOptimization(currentPeer.OptimizationRating) | ||
targetSoFar += currentRating | ||
if targetSoFar+0.000001 >= randTarget { | ||
peers = append(peers, currentPeer.Peer) | ||
optimizationTotal -= currentRating | ||
sm.RemoveCurrent() | ||
break | ||
} | ||
sm.Advance() | ||
} | ||
} | ||
returnSkipMap(sm) | ||
return peers | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package sessionrequestsplitter | ||
|
||
import ( | ||
"fmt" | ||
"math" | ||
"testing" | ||
|
||
bssd "github.com/ipfs/go-bitswap/sessiondata" | ||
"github.com/ipfs/go-bitswap/testutil" | ||
"github.com/libp2p/go-libp2p-core/peer" | ||
) | ||
|
||
func sampleDistributions(optimizedPeers []bssd.OptimizedPeer, sampleSize int) []map[peer.ID]float64 { | ||
sampleCounts := make([]map[peer.ID]int, len(optimizedPeers)) | ||
for i := range optimizedPeers { | ||
sampleCounts[i] = make(map[peer.ID]int) | ||
} | ||
for i := 0; i < sampleSize; i++ { | ||
samplePeers := peersFromOptimizedPeers(optimizedPeers) | ||
for j, peer := range samplePeers { | ||
sampleCounts[j][peer] = sampleCounts[j][peer] + 1 | ||
} | ||
} | ||
sampleMean := make([]map[peer.ID]float64, len(optimizedPeers)) | ||
for i, sampleCount := range sampleCounts { | ||
sampleMean[i] = make(map[peer.ID]float64) | ||
for p, count := range sampleCount { | ||
sampleMean[i][p] = float64(count) / float64(sampleSize) | ||
} | ||
} | ||
return sampleMean | ||
} | ||
|
||
func TestDistributionsFromOptimizations(t *testing.T) { | ||
peers := testutil.GeneratePeers(3) | ||
optimizedPeers := make([]bssd.OptimizedPeer, 0, len(peers)) | ||
for i, peer := range peers { | ||
optimizedPeers = append(optimizedPeers, bssd.OptimizedPeer{peer, 1.0 - (float64(i) * 0.4)}) | ||
} | ||
distributions := sampleDistributions(optimizedPeers, 1000) | ||
expectedDistributions := []map[peer.ID]float64{ | ||
map[peer.ID]float64{ | ||
peers[0]: 1.0 / 1.4, | ||
peers[1]: 0.36 / 1.4, | ||
peers[2]: 0.04 / 1.4, | ||
}, | ||
map[peer.ID]float64{ | ||
peers[0]: (0.36/1.4)*(1.0/1.04) + (0.04/1.4)*(1.0/1.36), | ||
peers[1]: (1.0/1.4)*(0.36/0.4) + (0.04/1.4)*(0.36/1.36), | ||
peers[2]: (1.0/1.4)*(0.04/0.4) + (0.36/1.4)*(0.04/1.04), | ||
}, | ||
map[peer.ID]float64{ | ||
peers[0]: (0.04/1.4)*(0.36/1.36) + (0.36/1.4)*(0.04/1.04), | ||
peers[1]: (0.04/1.4)*(1.0/1.36) + (1.0/1.4)*(0.04/0.4), | ||
peers[2]: (0.36/1.4)*(1.0/1.04) + (1.0/1.4)*(0.36/0.4), | ||
}, | ||
} | ||
for i, distribution := range distributions { | ||
expectedDistribution := expectedDistributions[i] | ||
for p, value := range distribution { | ||
expectedValue := expectedDistribution[p] | ||
fmt.Printf("Value: %f, Expected: %f\n", value, expectedValue) | ||
if math.Abs(value-expectedValue) >= 0.02 { | ||
t.Fatal("Distribution did not match expected distribution") | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters