Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: adaptive, low overhead fetching of cache timestamps. #43

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion BUILD
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
load("@rules_foreign_cc//tools/build_defs:configure.bzl", "configure_make")
load("@rules_foreign_cc//foreign_cc:configure.bzl", "configure_make")
# load("@rules_foreign_cc//tools/build_defs:make.bzl", "make")

configure_make(
Expand Down
9 changes: 6 additions & 3 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Rule repository
http_archive(
name = "rules_foreign_cc",
strip_prefix = "rules_foreign_cc-master",
url = "https://github.com/bazelbuild/rules_foreign_cc/archive/master.zip",
strip_prefix = "rules_foreign_cc-main",
#url = "https://github.com/bazelbuild/rules_foreign_cc/archive/master.zip",
url = "https://github.com/shiyi23/sentinel-cpp/raw/master/rules_foreign_cc-main.zip",
)

load("@rules_foreign_cc//:workspace_definitions.bzl", "rules_foreign_cc_dependencies")
#load("@rules_foreign_cc//:workspace_definitions.bzl", "rules_foreign_cc_dependencies")

load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies")

rules_foreign_cc_dependencies()

Expand Down
Binary file added rules_foreign_cc-main.zip
Binary file not shown.
7 changes: 3 additions & 4 deletions sentinel-core/log/block/block_log_task.cc
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#include "sentinel-core/log/block/block_log_task.h"
#include "block_log_task.h"

#include <iostream>
#include <memory>
#include <thread>

#include "sentinel-core/log/logger.h"
#include "sentinel-core/utils/time_utils.h"

#include "absl/strings/str_format.h"
#include "absl/time/time.h"
#include "logger.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "statistic_time_utils.h"

using namespace Sentinel::Utils;

Expand Down
5 changes: 4 additions & 1 deletion sentinel-core/statistic/base/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,14 @@ cc_library(
name = "leap_array_lib",
srcs = [
"leap_array.h",
"statistic_time_utils.h",
"statistic_time_utils.cc",
],
copts = DEFAULT_COPTS,
deps = [
":window_wrap_lib",
"//sentinel-core/log:logger_lib",
#"//sentinel-core/utils:utils_lib"
#"//sentinel-core/log:logger_lib",
]
)

Expand Down
2 changes: 1 addition & 1 deletion sentinel-core/statistic/base/bucket_leap_array.cc
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "sentinel-core/statistic/base/bucket_leap_array.h"
#include "bucket_leap_array.h"

namespace Sentinel {
namespace Stat {
Expand Down
4 changes: 2 additions & 2 deletions sentinel-core/statistic/base/bucket_leap_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

#include <memory>

#include "sentinel-core/statistic/base/leap_array.h"
#include "sentinel-core/statistic/base/metric_bucket.h"
#include "leap_array.h"
#include "metric_bucket.h"

namespace Sentinel {
namespace Stat {
Expand Down
13 changes: 6 additions & 7 deletions sentinel-core/statistic/base/leap_array.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
#include <mutex>
#include <vector>

#include "sentinel-core/log/logger.h"
#include "sentinel-core/statistic/base/window_wrap.h"
#include "sentinel-core/utils/time_utils.h"
#include "statistic_time_utils.h"
#include "window_wrap.h"

namespace Sentinel {
namespace Stat {
Expand Down Expand Up @@ -66,7 +65,7 @@ int32_t LeapArray<T>::IntervalInMs() const {

template <typename T>
WindowWrapSharedPtr<T> LeapArray<T>::CurrentWindow() {
return this->CurrentWindow(Utils::TimeUtils::CurrentTimeMillis().count());
return this->CurrentWindow(Statistic_Utils::TimeUtils::CurrentTimeMillis().count());
}

template <typename T>
Expand Down Expand Up @@ -119,7 +118,7 @@ int64_t LeapArray<T>::CalculateWindowStart(int64_t time_millis) const {
template <typename T>
bool LeapArray<T>::IsBucketDeprecated(
const WindowWrapSharedPtr<T>& wrap) const {
return this->IsBucketDeprecated(Utils::TimeUtils::CurrentTimeMillis().count(),
return this->IsBucketDeprecated(Statistic_Utils::TimeUtils::CurrentTimeMillis().count(),
wrap);
}

Expand All @@ -131,12 +130,12 @@ bool LeapArray<T>::IsBucketDeprecated(

template <typename T>
std::vector<WindowWrapSharedPtr<T>> LeapArray<T>::Buckets() const {
return this->Buckets(Utils::TimeUtils::CurrentTimeMillis().count());
return this->Buckets(Statistic_Utils::TimeUtils::CurrentTimeMillis().count());
}

template <typename T>
std::vector<std::shared_ptr<T>> LeapArray<T>::Values() const {
return this->Values(Utils::TimeUtils::CurrentTimeMillis().count());
return this->Values(Statistic_Utils::TimeUtils::CurrentTimeMillis().count());
}

template <typename T>
Expand Down
7 changes: 6 additions & 1 deletion sentinel-core/statistic/base/metric_bucket.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <memory>

#include "sentinel-core/common/constants.h"
#include "sentinel-core/statistic/base/metric_event.h"
#include "metric_event.h"

namespace Sentinel {
namespace Stat {
Expand All @@ -19,11 +19,16 @@ class MetricBucket {
void Add(const MetricEvent& event, int64_t n);
void AddRt(int64_t rt);

inline long get_writes() { return writes_.load();};
inline long get_reads() { return reads_.load();};

private:
const std::unique_ptr<std::atomic<int64_t>[]> counters_ =
std::make_unique<std::atomic<int64_t>[]>(
static_cast<int>(MetricEvent::Count));
long min_rt_;
std::atomic<long> writes_;
std::atomic<long> reads_;

void InitMinRt();
};
Expand Down
12 changes: 12 additions & 0 deletions sentinel-core/statistic/base/statistic_time_utils.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "statistic_time_utils.h"

namespace Sentinel {
namespace Statistic_Utils {

std::chrono::milliseconds TimeUtils::CurrentTimeMillis() {
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
}

} // namespace Utils
} // namespace Sentinel
16 changes: 16 additions & 0 deletions sentinel-core/statistic/base/statistic_time_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <chrono>

namespace Sentinel {
namespace Statistic_Utils {

class TimeUtils {
public:
TimeUtils() = delete;

static std::chrono::milliseconds CurrentTimeMillis();
};

} // namespace Utils
} // namespace Sentinel
19 changes: 14 additions & 5 deletions sentinel-core/statistic/base/window_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ class WindowWrap {
int64_t BucketStart() const;
std::shared_ptr<T> Value() const;

void ResetTo(int64_t start_time);
inline void ResetTo(int64_t start_time)
{
bucket_start_ = start_time;
}
bool IsTimeInBucket(int64_t time_millis) const;

private:
Expand All @@ -44,12 +47,18 @@ std::shared_ptr<T> WindowWrap<T>::Value() const {
return value_;
}

template <typename T>
void WindowWrap<T>::ResetTo(int64_t start_time) {
this->bucket_start_ = start_time;
}
//template <typename T>
//void WindowWrap<T>::ResetTo(int64_t start_time) {
// this->bucket_start_ = start_time;
//}

template <typename T>
/**
* Check whether given timestamp is in current bucket.
*
* @param time_millis valid timestamp in ms
* @return true if the given time is in current bucket, otherwise false
* */
bool WindowWrap<T>::IsTimeInBucket(int64_t time_millis) const {
return bucket_start_ <= time_millis &&
time_millis < bucket_start_ + bucket_length_ms_;
Expand Down
3 changes: 2 additions & 1 deletion sentinel-core/statistic/node/statistic_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ bool StatisticNode::IsNodeInTime(const MetricItemSharedPtr& item,
}

std::unordered_map<long, MetricItemSharedPtr> StatisticNode::Metrics() {
int64_t cur_time = Utils::TimeUtils::CurrentTimeMillis().count();
using Sentinel::Statistic_Utils;
int64_t cur_time = Sentinel::Statistic_Utils::TimeUtils::CurrentTimeMillis().count();
cur_time = cur_time - cur_time % 1000;
std::unordered_map<long, MetricItemSharedPtr> map;
std::vector<MetricItemSharedPtr> items_of_second =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ std::shared_ptr<StatisticNodeVO> StatisticNodeVO::FromResourceNode(
vo->set_block_per_min(node->BlockCountInMinute());
vo->set_total_per_min(node->TotalCountInMinute());
vo->set_exception_per_min(node->ExceptionCountInMinute());
vo->set_timestamp(Utils::TimeUtils::CurrentTimeMillis().count());
vo->set_timestamp(Sentinel::Statistic_Utils::TimeUtils::CurrentTimeMillis().count());
return vo;
}

Expand Down
6 changes: 6 additions & 0 deletions sentinel-core/utils/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ cc_library(
"time_utils.cc",
],
copts = DEFAULT_COPTS,
deps = [
"//sentinel-core/statistic/base:leap_array_lib",
"//sentinel-core/statistic/base:bucket_leap_array_lib",
"//sentinel-core/statistic/base:metric_bucket_lib",
"//sentinel-core/statistic/base:window_wrap_lib",
]
)


Expand Down
137 changes: 136 additions & 1 deletion sentinel-core/utils/time_utils.cc
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
#include "sentinel-core/utils/time_utils.h"
#include "time_utils.h"

#include <iostream>

/**
* <p>Provides millisecond-level time of OS.</p>
* <p>
* Here we should see that not all the time TimeUtil should
* keep looping 1_000 times every second (Actually about 800/s due to some losses).
* <pre>
* * In idle conditions it just acts as System.currentTimeMillis();
* * In busy conditions (significantly more than 1_000/s) it keeps loop to reduce costs.
* </pre>
* For detail design and proposals please goto
* <a href="https://github.com/alibaba/Sentinel/issues/1702#issuecomment-692151160">https://github.com/alibaba/Sentinel/issues/1702</a>
* @author alibaba.com
* @author huangshiyi
* */

namespace Sentinel {
namespace Utils {
Expand All @@ -8,5 +25,123 @@ std::chrono::milliseconds TimeUtils::CurrentTimeMillis() {
std::chrono::system_clock::now().time_since_epoch());
}

TimeUtils::TimeUtils()
{
// statistics_ = new Stat::BucketLeapArray(3, 3000);
currentTimeMillis_ = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
std::thread t(&TimeUtils::Run, this);
t.detach();
}

void TimeUtils::Run()
{
while(true)
{
this->Check();
if(this->state_ == STATE::RUNNING)
{
this->currentTimeMillis_ = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
this->statistics_->CurrentWindow(currentTimeMillis_.count())->Value()->get_writes().fetch_add(1);
try {
usleep(1000);//1000 microseconds = 1ms
} catch (std::exception e)
{
throw e.what();
}
continue ;
}

if(this->state_ == STATE::IDLE)
{
try {
usleep(300000);//300000 micro seconds = 300 ms
} catch (std::exception e)
{
throw e.what();
}
continue ;
}

if(this->state_ == STATE::PREPARE)
{
//TODO:should print debug level log info here, but I don't have too much time now
std::cout << "TimeUtils switches to RUNNING" << std::endl;
this->currentTimeMillis_ = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
this->state_ = STATE::RUNNING;
}

}
}

void TimeUtils::Check()
{
std::chrono::milliseconds now = this->CurrentTime(true);
//every period
if(now - this->last_check_ < CHECK_INTERVAL_)
{
return ;
}
this->last_check_ = now;
std::pair<long, long> qps = this->get_current_qps(now);
if(this->state_ == STATE::IDLE && qps.first > HITS_UPPER_BOUNDARY_)
{
std::cout << "TimeUtil switches to PREPARE for better performance, "
"reads= << " << qps.first << "writes= << " << qps.second << std::endl;
this->state_ = STATE::PREPARE;
} else if(this->state_ == STATE::RUNNING && qps.first < HITS_LOWER_BOUNDARY_)
{
std::cout << "TimeUtil switches to IDLE due to not enough load, "
"reads= " << qps.first << "writes= " << qps.second <<std::endl;
this->state_ = STATE::IDLE;
}
}

std::pair<long, long> TimeUtils::get_current_qps(std::chrono::milliseconds now)
{
auto vec = this->statistics_->Buckets();
long reads = 0, writes = 0;
int cnt = 0;
for (auto const elem : vec)
{
if (elem->IsTimeInBucket(now.count()))
{
continue ;
}
++ cnt;
reads += elem->Value()->get_reads().load();
writes += elem->Value()->get_writes().load();
if (cnt < 1)
{
return std::make_pair(0,0);
}
}
return std::make_pair(reads/cnt, writes/cnt);
}

std::chrono::milliseconds TimeUtils::CurrentTime(bool inner_call)
{
auto now = this->currentTimeMillis_;
auto val = this->statistics_->CurrentWindow()->Value();
if(!inner_call)
{
//external call
val->get_reads().fetch_add(1);
}
if(this->state_ == STATE::IDLE || this->state_ == STATE::PREPARE)
{
now = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
this->currentTimeMillis_ = now; //cache time
if(!inner_call)
{
val->get_writes().fetch_add(1);
}
}
return now;
}

} // namespace Utils
} // namespace Sentinel
Loading