Skip to content

Commit 5911b5c

Browse files
authored
Merge pull request #7 from itzmeanjan/make-kodr-zero-dependency
Make `kodr` zero-dependency
2 parents 953d539 + 6f535e7 commit 5911b5c

37 files changed

+813
-654
lines changed

.github/workflows/go.yml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Go
1+
name: Test kodr RLNC
22

33
on:
44
push:
@@ -11,12 +11,18 @@ jobs:
1111
build:
1212
runs-on: ubuntu-latest
1313
steps:
14-
- uses: actions/checkout@v2
14+
- uses: actions/checkout@v4
1515

1616
- name: Set up Go
17-
uses: actions/setup-go@v2
17+
uses: actions/setup-go@v5
1818
with:
19-
go-version: 1.16
19+
go-version: 1.24
2020

21-
- name: Test
22-
run: go test -v -cover ./...
21+
- name: Run all tests
22+
run: go test -v -cover -count=10 ./...
23+
24+
- name: Run Full RLNC example
25+
run: pushd examples/full; go run main.go; popd
26+
27+
- name: Run Systematic RLNC example
28+
run: pushd examples/systematic; go run main.go; popd

README.md

Lines changed: 195 additions & 203 deletions
Large diffs are not rendered by default.
Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,11 @@ import (
55
"testing"
66
"time"
77

8-
"github.com/itzmeanjan/kodr"
98
"github.com/itzmeanjan/kodr/full"
9+
"github.com/itzmeanjan/kodr/kodr_internals"
1010
)
1111

