SpeedFactor.pm 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. # ex:ts=8 sw=4:
  2. # $OpenBSD: SpeedFactor.pm,v 1.2 2013/10/12 14:11:23 espie Exp $
  3. #
  4. # Copyright (c) 2010-2013 Marc Espie <espie@openbsd.org>
  5. #
  6. # Permission to use, copy, modify, and distribute this software for any
  7. # purpose with or without fee is hereby granted, provided that the above
  8. # copyright notice and this permission notice appear in all copies.
  9. #
  10. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. use strict;
  18. use warnings;
  19. # this is the optional classes that are only used when speed factors are
  20. # involved
  21. # a bin that keeps tracks of its total weight
  22. package DPB::Heuristics::Bin::Heavy;
  23. our @ISA = qw(DPB::Heuristics::Bin);
  24. sub add
  25. {
  26. my ($self, $v) = @_;
  27. $self->SUPER::add($v);
  28. $self->{weight} += $DPB::Heuristics::weight{$v};
  29. }
  30. sub remove
  31. {
  32. my ($self, $v) = @_;
  33. $self->{weight} -= $DPB::Heuristics::weight{$v};
  34. $self->SUPER::remove($v);
  35. }
  36. # and the partitioned queue, based on heavy bins
  37. package DPB::Heuristics::Queue::Part;
  38. our @ISA = qw(DPB::Heuristics::Queue);
  39. # 20 bins, binary....
  40. sub find_bin
  41. {
  42. my $w = shift;
  43. return 10 if !defined $w;
  44. if ($w > 65536) {
  45. if ($w > 1048576) { 9 } else { 8 }
  46. } elsif ($w > 256) {
  47. if ($w > 4096) {
  48. if ($w > 16384) { 7 } else { 6 }
  49. } elsif ($w > 1024) { 5 } else { 4 }
  50. } elsif ($w > 16) {
  51. if ($w > 64) { 3 } else { 2 }
  52. } elsif ($w > 4) { 1 } else { 0 }
  53. }
  54. sub add
  55. {
  56. my ($self, $v) = @_;
  57. $self->SUPER::add($v);
  58. $v->{weight} = $DPB::Heuristics::weight{$v};
  59. $self->{bins}[find_bin($v->{weight})]->add($v);
  60. }
  61. sub remove
  62. {
  63. my ($self, $v) = @_;
  64. $self->SUPER::remove($v);
  65. $self->{bins}[find_bin($v->{weight})]->remove($v);
  66. }
  67. sub find_sorter
  68. {
  69. my ($self, $core) = @_;
  70. my $all = DPB::Core->all_sf;
  71. if ($core->sf > $all->[-1] - 1) {
  72. return $self->SUPER::find_sorter($core);
  73. } else {
  74. return DPB::Heuristics::Sorter->new($self->bin_part($core->sf,
  75. $all));
  76. }
  77. }
  78. # simpler partitioning
  79. sub bin_part
  80. {
  81. my ($self, $wanted, $all_sf) = @_;
  82. # note that all_sf is sorted
  83. # compute totals
  84. my $sum_sf = 0;
  85. for my $i (@$all_sf) {
  86. $sum_sf += $i;
  87. }
  88. my @bins = @{$self->{bins}};
  89. my $sum_weight = 0.0;
  90. for my $bin (@bins) {
  91. $sum_weight += $bin->weight;
  92. }
  93. # setup for the main loop
  94. my $partial_weight = 0.0;
  95. my $partial_sf = 0.0;
  96. my $result = [];
  97. # go through speed factors until we've gone thru the one we want
  98. while (my $sf = shift @$all_sf) {
  99. # passed it -> give result
  100. last if $sf > $wanted+1;
  101. # compute threshold for total weight
  102. $partial_sf += $sf;
  103. my $thr = $sum_weight * $partial_sf / $sum_sf;
  104. # grab weights until we reach the desired amount
  105. while (my $bin = shift @bins) {
  106. $partial_weight += $bin->weight;
  107. push(@$result, $bin);
  108. last if $partial_weight > $thr;
  109. }
  110. }
  111. return $result;
  112. }
  113. sub new
  114. {
  115. my ($class, $h) = @_;
  116. my $o = $class->SUPER::new($h);
  117. my $bins = $o->{bins} = [];
  118. for my $i (0 .. 9) {
  119. push(@$bins, DPB::Heuristics::Bin::Heavy->new($h));
  120. }
  121. push(@$bins, DPB::Heuristics::Bin->new($h));
  122. return $o;
  123. }
  124. 1;