-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a stride scheduler to split bandwidth between two sources of tra…
…ffic. (#443)
- Loading branch information
1 parent
7f67efb
commit 21c97b4
Showing
2 changed files
with
181 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/** \copyright | ||
* Copyright (c) 2020, Balazs Racz | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions are met: | ||
* | ||
* - Redistributions of source code must retain the above copyright notice, | ||
* this list of conditions and the following disclaimer. | ||
* | ||
* - Redistributions in binary form must reproduce the above copyright notice, | ||
* this list of conditions and the following disclaimer in the documentation | ||
* and/or other materials provided with the distribution. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
* POSSIBILITY OF SUCH DAMAGE. | ||
* | ||
* \file BandwidthMerger.cxxtest | ||
* | ||
* Unit tests for the stride scheduler. | ||
* | ||
* @author Balazs Racz | ||
* @date 10 Oct 2020 | ||
*/ | ||
|
||
#include "trains/BandwidthMerger.hxx" | ||
|
||
#include "utils/test_main.hxx" | ||
|
||
class BandwidthMergerTest : public ::testing::Test | ||
{ | ||
protected: | ||
/// Runs a simulation with a certain number of steps with a bandwidth | ||
/// merger. | ||
void collect_stats(uint8_t percent, unsigned num_steps) | ||
{ | ||
BandwidthMerger m {percent}; | ||
results_[0] = results_[1] = 0; | ||
for (unsigned i = 0; i < num_steps; ++i) | ||
{ | ||
if (m.step()) | ||
{ | ||
++results_[1]; | ||
} | ||
else | ||
{ | ||
++results_[0]; | ||
} | ||
} | ||
} | ||
|
||
/// Results of the simulation. [0] is the number of steps with false | ||
/// output, [1] is the number of steps with true output. | ||
unsigned results_[2]; | ||
}; | ||
|
||
TEST_F(BandwidthMergerTest, fifty) | ||
{ | ||
collect_stats(50, 34); | ||
EXPECT_EQ(17u, results_[0]); | ||
EXPECT_EQ(17u, results_[1]); | ||
} | ||
|
||
TEST_F(BandwidthMergerTest, hundred) | ||
{ | ||
collect_stats(100, 34); | ||
EXPECT_EQ(0u, results_[0]); | ||
EXPECT_EQ(34u, results_[1]); | ||
} | ||
|
||
TEST_F(BandwidthMergerTest, zero) | ||
{ | ||
collect_stats(0, 34); | ||
EXPECT_EQ(34u, results_[0]); | ||
EXPECT_EQ(0u, results_[1]); | ||
} | ||
|
||
TEST_F(BandwidthMergerTest, ten) | ||
{ | ||
collect_stats(10, 34); | ||
EXPECT_EQ(31u, results_[0]); | ||
EXPECT_EQ(3u, results_[1]); | ||
} |
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,89 @@ | ||
/** \copyright | ||
* Copyright (c) 2020, Balazs Racz | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions are met: | ||
* | ||
* - Redistributions of source code must retain the above copyright notice, | ||
* this list of conditions and the following disclaimer. | ||
* | ||
* - Redistributions in binary form must reproduce the above copyright notice, | ||
* this list of conditions and the following disclaimer in the documentation | ||
* and/or other materials provided with the distribution. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
* POSSIBILITY OF SUCH DAMAGE. | ||
* | ||
* \file BandwidthMerger.hxx | ||
* | ||
* Simple stride scheduler for splitting bandwidth. | ||
* | ||
* @author Balazs Racz | ||
* @date 10 Oct 2020 | ||
*/ | ||
|
||
#ifndef _TRAINS_BANDWIDTHMERGER_HXX_ | ||
#define _TRAINS_BANDWIDTHMERGER_HXX_ | ||
|
||
#include <inttypes.h> | ||
|
||
#include "utils/macros.h" | ||
|
||
/// Simple stride scheduler. Emulates a two-way split of bandwidth between a | ||
/// first source and a second source. The percentage assigned to the first | ||
/// source is a parameter. Over time the fraction of outputs selected from the | ||
/// first source converges to this percentage. | ||
struct BandwidthMerger | ||
{ | ||
/// Constructor. | ||
/// @param percent is the percentage (0..100) of the bandwidth that | ||
/// should be assigned to the first source. | ||
BandwidthMerger(uint8_t percent) | ||
: percentFirst_(percent) | ||
{ | ||
HASSERT(percentFirst_ <= 100); | ||
} | ||
/// Runs one step. | ||
/// @return true if the first source is selected in this step. | ||
bool step() | ||
{ | ||
currentState_ += percentFirst_; | ||
if (currentState_ >= 100) | ||
{ | ||
currentState_ -= 100; | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
/// If the step function returned false, but still the first source was | ||
/// taken (e.g. because the second source was empty), call this function to | ||
/// clear the state. This will avoid selecting the first source twice in a | ||
/// row for example. | ||
void reset() | ||
{ | ||
// Reduces the state by 100 but clips it to zero. Since the state is | ||
// always < 100, the clipping will always win. | ||
currentState_ = 0; | ||
} | ||
|
||
/// State of the current stride. This is always between 0..99. It | ||
/// represents the fractional steps that the first source has accumulated | ||
/// but not paid out in the form of selections yet. | ||
uint8_t currentState_ {0}; | ||
/// Percentage of the bandwidth that should be assigned to the first | ||
/// source. Range 0..100. | ||
uint8_t percentFirst_; | ||
}; | ||
|
||
#endif // _TRAINS_BANDWIDTHMERGER_HXX_ |