1212
func BenchmarkFullRLNCDecoder(t *testing.B) {
13-
t.Run("256K", func(b *testing.B) {
14-
b.Run("16 Pieces", func(b *testing.B) { decode(b, 1<<4, 1<<18) })
15-
b.Run("32 Pieces", func(b *testing.B) { decode(b, 1<<5, 1<<18) })
16-
b.Run("64 Pieces", func(b *testing.B) { decode(b, 1<<6, 1<<18) })
17-
b.Run("128 Pieces", func(b *testing.B) { decode(b, 1<<7, 1<<18) })
18-
b.Run("256 Pieces", func(b *testing.B) { decode(b, 1<<8, 1<<18) })
19-
})
20-
21-
t.Run("512K", func(b *testing.B) {
22-
b.Run("16 Pieces", func(b *testing.B) { decode(b, 1<<4, 1<<19) })
23-
b.Run("32 Pieces", func(b *testing.B) { decode(b, 1<<5, 1<<19) })
24-
b.Run("64 Pieces", func(b *testing.B) { decode(b, 1<<6, 1<<19) })
25-
b.Run("128 Pieces", func(b *testing.B) { decode(b, 1<<7, 1<<19) })
26-
b.Run("256 Pieces", func(b *testing.B) { decode(b, 1<<8, 1<<19) })
27-
})
28-
2913
t.Run("1M", func(b *testing.B) {
3014
b.Run("16 Pieces", func(b *testing.B) { decode(b, 1<<4, 1<<20) })
3115
b.Run("32 Pieces", func(b *testing.B) { decode(b, 1<<5, 1<<20) })
@@ -41,44 +25,59 @@ func BenchmarkFullRLNCDecoder(t *testing.B) {
4125
b.Run("128 Pieces", func(b *testing.B) { decode(b, 1<<7, 1<<21) })
4226
b.Run("256 Pieces", func(b *testing.B) { decode(b, 1<<8, 1<<21) })
4327
})
28+
29+
t.Run("16M", func(b *testing.B) {
30+
b.Run("16 Pieces", func(b *testing.B) { decode(b, 1<<4, 1<<24) })
31+
b.Run("32 Pieces", func(b *testing.B) { decode(b, 1<<5, 1<<24) })
32+
b.Run("64 Pieces", func(b *testing.B) { decode(b, 1<<6, 1<<24) })
33+
b.Run("128 Pieces", func(b *testing.B) { decode(b, 1<<7, 1<<24) })
34+
b.Run("256 Pieces", func(b *testing.B) { decode(b, 1<<8, 1<<24) })
35+
})
36+
37+
t.Run("32M", func(b *testing.B) {
38+
b.Run("16 Pieces", func(b *testing.B) { decode(b, 1<<4, 1<<25) })
39+
b.Run("32 Pieces", func(b *testing.B) { decode(b, 1<<5, 1<<25) })
40+
b.Run("64 Pieces", func(b *testing.B) { decode(b, 1<<6, 1<<25) })
41+
b.Run("128 Pieces", func(b *testing.B) { decode(b, 1<<7, 1<<25) })
42+
b.Run("256 Pieces", func(b *testing.B) { decode(b, 1<<8, 1<<25) })
43+
})
4444
}
4545

4646
func decode(t *testing.B, pieceCount uint, total uint) {
47-
rand.Seed(time.Now().UnixNano())
47+
data := generateRandomData(total)
4848

49-
data := generateData(total)
5049
enc, err := full.NewFullRLNCEncoderWithPieceCount(data, pieceCount)
5150
if err != nil {
5251
t.Fatalf("Error: %s\n", err.Error())
5352
}
5453

55-
pieces := make([]*kodr.CodedPiece, 0, 2*pieceCount)
56-
for i := 0; i < int(2*pieceCount); i++ {
54+
pieces := make([]*kodr_internals.CodedPiece, 0, 2*pieceCount)
55+
for range 2 * pieceCount {
5756
pieces = append(pieces, enc.CodedPiece())
5857
}
5958

6059
t.ResetTimer()
6160

6261
totalDuration := 0 * time.Second
63-
for i := 0; i < t.N; i++ {
64-
totalDuration += decode_(t, pieceCount, pieces)
62+
for t.Loop() {
63+
totalDuration += decode_internal(t, pieceCount, pieces)
6564
}
6665

6766
t.ReportMetric(0, "ns/op")
6867
t.ReportMetric(float64(totalDuration.Seconds())/float64(t.N), "second/decode")
6968
}
7069

71-
func decode_(t *testing.B, pieceCount uint, pieces []*kodr.CodedPiece) time.Duration {
70+
func decode_internal(t *testing.B, pieceCount uint, pieces []*kodr_internals.CodedPiece) time.Duration {
7271
dec := full.NewFullRLNCDecoder(pieceCount)
7372

74-
// randomly shuffle piece ordering
75-
rand.Shuffle(int(2*pieceCount), func(i, j int) {
73+
// Random shuffle piece ordering
74+
rand.Shuffle(len(pieces), func(i, j int) {
7675
pieces[i], pieces[j] = pieces[j], pieces[i]
7776
})
7877

7978
totalDuration := 0 * time.Second
80-
for j := 0; j < int(2*pieceCount); j++ {
81-
if j+1 >= int(pieceCount) && dec.IsDecoded() {
79+
for j := range 2 * pieceCount {
80+
if j+1 >= pieceCount && dec.IsDecoded() {
8281
break
8382
}
8483

@@ -88,7 +87,7 @@ func decode_(t *testing.B, pieceCount uint, pieces []*kodr.CodedPiece) time.Dura
8887
}
8988

9089
if !dec.IsDecoded() {
91-
t.Fatal("expected pieces to be decoded")
90+
t.Fatal("expected pieces to be already decoded")
9291
}
9392

9493
return totalDuration
Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
package full_test
22

33
import (
4-
"math/rand"
4+
"crypto/rand"
55
"testing"
6-
"time"
76

87
"github.com/itzmeanjan/kodr/full"
98
)
@@ -34,32 +33,27 @@ func BenchmarkFullRLNCEncoder(t *testing.B) {
3433
})
3534
}
3635

37-
// generate random data of N-bytes
38-
func generateData(n uint) []byte {
36+
// Generate random data of N-bytes
37+
func generateRandomData(n uint) []byte {
3938
data := make([]byte, n)
40-
// can safely ignore error
4139
rand.Read(data)
40+
4241
return data
4342
}
4443

4544
func encode(t *testing.B, pieceCount uint, total uint) {
46-
// non-reproducible random number sequence
47-
rand.Seed(time.Now().UnixNano())
45+
data := generateRandomData(total)
4846

49-
data := generateData(total)
5047
enc, err := full.NewFullRLNCEncoderWithPieceCount(data, pieceCount)
5148
if err != nil {
5249
t.Fatalf("Error: %s\n", err.Error())
5350
}
5451

5552
t.ReportAllocs()
56-
// because pieceSize = total / pieceCount
57-
// so each coded piece = pieceCount + pieceSize bytes
58-
t.SetBytes(int64(total) + int64(pieceCount+total/pieceCount))
53+
t.SetBytes(int64(total+enc.Padding()) + int64(enc.CodedPieceLen()))
5954
t.ResetTimer()
6055

61-
// keep generating encoded pieces on-the-fly
62-
for i := 0; i < t.N; i++ {
56+
for t.Loop() {
6357
enc.CodedPiece()
6458
}
6559
}
Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package full_test
22

33
import (
4-
"math/rand"
54
"testing"
6-
"time"
75

8-
"github.com/itzmeanjan/kodr"
96
"github.com/itzmeanjan/kodr/full"
7+
"github.com/itzmeanjan/kodr/kodr_internals"
108
)
119

1210
func BenchmarkFullRLNCRecoder(t *testing.B) {
@@ -36,33 +34,26 @@ func BenchmarkFullRLNCRecoder(t *testing.B) {
3634
}
3735

3836
func recode(t *testing.B, pieceCount uint, total uint) {
39-
// non-reproducible sequence
40-
rand.Seed(time.Now().UnixNano())
41-
42-
// -- encode
43-
data := generateData(total)
37+
// Encode
38+
data := generateRandomData(total)
4439
enc, err := full.NewFullRLNCEncoderWithPieceCount(data, pieceCount)
4540
if err != nil {
4641
t.Fatalf("Error: %s\n", err.Error())
4742
}
4843

49-
pieces := make([]*kodr.CodedPiece, 0, pieceCount)
50-
for i := 0; i < int(pieceCount); i++ {
44+
pieces := make([]*kodr_internals.CodedPiece, 0, pieceCount)
45+
for range pieceCount {
5146
pieces = append(pieces, enc.CodedPiece())
5247
}
53-
// -- encoding ends
5448

55-
// -- recode
49+
// Recode
5650
rec := full.NewFullRLNCRecoder(pieces)
5751

5852
t.ReportAllocs()
5953
t.SetBytes(int64((pieceCount+total/pieceCount)*pieceCount) + int64(pieceCount+total/pieceCount))
6054
t.ResetTimer()
6155

62-
for i := 0; i < t.N; i++ {
63-
if _, err := rec.CodedPiece(); err != nil {
64-
t.Fatalf("Error: %s\n", err.Error())
65-
}
56+
for t.Loop() {
57+
rec.CodedPiece()
6658
}
67-
// -- recoding ends
6859
}
Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,17 @@ import (
55
"testing"
66
"time"
77

8-
"github.com/itzmeanjan/kodr"
9-
"github.com/itzmeanjan/kodr/full"
8+
"github.com/itzmeanjan/kodr/kodr_internals"
109
"github.com/itzmeanjan/kodr/systematic"
1110
)
1211

13-
func BenchmarkFullRLNCDecoder(t *testing.B) {
12+
func BenchmarkSystematicRLNCDecoder(t *testing.B) {
1413
t.Run("1M", func(b *testing.B) {
1514
b.Run("16Pieces", func(b *testing.B) { decode(b, 1<<4, 1<<20) })
1615
b.Run("32Pieces", func(b *testing.B) { decode(b, 1<<5, 1<<20) })
1716
b.Run("64Pieces", func(b *testing.B) { decode(b, 1<<6, 1<<20) })
1817
b.Run("128Pieces", func(b *testing.B) { decode(b, 1<<7, 1<<20) })
1918
b.Run("256Pieces", func(b *testing.B) { decode(b, 1<<8, 1<<20) })
20-
b.Run("512Pieces", func(b *testing.B) { decode(b, 1<<9, 1<<20) })
2119
})
2220

2321
t.Run("2M", func(b *testing.B) {
@@ -26,46 +24,60 @@ func BenchmarkFullRLNCDecoder(t *testing.B) {
2624
b.Run("64Pieces", func(b *testing.B) { decode(b, 1<<6, 1<<21) })
2725
b.Run("128Pieces", func(b *testing.B) { decode(b, 1<<7, 1<<21) })
2826
b.Run("256Pieces", func(b *testing.B) { decode(b, 1<<8, 1<<21) })
29-
b.Run("512Pieces", func(b *testing.B) { decode(b, 1<<9, 1<<21) })
27+
})
28+
29+
t.Run("16M", func(b *testing.B) {
30+
b.Run("16 Pieces", func(b *testing.B) { decode(b, 1<<4, 1<<24) })
31+
b.Run("32 Pieces", func(b *testing.B) { decode(b, 1<<5, 1<<24) })
32+
b.Run("64 Pieces", func(b *testing.B) { decode(b, 1<<6, 1<<24) })
33+
b.Run("128 Pieces", func(b *testing.B) { decode(b, 1<<7, 1<<24) })
34+
b.Run("256 Pieces", func(b *testing.B) { decode(b, 1<<8, 1<<24) })
35+
})
36+
37+
t.Run("32M", func(b *testing.B) {
38+
b.Run("16 Pieces", func(b *testing.B) { decode(b, 1<<4, 1<<25) })
39+
b.Run("32 Pieces", func(b *testing.B) { decode(b, 1<<5, 1<<25) })
40+
b.Run("64 Pieces", func(b *testing.B) { decode(b, 1<<6, 1<<25) })
41+
b.Run("128 Pieces", func(b *testing.B) { decode(b, 1<<7, 1<<25) })
42+
b.Run("256 Pieces", func(b *testing.B) { decode(b, 1<<8, 1<<25) })
3043
})
3144
}
3245

3346
func decode(t *testing.B, pieceCount uint, total uint) {
34-
rand.Seed(time.Now().UnixNano())
47+
data := generateRandomData(total)
3548

36-
data := generateData(total)
3749
enc, err := systematic.NewSystematicRLNCEncoderWithPieceCount(data, pieceCount)
3850
if err != nil {
3951
t.Fatalf("Error: %s\n", err.Error())
4052
}
4153

42-
pieces := make([]*kodr.CodedPiece, 0, 2*pieceCount)
43-
for i := 0; i < int(2*pieceCount); i++ {
54+
pieces := make([]*kodr_internals.CodedPiece, 0, 2*pieceCount)
55+
for range 2 * pieceCount {
4456
pieces = append(pieces, enc.CodedPiece())
4557
}
4658

4759
t.ResetTimer()
4860

4961
totalDuration := 0 * time.Second
50-
for i := 0; i < t.N; i++ {
51-
totalDuration += decode_(t, pieceCount, pieces)
62+
for t.Loop() {
63+
totalDuration += decode_internal(t, pieceCount, pieces)
5264
}
5365

5466
t.ReportMetric(0, "ns/op")
55-
t.ReportMetric(float64(totalDuration.Seconds())/float64(t.N), "second/decode")
67+
t.ReportMetric(float64(totalDuration.Seconds())/float64(t.N), "seconds/decode")
5668
}
5769

58-
func decode_(t *testing.B, pieceCount uint, pieces []*kodr.CodedPiece) time.Duration {
59-
dec := full.NewFullRLNCDecoder(pieceCount)
70+
func decode_internal(t *testing.B, pieceCount uint, pieces []*kodr_internals.CodedPiece) time.Duration {
71+
dec := systematic.NewSystematicRLNCDecoder(pieceCount)
6072

61-
// randomly shuffle piece ordering
62-
rand.Shuffle(int(2*pieceCount), func(i, j int) {
73+
// Random shuffle piece ordering
74+
rand.Shuffle(len(pieces), func(i, j int) {
6375
pieces[i], pieces[j] = pieces[j], pieces[i]
6476
})
6577

6678
totalDuration := 0 * time.Second
67-
for j := 0; j < int(2*pieceCount); j++ {
68-
if j+1 >= int(pieceCount) && dec.IsDecoded() {
79+
for j := range 2 * pieceCount {
80+
if j+1 >= pieceCount && dec.IsDecoded() {
6981
break
7082
}
7183

@@ -75,7 +87,7 @@ func decode_(t *testing.B, pieceCount uint, pieces []*kodr.CodedPiece) time.Dura
7587
}
7688

7789
if !dec.IsDecoded() {
78-
t.Fatal("expected pieces to be decoded")
90+
t.Fatal("expected pieces to be already decoded")
7991
}
8092

8193
return totalDuration

0 commit comments

Comments
 (0)