Skip to content

Commit

Permalink
[Link event damping] Add utility methods. (#1313)
Browse files Browse the repository at this point in the history
- Adding utility methods to calculate:
  1) Remaining value of a substance after time t using half-life
     formula.
  2) Time to reach a target value using half-life formula.

HLD: sonic-net/SONiC#1071
  • Loading branch information
Ashish1805 authored Oct 25, 2023
1 parent 1ef16ee commit 7210b0c
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
39 changes: 39 additions & 0 deletions lib/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ extern "C" {
#include "meta/sai_serialize.h"
#include "swss/logger.h"

#include <cmath>

using namespace sairedis;

void Utils::clearOidList(
Expand Down Expand Up @@ -80,3 +82,40 @@ void Utils::clearOidValues(

}
}

uint64_t Utils::timeToReachTargetValueUsingHalfLife(
_In_ uint64_t halfLifeUsec,
_In_ uint32_t initialValue,
_In_ uint32_t targetValue)
{
SWSS_LOG_ENTER();

// Check if all the input fields have positive values and targeted value is
// smaller than initial value.
if ((initialValue == 0) || (targetValue == 0) ||
(targetValue >= initialValue) || (halfLifeUsec == 0))
{
return 0;
}

// t = -half_life * log2[N(t)/N(0)] from half-life formula "N(t) = N(0) * 2 ^ (-t / half_life)"
return uint64_t(-double(halfLifeUsec) * (log(double(targetValue)/double(initialValue))/log(2.0)));
}

uint32_t Utils::valueAfterDecay(
_In_ uint64_t timeToDecayUsec,
_In_ uint64_t halfLifeUsec,
_In_ uint32_t initialValue)
{
SWSS_LOG_ENTER();

if ((initialValue == 0) || (timeToDecayUsec == 0) || (halfLifeUsec == 0))
{
return initialValue;
}

// Using half-life formula: N(t) = N(0) * 2 ^ (-t / half_life)
double ratio = double(timeToDecayUsec)/double(halfLifeUsec);

return uint32_t(double(initialValue) * pow(0.5, ratio));
}
11 changes: 11 additions & 0 deletions lib/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,16 @@ namespace sairedis

static void clearOidList(
_Out_ sai_object_list_t& list);

static uint64_t timeToReachTargetValueUsingHalfLife(
_In_ uint64_t halfLifeUsec,
_In_ uint32_t initialValue,
_In_ uint32_t targetValue);

static uint32_t valueAfterDecay(
_In_ uint64_t timeToDecayUsec,
_In_ uint64_t halfLifeUsec,
_In_ uint32_t initialValue);

};
}
110 changes: 110 additions & 0 deletions unittest/lib/TestUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include <gtest/gtest.h>

#include <vector>

using namespace sairedis;

TEST(Utils, clearOidValues)
Expand Down Expand Up @@ -59,3 +61,111 @@ TEST(Utils, clearOidValues)
EXPECT_EQ(oids[0], 0);

}

struct ExpectedTimeToReachTargetData
{
uint64_t half_life_usec;
uint32_t initial_value;
uint32_t target_value;
uint64_t expected_time_to_reach_target_usec;
};

TEST(Utils, TimeToReachTargetValueUsingHalfLifeWithInvalidInput)
{
std::vector<struct ExpectedTimeToReachTargetData> testData = {
/*Invalid input when initial value is 0.*/ {5, 0, 10, 0},
/*Invalid input when target value is 0.*/ {5, 10, 0, 0},
/*Invalid input when target value is more than initial value.*/
{5, 5, 10, 0},
/*Invalid input when initial value is same as target value.*/
{5, 10, 10, 0},
/*Invalid input when half life duration is 0.*/ {0, 15, 10, 0}};

for (const auto &data : testData)
{
SCOPED_TRACE(::testing::Message()
<< "Testing half life(usec): " << data.half_life_usec
<< ", initial value: " << data.initial_value
<< ", final value: " << data.target_value
<< ", expected_time_to_reach_target(usec): "
<< data.expected_time_to_reach_target_usec);

EXPECT_EQ(Utils::timeToReachTargetValueUsingHalfLife(
data.half_life_usec, data.initial_value, data.target_value),
data.expected_time_to_reach_target_usec);
}
}

TEST(Utils, VerifyTimeToReachTargetValueUsingHalfLife)
{
std::vector<struct ExpectedTimeToReachTargetData> testData = {
{30000000, 4500, 500, 95097750}, {30000000, 4500, 1100, 60972644},
{30000000, 4500, 1700, 42131707}, {8000000, 17000, 1300, 29671609},
{8000000, 17000, 350, 44816288}, {8000000, 1532, 311, 18403438},
{8000000, 1532, 1, 84649604}, {5000000, 20000, 2500, 15000000},
{5000000, 20000, 133, 36162149}, {30000000, 2000, 1500, 12451124}};

for (const auto &data : testData)
{
SCOPED_TRACE(::testing::Message()
<< "Testing half life(usec): " << data.half_life_usec
<< ", initial value: " << data.initial_value
<< ", final value: " << data.target_value
<< ", expected_time_to_reach_target(usec): "
<< data.expected_time_to_reach_target_usec);

EXPECT_EQ(Utils::timeToReachTargetValueUsingHalfLife(
data.half_life_usec, data.initial_value, data.target_value),
data.expected_time_to_reach_target_usec);
}
}

struct ValueAFterDecayData
{
uint64_t time_to_decay_usec;
uint32_t half_life_usec;
uint32_t initial_value;
uint32_t expected_target_value;
};

TEST(Utils, ValueAfterDecayWithInvalidInput)
{
std::vector<struct ValueAFterDecayData> test_data = {
/*Invalid input when time to decay duration is 0.*/ {0, 5, 10, 10},
/*Invalid input when half life is 0.*/ {5, 0, 10, 10},
/*Invalid input when initial value is 0.*/ {5, 5, 0, 0}};

for (const auto &data : test_data)
{
SCOPED_TRACE(::testing::Message()
<< "Testing time to decay(usec): " << data.time_to_decay_usec
<< ", half life(usec): " << data.half_life_usec
<< ", initial value: " << data.initial_value
<< ", expected target value: " << data.expected_target_value);

EXPECT_EQ(Utils::valueAfterDecay(
data.time_to_decay_usec, data.half_life_usec, data.initial_value),
data.expected_target_value);
}
}

TEST(Utils, VerifyValueAfterDecay)
{
std::vector<struct ValueAFterDecayData> test_data = {
{15345678, 5000000, 20000, 2383},
{3000000, 5000000, 20000, 13195},
{37256870, 5000000, 15, 0}};

for (const auto &data : test_data)
{
SCOPED_TRACE(::testing::Message()
<< "Testing time to decay(usec): " << data.time_to_decay_usec
<< ", half life(usec): " << data.half_life_usec
<< ", initial value: " << data.initial_value
<< ", expected target value: " << data.expected_target_value);

EXPECT_EQ(Utils::valueAfterDecay(
data.time_to_decay_usec, data.half_life_usec, data.initial_value),
data.expected_target_value);
}
}

0 comments on commit 7210b0c

Please sign in to comment.