type_balancer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +96 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/Dockerfile +38 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +101 -0
- data/LICENSE.txt +21 -0
- data/README.md +86 -0
- data/Rakefile +101 -0
- data/benchmark/README.md +90 -0
- data/benchmark/end_to_end_benchmark.rb +65 -0
- data/benchmark/quick_benchmark.rb +70 -0
- data/benchmark_output.log +1581 -0
- data/benchmark_results/ruby3.2.8.txt +55 -0
- data/benchmark_results/ruby3.2.8_yjit.txt +55 -0
- data/benchmark_results/ruby3.3.7.txt +55 -0
- data/benchmark_results/ruby3.3.7_yjit.txt +55 -0
- data/benchmark_results/ruby3.4.2.txt +55 -0
- data/benchmark_results/ruby3.4.2_yjit.txt +55 -0
- data/docs/benchmarks/README.md +180 -0
- data/examples/quality.rb +178 -0
- data/lib/type_balancer/alternating_filler.rb +46 -0
- data/lib/type_balancer/balancer.rb +126 -0
- data/lib/type_balancer/calculator.rb +218 -0
- data/lib/type_balancer/distribution_calculator.rb +21 -0
- data/lib/type_balancer/distributor.rb +61 -0
- data/lib/type_balancer/ordered_collection_manager.rb +95 -0
- data/lib/type_balancer/sequential_filler.rb +32 -0
- data/lib/type_balancer/version.rb +5 -0
- data/lib/type_balancer.rb +44 -0
- data/sig/type_balancer.rbs +85 -0
- data/type_balancer.gemspec +33 -0
- metadata +77 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
+ cd /app
|
2
|
+
+ bundle exec ruby -I lib benchmark/end_to_end_benchmark.rb
|
3
|
+
Ruby version: 3.2.8
|
4
|
+
RUBY_PLATFORM: aarch64-linux
|
5
|
+
YJIT enabled: false
|
6
|
+
|
7
|
+
Running benchmarks...
|
8
|
+
|
9
|
+
Benchmarking Tiny Dataset (10 items)
|
10
|
+
ruby 3.2.8 (2025-03-26 revision 13f495dc2c) [aarch64-linux]
|
11
|
+
Warming up --------------------------------------
|
12
|
+
Ruby Implementation 5.815k i/100ms
|
13
|
+
Calculating -------------------------------------
|
14
|
+
Ruby Implementation 70.626k (± 8.1%) i/s (14.16 μs/i) - 145.375k in 2.072857s
|
15
|
+
|
16
|
+
Distribution Stats:
|
17
|
+
Video: 4 (40.0%)
|
18
|
+
Image: 3 (30.0%)
|
19
|
+
Article: 3 (30.0%)
|
20
|
+
|
21
|
+
Benchmarking Small Dataset (100 items)
|
22
|
+
ruby 3.2.8 (2025-03-26 revision 13f495dc2c) [aarch64-linux]
|
23
|
+
Warming up --------------------------------------
|
24
|
+
Ruby Implementation 179.000 i/100ms
|
25
|
+
Calculating -------------------------------------
|
26
|
+
Ruby Implementation 1.904k (± 4.8%) i/s (525.33 μs/i) - 3.938k in 2.073542s
|
27
|
+
|
28
|
+
Distribution Stats:
|
29
|
+
Video: 34 (34.0%)
|
30
|
+
Image: 33 (33.0%)
|
31
|
+
Article: 33 (33.0%)
|
32
|
+
|
33
|
+
Benchmarking Medium Dataset (1000 items)
|
34
|
+
ruby 3.2.8 (2025-03-26 revision 13f495dc2c) [aarch64-linux]
|
35
|
+
Warming up --------------------------------------
|
36
|
+
Ruby Implementation 1.000 i/100ms
|
37
|
+
Calculating -------------------------------------
|
38
|
+
Ruby Implementation 20.785 (± 9.6%) i/s (48.11 ms/i) - 62.000 in 3.018630s
|
39
|
+
|
40
|
+
Distribution Stats:
|
41
|
+
Video: 334 (33.4%)
|
42
|
+
Image: 333 (33.3%)
|
43
|
+
Article: 333 (33.3%)
|
44
|
+
|
45
|
+
Benchmarking Large Dataset (10000 items)
|
46
|
+
ruby 3.2.8 (2025-03-26 revision 13f495dc2c) [aarch64-linux]
|
47
|
+
Warming up --------------------------------------
|
48
|
+
Ruby Implementation 1.000 i/100ms
|
49
|
+
Calculating -------------------------------------
|
50
|
+
Ruby Implementation 0.229 (± 0.0%) i/s (4.37 s/i) - 1.000 in 4.371704s
|
51
|
+
|
52
|
+
Distribution Stats:
|
53
|
+
Video: 3334 (33.34%)
|
54
|
+
Image: 3333 (33.33%)
|
55
|
+
Article: 3333 (33.33%)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
+ cd /app
|
2
|
+
+ bundle exec ruby -I lib benchmark/end_to_end_benchmark.rb
|
3
|
+
Ruby version: 3.2.8
|
4
|
+
RUBY_PLATFORM: aarch64-linux
|
5
|
+
YJIT enabled: false
|
6
|
+
|
7
|
+
Running benchmarks...
|
8
|
+
|
9
|
+
Benchmarking Tiny Dataset (10 items)
|
10
|
+
ruby 3.2.8 (2025-03-26 revision 13f495dc2c) [aarch64-linux]
|
11
|
+
Warming up --------------------------------------
|
12
|
+
Ruby Implementation 8.136k i/100ms
|
13
|
+
Calculating -------------------------------------
|
14
|
+
Ruby Implementation 74.212k (± 6.1%) i/s (13.47 μs/i) - 154.584k in 2.090755s
|
15
|
+
|
16
|
+
Distribution Stats:
|
17
|
+
Video: 4 (40.0%)
|
18
|
+
Image: 3 (30.0%)
|
19
|
+
Article: 3 (30.0%)
|
20
|
+
|
21
|
+
Benchmarking Small Dataset (100 items)
|
22
|
+
ruby 3.2.8 (2025-03-26 revision 13f495dc2c) [aarch64-linux]
|
23
|
+
Warming up --------------------------------------
|
24
|
+
Ruby Implementation 181.000 i/100ms
|
25
|
+
Calculating -------------------------------------
|
26
|
+
Ruby Implementation 1.934k (± 4.9%) i/s (517.12 μs/i) - 3.982k in 2.064193s
|
27
|
+
|
28
|
+
Distribution Stats:
|
29
|
+
Video: 34 (34.0%)
|
30
|
+
Image: 33 (33.0%)
|
31
|
+
Article: 33 (33.0%)
|
32
|
+
|
33
|
+
Benchmarking Medium Dataset (1000 items)
|
34
|
+
ruby 3.2.8 (2025-03-26 revision 13f495dc2c) [aarch64-linux]
|
35
|
+
Warming up --------------------------------------
|
36
|
+
Ruby Implementation 1.000 i/100ms
|
37
|
+
Calculating -------------------------------------
|
38
|
+
Ruby Implementation 18.611 (±16.1%) i/s (53.73 ms/i) - 54.000 in 3.010201s
|
39
|
+
|
40
|
+
Distribution Stats:
|
41
|
+
Video: 334 (33.4%)
|
42
|
+
Image: 333 (33.3%)
|
43
|
+
Article: 333 (33.3%)
|
44
|
+
|
45
|
+
Benchmarking Large Dataset (10000 items)
|
46
|
+
ruby 3.2.8 (2025-03-26 revision 13f495dc2c) [aarch64-linux]
|
47
|
+
Warming up --------------------------------------
|
48
|
+
Ruby Implementation 1.000 i/100ms
|
49
|
+
Calculating -------------------------------------
|
50
|
+
Ruby Implementation 0.227 (± 0.0%) i/s (4.41 s/i) - 1.000 in 4.405356s
|
51
|
+
|
52
|
+
Distribution Stats:
|
53
|
+
Video: 3334 (33.34%)
|
54
|
+
Image: 3333 (33.33%)
|
55
|
+
Article: 3333 (33.33%)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
+ cd /app
|
2
|
+
+ bundle exec ruby -I lib benchmark/end_to_end_benchmark.rb
|
3
|
+
Ruby version: 3.3.7
|
4
|
+
RUBY_PLATFORM: aarch64-linux
|
5
|
+
YJIT enabled: false
|
6
|
+
|
7
|
+
Running benchmarks...
|
8
|
+
|
9
|
+
Benchmarking Tiny Dataset (10 items)
|
10
|
+
ruby 3.3.7 (2025-01-15 revision be31f993d7) [aarch64-linux]
|
11
|
+
Warming up --------------------------------------
|
12
|
+
Ruby Implementation 6.917k i/100ms
|
13
|
+
Calculating -------------------------------------
|
14
|
+
Ruby Implementation 66.848k (± 4.7%) i/s (14.96 μs/i) - 138.340k in 2.074218s
|
15
|
+
|
16
|
+
Distribution Stats:
|
17
|
+
Video: 4 (40.0%)
|
18
|
+
Image: 3 (30.0%)
|
19
|
+
Article: 3 (30.0%)
|
20
|
+
|
21
|
+
Benchmarking Small Dataset (100 items)
|
22
|
+
ruby 3.3.7 (2025-01-15 revision be31f993d7) [aarch64-linux]
|
23
|
+
Warming up --------------------------------------
|
24
|
+
Ruby Implementation 174.000 i/100ms
|
25
|
+
Calculating -------------------------------------
|
26
|
+
Ruby Implementation 1.897k (± 4.5%) i/s (527.03 μs/i) - 3.828k in 2.021687s
|
27
|
+
|
28
|
+
Distribution Stats:
|
29
|
+
Video: 34 (34.0%)
|
30
|
+
Image: 33 (33.0%)
|
31
|
+
Article: 33 (33.0%)
|
32
|
+
|
33
|
+
Benchmarking Medium Dataset (1000 items)
|
34
|
+
ruby 3.3.7 (2025-01-15 revision be31f993d7) [aarch64-linux]
|
35
|
+
Warming up --------------------------------------
|
36
|
+
Ruby Implementation 2.000 i/100ms
|
37
|
+
Calculating -------------------------------------
|
38
|
+
Ruby Implementation 19.511 (±10.3%) i/s (51.25 ms/i) - 58.000 in 3.018480s
|
39
|
+
|
40
|
+
Distribution Stats:
|
41
|
+
Video: 334 (33.4%)
|
42
|
+
Image: 333 (33.3%)
|
43
|
+
Article: 333 (33.3%)
|
44
|
+
|
45
|
+
Benchmarking Large Dataset (10000 items)
|
46
|
+
ruby 3.3.7 (2025-01-15 revision be31f993d7) [aarch64-linux]
|
47
|
+
Warming up --------------------------------------
|
48
|
+
Ruby Implementation 1.000 i/100ms
|
49
|
+
Calculating -------------------------------------
|
50
|
+
Ruby Implementation 0.224 (± 0.0%) i/s (4.46 s/i) - 1.000 in 4.464788s
|
51
|
+
|
52
|
+
Distribution Stats:
|
53
|
+
Video: 3334 (33.34%)
|
54
|
+
Image: 3333 (33.33%)
|
55
|
+
Article: 3333 (33.33%)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
+ cd /app
|
2
|
+
+ bundle exec ruby -I lib benchmark/end_to_end_benchmark.rb
|
3
|
+
Ruby version: 3.3.7
|
4
|
+
RUBY_PLATFORM: aarch64-linux
|
5
|
+
YJIT enabled: false
|
6
|
+
|
7
|
+
Running benchmarks...
|
8
|
+
|
9
|
+
Benchmarking Tiny Dataset (10 items)
|
10
|
+
ruby 3.3.7 (2025-01-15 revision be31f993d7) [aarch64-linux]
|
11
|
+
Warming up --------------------------------------
|
12
|
+
Ruby Implementation 6.343k i/100ms
|
13
|
+
Calculating -------------------------------------
|
14
|
+
Ruby Implementation 66.941k (± 6.0%) i/s (14.94 μs/i) - 139.546k in 2.092006s
|
15
|
+
|
16
|
+
Distribution Stats:
|
17
|
+
Video: 4 (40.0%)
|
18
|
+
Image: 3 (30.0%)
|
19
|
+
Article: 3 (30.0%)
|
20
|
+
|
21
|
+
Benchmarking Small Dataset (100 items)
|
22
|
+
ruby 3.3.7 (2025-01-15 revision be31f993d7) [aarch64-linux]
|
23
|
+
Warming up --------------------------------------
|
24
|
+
Ruby Implementation 175.000 i/100ms
|
25
|
+
Calculating -------------------------------------
|
26
|
+
Ruby Implementation 1.888k (± 5.1%) i/s (529.71 μs/i) - 3.850k in 2.044860s
|
27
|
+
|
28
|
+
Distribution Stats:
|
29
|
+
Video: 34 (34.0%)
|
30
|
+
Image: 33 (33.0%)
|
31
|
+
Article: 33 (33.0%)
|
32
|
+
|
33
|
+
Benchmarking Medium Dataset (1000 items)
|
34
|
+
ruby 3.3.7 (2025-01-15 revision be31f993d7) [aarch64-linux]
|
35
|
+
Warming up --------------------------------------
|
36
|
+
Ruby Implementation 1.000 i/100ms
|
37
|
+
Calculating -------------------------------------
|
38
|
+
Ruby Implementation 19.923 (±15.1%) i/s (50.19 ms/i) - 59.000 in 3.031767s
|
39
|
+
|
40
|
+
Distribution Stats:
|
41
|
+
Video: 334 (33.4%)
|
42
|
+
Image: 333 (33.3%)
|
43
|
+
Article: 333 (33.3%)
|
44
|
+
|
45
|
+
Benchmarking Large Dataset (10000 items)
|
46
|
+
ruby 3.3.7 (2025-01-15 revision be31f993d7) [aarch64-linux]
|
47
|
+
Warming up --------------------------------------
|
48
|
+
Ruby Implementation 1.000 i/100ms
|
49
|
+
Calculating -------------------------------------
|
50
|
+
Ruby Implementation 0.224 (± 0.0%) i/s (4.47 s/i) - 1.000 in 4.467441s
|
51
|
+
|
52
|
+
Distribution Stats:
|
53
|
+
Video: 3334 (33.34%)
|
54
|
+
Image: 3333 (33.33%)
|
55
|
+
Article: 3333 (33.33%)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
+ cd /app
|
2
|
+
+ bundle exec ruby -I lib benchmark/end_to_end_benchmark.rb
|
3
|
+
Ruby version: 3.4.2
|
4
|
+
RUBY_PLATFORM: aarch64-linux
|
5
|
+
YJIT enabled: false
|
6
|
+
|
7
|
+
Running benchmarks...
|
8
|
+
|
9
|
+
Benchmarking Tiny Dataset (10 items)
|
10
|
+
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
|
11
|
+
Warming up --------------------------------------
|
12
|
+
Ruby Implementation 6.476k i/100ms
|
13
|
+
Calculating -------------------------------------
|
14
|
+
Ruby Implementation 66.552k (± 5.7%) i/s (15.03 μs/i) - 135.996k in 2.050038s
|
15
|
+
|
16
|
+
Distribution Stats:
|
17
|
+
Video: 4 (40.0%)
|
18
|
+
Image: 3 (30.0%)
|
19
|
+
Article: 3 (30.0%)
|
20
|
+
|
21
|
+
Benchmarking Small Dataset (100 items)
|
22
|
+
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
|
23
|
+
Warming up --------------------------------------
|
24
|
+
Ruby Implementation 168.000 i/100ms
|
25
|
+
Calculating -------------------------------------
|
26
|
+
Ruby Implementation 1.790k (± 5.2%) i/s (558.74 μs/i) - 3.696k in 2.070989s
|
27
|
+
|
28
|
+
Distribution Stats:
|
29
|
+
Video: 34 (34.0%)
|
30
|
+
Image: 33 (33.0%)
|
31
|
+
Article: 33 (33.0%)
|
32
|
+
|
33
|
+
Benchmarking Medium Dataset (1000 items)
|
34
|
+
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
|
35
|
+
Warming up --------------------------------------
|
36
|
+
Ruby Implementation 1.000 i/100ms
|
37
|
+
Calculating -------------------------------------
|
38
|
+
Ruby Implementation 19.043 (±10.5%) i/s (52.51 ms/i) - 57.000 in 3.042588s
|
39
|
+
|
40
|
+
Distribution Stats:
|
41
|
+
Video: 334 (33.4%)
|
42
|
+
Image: 333 (33.3%)
|
43
|
+
Article: 333 (33.3%)
|
44
|
+
|
45
|
+
Benchmarking Large Dataset (10000 items)
|
46
|
+
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
|
47
|
+
Warming up --------------------------------------
|
48
|
+
Ruby Implementation 1.000 i/100ms
|
49
|
+
Calculating -------------------------------------
|
50
|
+
Ruby Implementation 0.212 (± 0.0%) i/s (4.71 s/i) - 1.000 in 4.711867s
|
51
|
+
|
52
|
+
Distribution Stats:
|
53
|
+
Video: 3334 (33.34%)
|
54
|
+
Image: 3333 (33.33%)
|
55
|
+
Article: 3333 (33.33%)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
+ cd /app
|
2
|
+
+ bundle exec ruby -I lib benchmark/end_to_end_benchmark.rb
|
3
|
+
Ruby version: 3.4.2
|
4
|
+
RUBY_PLATFORM: aarch64-linux
|
5
|
+
YJIT enabled: false
|
6
|
+
|
7
|
+
Running benchmarks...
|
8
|
+
|
9
|
+
Benchmarking Tiny Dataset (10 items)
|
10
|
+
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
|
11
|
+
Warming up --------------------------------------
|
12
|
+
Ruby Implementation 6.784k i/100ms
|
13
|
+
Calculating -------------------------------------
|
14
|
+
Ruby Implementation 66.579k (± 4.7%) i/s (15.02 μs/i) - 135.680k in 2.042522s
|
15
|
+
|
16
|
+
Distribution Stats:
|
17
|
+
Video: 4 (40.0%)
|
18
|
+
Image: 3 (30.0%)
|
19
|
+
Article: 3 (30.0%)
|
20
|
+
|
21
|
+
Benchmarking Small Dataset (100 items)
|
22
|
+
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
|
23
|
+
Warming up --------------------------------------
|
24
|
+
Ruby Implementation 168.000 i/100ms
|
25
|
+
Calculating -------------------------------------
|
26
|
+
Ruby Implementation 1.768k (± 6.2%) i/s (565.69 μs/i) - 3.528k in 2.003878s
|
27
|
+
|
28
|
+
Distribution Stats:
|
29
|
+
Video: 34 (34.0%)
|
30
|
+
Image: 33 (33.0%)
|
31
|
+
Article: 33 (33.0%)
|
32
|
+
|
33
|
+
Benchmarking Medium Dataset (1000 items)
|
34
|
+
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
|
35
|
+
Warming up --------------------------------------
|
36
|
+
Ruby Implementation 1.000 i/100ms
|
37
|
+
Calculating -------------------------------------
|
38
|
+
Ruby Implementation 19.919 (± 5.0%) i/s (50.20 ms/i) - 60.000 in 3.023325s
|
39
|
+
|
40
|
+
Distribution Stats:
|
41
|
+
Video: 334 (33.4%)
|
42
|
+
Image: 333 (33.3%)
|
43
|
+
Article: 333 (33.3%)
|
44
|
+
|
45
|
+
Benchmarking Large Dataset (10000 items)
|
46
|
+
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [aarch64-linux]
|
47
|
+
Warming up --------------------------------------
|
48
|
+
Ruby Implementation 1.000 i/100ms
|
49
|
+
Calculating -------------------------------------
|
50
|
+
Ruby Implementation 0.212 (± 0.0%) i/s (4.71 s/i) - 1.000 in 4.706258s
|
51
|
+
|
52
|
+
Distribution Stats:
|
53
|
+
Video: 3334 (33.34%)
|
54
|
+
Image: 3333 (33.33%)
|
55
|
+
Article: 3333 (33.33%)
|
@@ -0,0 +1,180 @@
|
|
1
|
+
# Benchmark Documentation
|
2
|
+
|
3
|
+
This document provides detailed information about TypeBalancer's performance benchmarks, including methodology, environment setup, and comprehensive results across different Ruby versions.
|
4
|
+
|
5
|
+
## Methodology
|
6
|
+
|
7
|
+
### Test Environment
|
8
|
+
|
9
|
+
- Hardware: ARM64 (aarch64) Linux environment
|
10
|
+
- Ruby Versions:
|
11
|
+
- Ruby 3.2.8
|
12
|
+
- Ruby 3.3.7
|
13
|
+
- Ruby 3.4.2
|
14
|
+
- YJIT: Both enabled and disabled configurations tested
|
15
|
+
- Docker containers used for consistent testing environment
|
16
|
+
|
17
|
+
### Test Scenarios
|
18
|
+
|
19
|
+
Each benchmark test evaluates performance across different collection sizes, from small content feeds to large-scale collections:
|
20
|
+
|
21
|
+
1. Tiny Dataset (Content Widget):
|
22
|
+
- Total Items: 10
|
23
|
+
- Distribution: Video (40%), Image (30%), Article (30%)
|
24
|
+
- Processing Time: ~12 microseconds
|
25
|
+
|
26
|
+
2. Small Dataset (Content Feed):
|
27
|
+
- Total Items: 100
|
28
|
+
- Distribution: Video (34%), Image (33%), Article (33%)
|
29
|
+
- Processing Time: ~464 microseconds
|
30
|
+
|
31
|
+
3. Medium Dataset (Category Page):
|
32
|
+
- Total Items: 1,000
|
33
|
+
- Distribution: Video (33.4%), Image (33.3%), Article (33.3%)
|
34
|
+
- Processing Time: ~19 milliseconds
|
35
|
+
|
36
|
+
4. Large Dataset (Site-wide Content):
|
37
|
+
- Total Items: 10,000
|
38
|
+
- Distribution: Video (33.34%), Image (33.33%), Article (33.33%)
|
39
|
+
- Processing Time: ~191 milliseconds
|
40
|
+
|
41
|
+
### Real-world Application
|
42
|
+
|
43
|
+
TypeBalancer is designed for practical use in content management and display systems:
|
44
|
+
- Process 10,000 items in under 200ms
|
45
|
+
- Maintain perfect distribution ratios
|
46
|
+
- Suitable for real-time web applications
|
47
|
+
- Efficient enough for on-the-fly content organization
|
48
|
+
|
49
|
+
### Measurement Approach
|
50
|
+
|
51
|
+
- Each test scenario is run multiple times to ensure statistical significance
|
52
|
+
- Both wall-clock time and CPU time are measured
|
53
|
+
- Results include operations per second and time per operation
|
54
|
+
- Benchmark-ips gem used for iterations per second calculations
|
55
|
+
- Performance measured across different Ruby versions and configurations
|
56
|
+
|
57
|
+
## Detailed Results
|
58
|
+
|
59
|
+
### Ruby 3.4.2 Performance (with PRISM)
|
60
|
+
|
61
|
+
| Metric | Tiny Dataset | Small Dataset | Medium Dataset | Large Dataset |
|
62
|
+
|--------|--------------|---------------|----------------|---------------|
|
63
|
+
| Speed (no YJIT) | 73.3K ops/sec | 2.0K ops/sec | 46.9 ops/sec | 4.8 ops/sec |
|
64
|
+
| Speed (YJIT) | 102.0K ops/sec | 2.1K ops/sec | 46.2 ops/sec | 4.8 ops/sec |
|
65
|
+
| Time/Op (no YJIT) | 13.63 μs | 494.84 μs | 21.34 ms | 207.62 ms |
|
66
|
+
| Time/Op (YJIT) | 9.80 μs | 478.05 μs | 21.64 ms | 208.85 ms |
|
67
|
+
| YJIT Impact | +39.1% | +3.5% | -1.4% | -0.6% |
|
68
|
+
| Distribution Quality | Perfect | Excellent | Excellent | Excellent |
|
69
|
+
|
70
|
+
### Ruby 3.3.7 Performance
|
71
|
+
|
72
|
+
| Metric | Tiny Dataset | Small Dataset | Medium Dataset | Large Dataset |
|
73
|
+
|--------|--------------|---------------|----------------|---------------|
|
74
|
+
| Speed (no YJIT) | 74.8K ops/sec | 2.1K ops/sec | 49.2 ops/sec | 5.1 ops/sec |
|
75
|
+
| Speed (YJIT) | 108.1K ops/sec | 2.3K ops/sec | 48.8 ops/sec | 5.2 ops/sec |
|
76
|
+
| Time/Op (no YJIT) | 13.37 μs | 477.95 μs | 20.34 ms | 196.05 ms |
|
77
|
+
| Time/Op (YJIT) | 9.25 μs | 437.36 μs | 20.49 ms | 193.08 ms |
|
78
|
+
| YJIT Impact | +44.5% | +9.3% | -0.7% | +1.5% |
|
79
|
+
| Distribution Quality | Perfect | Excellent | Excellent | Excellent |
|
80
|
+
|
81
|
+
### Ruby 3.2.8 Performance
|
82
|
+
|
83
|
+
| Metric | Tiny Dataset | Small Dataset | Medium Dataset | Large Dataset |
|
84
|
+
|--------|--------------|---------------|----------------|---------------|
|
85
|
+
| Speed (no YJIT) | 72.2K ops/sec | 2.2K ops/sec | 46.3 ops/sec | 4.7 ops/sec |
|
86
|
+
| Speed (YJIT) | 108.8K ops/sec | 2.2K ops/sec | 47.3 ops/sec | 5.2 ops/sec |
|
87
|
+
| Time/Op (no YJIT) | 13.86 μs | 451.35 μs | 21.59 ms | 215.04 ms |
|
88
|
+
| Time/Op (YJIT) | 9.19 μs | 449.99 μs | 21.15 ms | 193.67 ms |
|
89
|
+
| YJIT Impact | +50.8% | +0.3% | +2.1% | +11.0% |
|
90
|
+
| Distribution Quality | Perfect | Excellent | Excellent | Excellent |
|
91
|
+
|
92
|
+
## Analysis
|
93
|
+
|
94
|
+
### Performance Characteristics
|
95
|
+
|
96
|
+
1. Speed and Efficiency:
|
97
|
+
- Processes 10K items in ~200ms across all Ruby versions
|
98
|
+
- Microsecond-level processing for small collections (9-14μs)
|
99
|
+
- Millisecond-level processing for large collections (193-209ms)
|
100
|
+
- YJIT provides significant speedup for tiny datasets (39-51% faster)
|
101
|
+
- Suitable for real-time web applications
|
102
|
+
|
103
|
+
2. YJIT Impact:
|
104
|
+
- Most effective on tiny datasets (10 items)
|
105
|
+
- Benefits diminish as dataset size increases
|
106
|
+
- Ruby 3.2.8 shows most consistent YJIT improvements
|
107
|
+
- Some versions show slight regressions on larger datasets
|
108
|
+
|
109
|
+
3. Distribution Quality:
|
110
|
+
- Perfect distribution in small datasets
|
111
|
+
- Highly accurate distribution in larger datasets
|
112
|
+
- Consistent quality across all Ruby versions and YJIT settings
|
113
|
+
|
114
|
+
### Scaling Characteristics
|
115
|
+
|
116
|
+
1. Dataset Size Impact:
|
117
|
+
- Predictable performance scaling with size
|
118
|
+
- Sub-second processing even for large datasets
|
119
|
+
- Reliable performance characteristics
|
120
|
+
|
121
|
+
2. Memory Usage:
|
122
|
+
- Efficient memory utilization
|
123
|
+
- Predictable memory patterns
|
124
|
+
- Stable across different workloads
|
125
|
+
|
126
|
+
3. Distribution Quality:
|
127
|
+
- Maintains high accuracy at all scales
|
128
|
+
- Improves with larger datasets
|
129
|
+
- Consistent across implementations
|
130
|
+
|
131
|
+
## Use Cases
|
132
|
+
|
133
|
+
1. Content Management Systems:
|
134
|
+
- Homepage feeds (100s of items): < 1ms processing
|
135
|
+
- Category pages (1000s of items): ~20ms processing
|
136
|
+
- Site-wide content (10,000s of items): ~200ms processing
|
137
|
+
|
138
|
+
2. Real-time Applications:
|
139
|
+
- Widget content balancing: microsecond response
|
140
|
+
- Feed generation: sub-millisecond processing
|
141
|
+
- Content reorganization: real-time capable
|
142
|
+
|
143
|
+
3. Batch Processing:
|
144
|
+
- Large collection processing: efficient and reliable
|
145
|
+
- Consistent performance characteristics
|
146
|
+
- Predictable resource usage
|
147
|
+
|
148
|
+
## Conclusions
|
149
|
+
|
150
|
+
1. Version Selection:
|
151
|
+
- Ruby 3.2.8 shows optimal performance
|
152
|
+
- All versions maintain high distribution quality
|
153
|
+
- Version choice can be based on other requirements
|
154
|
+
|
155
|
+
2. Production Readiness:
|
156
|
+
- Suitable for production workloads
|
157
|
+
- Handles large datasets efficiently
|
158
|
+
- Real-time processing capable
|
159
|
+
|
160
|
+
3. Future Outlook:
|
161
|
+
- Continued optimization for larger datasets
|
162
|
+
- Focus on maintaining distribution quality
|
163
|
+
- Performance improvements in newer Ruby versions
|
164
|
+
|
165
|
+
## Running the Benchmarks
|
166
|
+
|
167
|
+
To run these benchmarks in your environment:
|
168
|
+
|
169
|
+
```bash
|
170
|
+
# Run all benchmarks
|
171
|
+
./bin/run_benchmarks.sh
|
172
|
+
|
173
|
+
# Run for specific platform
|
174
|
+
./bin/run_benchmarks.sh --platform linux/arm64
|
175
|
+
|
176
|
+
# Run for specific Ruby version
|
177
|
+
./bin/run_benchmarks.sh --version 3.2.8
|
178
|
+
```
|
179
|
+
|
180
|
+
Results will be saved in the `benchmark_results` directory.
|
data/examples/quality.rb
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'type_balancer'
|
4
|
+
|
5
|
+
class QualityChecker
|
6
|
+
def initialize
|
7
|
+
@issues = []
|
8
|
+
@examples_run = 0
|
9
|
+
@examples_passed = 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
check_basic_distribution
|
14
|
+
check_available_items
|
15
|
+
check_edge_cases
|
16
|
+
check_real_world_feed
|
17
|
+
|
18
|
+
print_summary
|
19
|
+
exit(@issues.empty? ? 0 : 1)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def record_issue(message)
|
25
|
+
@issues << message
|
26
|
+
end
|
27
|
+
|
28
|
+
def check_basic_distribution
|
29
|
+
@examples_run += 1
|
30
|
+
puts "\nBasic Distribution Example:"
|
31
|
+
positions = TypeBalancer.calculate_positions(total_count: 10, ratio: 0.3)
|
32
|
+
|
33
|
+
if positions == [0, 5, 9]
|
34
|
+
@examples_passed += 1
|
35
|
+
else
|
36
|
+
record_issue("Basic distribution positions #{positions.inspect} don't match expected [0, 5, 9]")
|
37
|
+
end
|
38
|
+
|
39
|
+
spacing = positions&.each_cons(2)&.map { |a, b| b - a }
|
40
|
+
puts "Positions for 3 items across 10 slots: #{positions.inspect}"
|
41
|
+
puts "Spacing between positions: #{spacing.inspect}"
|
42
|
+
|
43
|
+
return unless spacing != [5, 4]
|
44
|
+
|
45
|
+
record_issue("Basic distribution spacing #{spacing.inspect} isn't optimal [5, 4]")
|
46
|
+
end
|
47
|
+
|
48
|
+
def check_available_items
|
49
|
+
@examples_run += 1
|
50
|
+
puts "\nAvailable Items Example:"
|
51
|
+
positions = TypeBalancer.calculate_positions(
|
52
|
+
total_count: 10,
|
53
|
+
ratio: 0.5,
|
54
|
+
available_items: [0, 1, 2]
|
55
|
+
)
|
56
|
+
|
57
|
+
if positions == [0, 1, 2]
|
58
|
+
@examples_passed += 1
|
59
|
+
else
|
60
|
+
record_issue("Available items test returned #{positions.inspect} instead of expected [0, 1, 2]")
|
61
|
+
end
|
62
|
+
|
63
|
+
puts "Positions when only 3 slots available: #{positions.inspect}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def check_edge_cases
|
67
|
+
puts "\nEdge Cases:"
|
68
|
+
|
69
|
+
# Single item
|
70
|
+
@examples_run += 1
|
71
|
+
single = TypeBalancer.calculate_positions(total_count: 1, ratio: 1.0)
|
72
|
+
puts "Single item: #{single.inspect}"
|
73
|
+
if single == [0]
|
74
|
+
@examples_passed += 1
|
75
|
+
else
|
76
|
+
record_issue("Single item case returned #{single.inspect} instead of [0]")
|
77
|
+
end
|
78
|
+
|
79
|
+
# No items
|
80
|
+
@examples_run += 1
|
81
|
+
none = TypeBalancer.calculate_positions(total_count: 100, ratio: 0.0)
|
82
|
+
puts "No items needed: #{none.inspect}"
|
83
|
+
if none == []
|
84
|
+
@examples_passed += 1
|
85
|
+
else
|
86
|
+
record_issue("Zero ratio case returned #{none.inspect} instead of []")
|
87
|
+
end
|
88
|
+
|
89
|
+
# All items
|
90
|
+
@examples_run += 1
|
91
|
+
all = TypeBalancer.calculate_positions(total_count: 5, ratio: 1.0)
|
92
|
+
puts "All items needed: #{all.inspect}"
|
93
|
+
if all == [0, 1, 2, 3, 4]
|
94
|
+
@examples_passed += 1
|
95
|
+
else
|
96
|
+
record_issue("Full ratio case returned #{all.inspect} instead of [0, 1, 2, 3, 4]")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def check_real_world_feed
|
101
|
+
@examples_run += 1
|
102
|
+
puts "\nReal World Example - Content Feed:"
|
103
|
+
feed_size = 20
|
104
|
+
|
105
|
+
# Track allocated positions
|
106
|
+
allocated_positions = []
|
107
|
+
content_positions = {}
|
108
|
+
|
109
|
+
# Calculate positions for each type
|
110
|
+
content_positions[:video] = TypeBalancer.calculate_positions(
|
111
|
+
total_count: feed_size,
|
112
|
+
ratio: 0.3,
|
113
|
+
available_items: (0..7).to_a - allocated_positions
|
114
|
+
)
|
115
|
+
allocated_positions += content_positions[:video]
|
116
|
+
|
117
|
+
content_positions[:image] = TypeBalancer.calculate_positions(
|
118
|
+
total_count: feed_size,
|
119
|
+
ratio: 0.4,
|
120
|
+
available_items: (0..14).to_a - allocated_positions
|
121
|
+
)
|
122
|
+
allocated_positions += content_positions[:image]
|
123
|
+
|
124
|
+
content_positions[:article] = TypeBalancer.calculate_positions(
|
125
|
+
total_count: feed_size,
|
126
|
+
ratio: 0.3,
|
127
|
+
available_items: (0..19).to_a - allocated_positions
|
128
|
+
)
|
129
|
+
|
130
|
+
puts "\nContent Type Positions:"
|
131
|
+
content_positions.each do |type, pos|
|
132
|
+
puts "#{type}: #{pos.inspect}"
|
133
|
+
end
|
134
|
+
|
135
|
+
# Check for overlaps
|
136
|
+
all_positions = content_positions.values.compact.flatten
|
137
|
+
if all_positions == all_positions.uniq
|
138
|
+
puts "\nSuccess: No overlapping positions!"
|
139
|
+
@examples_passed += 1
|
140
|
+
else
|
141
|
+
overlaps = all_positions.group_by { |e| e }.select { |_, v| v.size > 1 }.keys
|
142
|
+
record_issue("Found overlapping positions at indices: #{overlaps.inspect}")
|
143
|
+
puts "\nWarning: Some positions overlap!"
|
144
|
+
end
|
145
|
+
|
146
|
+
# Verify distribution
|
147
|
+
puts "\nDistribution Stats:"
|
148
|
+
expected_counts = { video: 6, image: 8, article: 6 }
|
149
|
+
content_positions.each do |type, positions|
|
150
|
+
count = positions&.length || 0
|
151
|
+
percentage = (count.to_f / feed_size * 100).round(1)
|
152
|
+
puts "#{type}: #{count} items (#{percentage}% of feed)"
|
153
|
+
|
154
|
+
if count != expected_counts[type]
|
155
|
+
record_issue("#{type} count #{count} doesn't match expected #{expected_counts[type]}")
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def print_summary
|
161
|
+
puts "\n#{'-' * 50}"
|
162
|
+
puts 'Quality Check Summary:'
|
163
|
+
puts "Examples Run: #{@examples_run}"
|
164
|
+
puts "Examples Passed: #{@examples_passed}"
|
165
|
+
|
166
|
+
if @issues.empty?
|
167
|
+
puts "\nAll quality checks passed! ✓"
|
168
|
+
else
|
169
|
+
puts "\nQuality check failed with #{@issues.size} issues:"
|
170
|
+
@issues.each_with_index do |issue, index|
|
171
|
+
puts "#{index + 1}. #{issue}"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
puts "#{'-' * 50}"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
QualityChecker.new.run
|