From 82bd0304d05a4f4c7ca913eab7d0863912bccfa3 Mon Sep 17 00:00:00 2001 From: rfwang07 Date: Tue, 3 Dec 2024 23:05:06 +0800 Subject: [PATCH] adapt the code for oeaware 2.0 --- CMakeLists.txt | 11 +- include/interface.h | 74 -------- include/logs.h | 12 +- include/opt.h | 2 +- include/tuner.h | 21 ++- src/configs.cc | 2 +- src/oeaware_plugins/instance.cc | 11 +- src/oeaware_plugins/tuner_sysboost.cc | 249 ++++++++++++-------------- src/startup_opt.cc | 14 +- 9 files changed, 158 insertions(+), 238 deletions(-) delete mode 100644 include/interface.h diff --git a/CMakeLists.txt b/CMakeLists.txt index df8006e..dda676e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 3.15) project(D-FOT) -set(CMAKE_CXX_STANDARD 11) - if(CMAKE_BUILD_TYPE STREQUAL "Debug") message("-- Build type: Debug") add_compile_options(-g3 -O0) @@ -17,7 +15,7 @@ else() add_compile_options(-O3) endif() -add_compile_options(-fPIC -Wall -Wextra) +add_compile_options(-std=c++17 -fPIC -Wall -Wextra) set(dfot_tuner_sysboost_src src/oeaware_plugins/instance.cc @@ -31,8 +29,13 @@ set(dfot_tuner_sysboost_src add_library(dfot SHARED ${dfot_tuner_sysboost_src}) + include_directories(dfot PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + # 因为oeAware头文件问题,此处临时适配 + /usr/include/libkperf + /usr/include/oeaware + /usr/include/oeaware/interface ) -target_link_libraries(dfot kperf sym dl log4cplus boost_system boost_filesystem) +target_link_libraries(dfot boundscheck kperf sym dl log4cplus boost_system boost_filesystem) diff --git a/include/interface.h b/include/interface.h deleted file mode 100644 index 0a49743..0000000 --- a/include/interface.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2024 Huawei Technologies Co., Ltd. - * oeAware is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - ******************************************************************************/ -#ifndef __INTERFACE_H__ -#define __INTERFACE_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct DataBuf { - int len; - void *data; -}; - -struct DataRingBuf { - /* instance name */ - const char *instance_name; - /* buf write index, initial value is -1 */ - int index; - /* instance run times */ - uint64_t count; - struct DataBuf *buf; - int buf_len; -}; - -struct Param { - const struct DataRingBuf **ring_bufs; - int len; -}; - -struct Interface { - const char* (*get_version)(); - /* The instance name is a unique identifier in the system. */ - const char* (*get_name)(); - const char* (*get_description)(); - /* Specifies the instance dependencies, which is used as the input information - * for instance execution. - */ - const char* (*get_dep)(); - /* Instance scheduling priority. In a uniform time period, a instance with a - * lower priority is scheduled first. - */ - int (*get_priority)(); - int (*get_type)(); - /* Instance execution period. */ - int (*get_period)(); - bool (*enable)(); - void (*disable)(); - const struct DataRingBuf* (*get_ring_buf)(); - void (*run)(const struct Param*); -}; - -/* Obtains the instances from the plugin. - * The return value is the number of instances. - */ -int get_instance(struct Interface **interface); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/logs.h b/include/logs.h index f27d289..331060c 100644 --- a/include/logs.h +++ b/include/logs.h @@ -22,11 +22,11 @@ #define DFOT_LOG_PATH "/etc/dfot/dfot.log" -#define DEBUG(fmt) LOG4CPLUS_DEBUG(logger.get(), fmt) -#define INFO(fmt) LOG4CPLUS_INFO(logger.get(), fmt) -#define WARN(fmt) LOG4CPLUS_WARN(logger.get(), fmt) -#define ERROR(fmt) LOG4CPLUS_ERROR(logger.get(), fmt) -#define FATAL(fmt) LOG4CPLUS_FATAL(logger.get(), fmt) +#define DEBUG(fmt) LOG4CPLUS_DEBUG(dfot_logger.get(), fmt) +#define INFO(fmt) LOG4CPLUS_INFO(dfot_logger.get(), fmt) +#define WARN(fmt) LOG4CPLUS_WARN(dfot_logger.get(), fmt) +#define ERROR(fmt) LOG4CPLUS_ERROR(dfot_logger.get(), fmt) +#define FATAL(fmt) LOG4CPLUS_FATAL(dfot_logger.get(), fmt) static std::map LOG_LEVEL = { {"DEBUG", log4cplus::DEBUG_LOG_LEVEL}, @@ -51,6 +51,6 @@ private: log4cplus::Initializer initializer; }; -extern Logger logger; +extern Logger dfot_logger; #endif diff --git a/include/opt.h b/include/opt.h index 2c40cbe..ff0241b 100644 --- a/include/opt.h +++ b/include/opt.h @@ -14,7 +14,7 @@ #include -#include "libkperf/pmu.h" +#include #include "configs.h" extern bool check_dependence_ready(); diff --git a/include/tuner.h b/include/tuner.h index 326615c..46db4f7 100644 --- a/include/tuner.h +++ b/include/tuner.h @@ -12,8 +12,25 @@ #ifndef __TUNER_H__ #define __TUNER_H__ -#include "interface.h" +#include +#include +#include -extern struct Interface sysboost_tuner; +class SysboostTuner : public oeaware::Interface { +public: + SysboostTuner(); + ~SysboostTuner(); + oeaware::Result OpenTopic(const oeaware::Topic &topic) override; + void CloseTopic(const oeaware::Topic &topic) override; + void UpdateData(const DataList &dataList) override; + oeaware::Result Enable(const std::string ¶m) override; + void Disable() override; + void Run() override; + +private: + oeaware::Topic depTopic; + void *processingArea; + size_t processingAreaSize; +}; #endif diff --git a/src/configs.cc b/src/configs.cc index 9cc0c38..9aa6d36 100644 --- a/src/configs.cc +++ b/src/configs.cc @@ -81,7 +81,7 @@ int parse_general(boost::property_tree::ptree pt) } else { configs->log_level = it->second; } - logger.setLogLevel(configs->log_level); + dfot_logger.setLogLevel(configs->log_level); configs->sampling_strategy = pt.get("general.COLLECTOR_SAMPLING_STRATEGY"); configs->high_load_threshold = pt.get("general.COLLECTOR_HIGH_LOAD_THRESHOLD"); configs->collector_sampling_period = pt.get("general.COLLECTOR_SAMPLING_PERIOD"); diff --git a/src/oeaware_plugins/instance.cc b/src/oeaware_plugins/instance.cc index 5a5e7bf..b51c987 100644 --- a/src/oeaware_plugins/instance.cc +++ b/src/oeaware_plugins/instance.cc @@ -1,12 +1,11 @@ -#include "logs.h" +#include -#include "interface.h" +#include "logs.h" #include "tuner.h" -Logger __attribute__((visibility("hidden"))) logger("D-FOT"); +Logger __attribute__((visibility("hidden"))) dfot_logger("D-FOT"); -extern "C" int get_instance(struct Interface **interface) +extern "C" void GetInstance(std::vector> &interface) { - *interface = &sysboost_tuner; - return 1; + interface.emplace_back(std::make_shared()); } diff --git a/src/oeaware_plugins/tuner_sysboost.cc b/src/oeaware_plugins/tuner_sysboost.cc index 8bca214..cfab1fc 100644 --- a/src/oeaware_plugins/tuner_sysboost.cc +++ b/src/oeaware_plugins/tuner_sysboost.cc @@ -1,163 +1,163 @@ #include +#include + +#include +#include #include "logs.h" #include "utils.h" #include "configs.h" #include "records.h" -#include "interface.h" #include "opt.h" - -// 当前优化插件需要的采样数据来源于oeaware-collector采样实例PMU_CYCLES_SAMPLING -// 本插件不显式依赖该PMU_CYCLES_SAMPLING(因为可以预置profile来优化) -// 注意如果oeaware-collector仓库对应采样实例名字有变化时,此处也要同步修改 -#define PMU_CYCLES_SAMPLING "pmu_cycles_sampling" +#include "tuner.h" + +// 当前优化插件需要的采样数据来源于oeaware-manager采样实例pmu_sampling_collector +// 本插件通过订阅获取pmu_sampling_collector的采样数据,也可以预置profile来优化 +// 注意如果oeaware-manager仓库对应采样实例名字有变化时,此处也要同步修改 +#define DEP_INSTANCE_NAME "pmu_sampling_collector" +// 订阅性能事件 +#define DEP_TOPIC_NAME "cycles" // sysboost优化插件实例名 #define TUNER_INSTANCE_NAME "dfot_tuner_sysboost" -// 从collector获取ringbuf -void get_collector_ringbuf( - const struct Param *param, const struct DataRingBuf **ringbuf, uint64_t *cnt) +SysboostTuner::SysboostTuner() { - const struct DataRingBuf *buf = nullptr; - static int last_record_index = -1; // 记录上一次处理的ring_bufs下标 - static uint64_t last_record_count = 0; // 记录上一次处理时采集插件的运行次数 - - *ringbuf = nullptr; - *cnt = 0; - - // 如果插件无变化,可以快速找到对应param - if (last_record_index >= 0 && last_record_index < param->len && - param->ring_bufs[last_record_index] != nullptr && - strcmp(param->ring_bufs[last_record_index]->instance_name, PMU_CYCLES_SAMPLING) == 0) { - buf = param->ring_bufs[last_record_index]; - } else { - for (int i = 0; i < param->len; i++) { - if (param->ring_bufs[i] == nullptr) { - continue; - } - if (strcmp(param->ring_bufs[i]->instance_name, PMU_CYCLES_SAMPLING) == 0) { - buf = param->ring_bufs[i]; - last_record_index = i; - break; - } - } - } - - if (buf == nullptr) { - last_record_index = -1; - last_record_count = 0; - return; - } + // 基类参数 + name = TUNER_INSTANCE_NAME; + version = "1.0.0"; + description = "dfot tuner: sysboost"; + priority = 2; + type = oeaware::TUNE; + period = 1000; + + depTopic.instanceName = DEP_INSTANCE_NAME; + depTopic.topicName = DEP_TOPIC_NAME; + + processingArea = nullptr; + processingAreaSize = 0; +} - if (buf->count > last_record_count) { - // 数据有更新,注意DataBuf已经全部刷新的场景 - *ringbuf = buf; - *cnt = std::min(buf->count - last_record_count, (uint64_t)buf->buf_len); - last_record_count = buf->count; - } else if (buf->count < last_record_count) { - // 异常场景 - WARN("[run] record data count: " << last_record_count - << " is large than " << "current count: " << buf->count); - *ringbuf = nullptr; - last_record_count = 0; +SysboostTuner::~SysboostTuner() +{ + if (processingArea != nullptr) { + free(processingArea); + processingArea = nullptr; + processingAreaSize = 0; } } -void get_sampling_data_from_collector(const struct Param *param) +/// @brief 调优插件不需要打开topic +/// @param topic +/// @return +oeaware::Result SysboostTuner::OpenTopic(const oeaware::Topic &topic) { - const struct DataRingBuf *ringbuf = nullptr; - uint64_t cnt = 0; // 需要处理的DataBuf的个数,小于buf_len + (void)topic; + return oeaware::Result(OK); +} - int64_t start_ts = get_current_timestamp(); +/// @brief 调优插件不需要关闭topic +/// @param topic +void SysboostTuner::CloseTopic(const oeaware::Topic &topic) +{ + (void)topic; +} - get_collector_ringbuf(param, &ringbuf, &cnt); - if (ringbuf == nullptr || cnt == 0) { +/// @brief 处理依赖采集插件实例的新采样数据 +/// @param dataList 采样数据 +void SysboostTuner::UpdateData(const DataList &dataList) +{ + if (configs == nullptr) { + FATAL("[update] no valid configs found"); return; } - // 从ringbuf->index开始,倒序处理cnt个DataBuf,同时校验PmuData的ts; + static bool processing = false; + if (processing) { + DEBUG("[update] last processing is not finished, skip"); + return; + } + processing = true; + + int64_t start_ts = get_current_timestamp(); uint64_t total_samples = 0; - for (int i = 0; i < (int)cnt; i++) { - int index = (ringbuf->buf_len + ringbuf->index - i) % ringbuf->buf_len; - process_pmudata((struct PmuData *)(ringbuf->buf[index].data), ringbuf->buf[index].len); - total_samples += (uint64_t)ringbuf->buf[index].len; + for (unsigned long long i = 0; i < dataList.len; i++) { + PmuSamplingData *data = (PmuSamplingData *)(dataList.data[i]); + + // 复制一份采样数据到插件公共内存中,防止数据被覆盖, + // 如果内存不足,则重新申请内存 + if (processingArea == nullptr || + processingAreaSize < sizeof(PmuData) * data->len) { + if (processingArea != nullptr) { + free(processingArea); + } + processingArea = malloc(sizeof(PmuData) * data->len); + if (processingArea == nullptr) { + processingAreaSize = 0; + continue; + } + processingAreaSize = sizeof(PmuData) * data->len; + } + auto ret = memcpy_s( + processingArea, processingAreaSize, data->pmuData, sizeof(PmuData) * data->len); + if (ret != EOK) { + continue; + } + process_pmudata((PmuData *)processingArea, data->len); + total_samples += data->len; } records.processed_samples += total_samples; int64_t end_ts = get_current_timestamp(); - DEBUG("[run] processing pmudata cost: " << (end_ts - start_ts) << " ms, " + DEBUG("[update] processing pmudata cost: " << (end_ts - start_ts) << " ms, " << "current: " << total_samples << " samples, " << "total: " << records.processed_samples << " samples"); + processing = false; } -const char *sysboost_get_version() +/// @brief 使能调优插件实例 +/// @param param 预留参数 +/// @return +oeaware::Result SysboostTuner::Enable(const std::string ¶m) { - return "v1.0"; -} - -const char *sysboost_get_name() -{ - return TUNER_INSTANCE_NAME; -} - -const char *sysboost_get_description() -{ - return "dfot tuner: sysboost"; -} - -const char *sysboost_get_dep() -{ - // 本插件启动时,不依赖采样插件,兼容使用预置profile的场景 - // 本插件启动后,增加对PMU_CYCLES_SAMPLING的依赖,方便获取ringbuf数据 - // configs非空即表示插件已启动 - return configs != nullptr ? PMU_CYCLES_SAMPLING : nullptr; -} - -int sysboost_get_priority() -{ - return 0; -} - -int sysboost_get_type() -{ - return -1; -} - -// 每隔多少ms执行一次run -int sysboost_get_period() -{ - return configs != nullptr ? configs->tuner_check_period : 1000; -} - -bool sysboost_enable() -{ - logger.init(); + (void)param; + + dfot_logger.init(); if (configs == nullptr && parse_dfot_ini(DEFAULT_DFOT_CONFIG_PATH) != DFOT_OK) { ERROR("[enable] instance [" << TUNER_INSTANCE_NAME << "] init configs failed"); - return false; + return oeaware::Result(FAILED); } if (!check_configs_valid()) { ERROR("[enable] invalid configs"); - return false; + return oeaware::Result(FAILED); } if (!check_dependence_ready()) { ERROR("[enable] dependencies are not ready"); - return false; + return oeaware::Result(FAILED); } reset_records(); + if (Subscribe(depTopic).code != OK) { + ERROR("[enable] subscribe dep topic error"); + return oeaware::Result(FAILED); + } + INFO("[enable] plugin instance [" << TUNER_INSTANCE_NAME << "] enabled"); - return true; + return oeaware::Result(OK); } -void sysboost_disable() +/// @brief 禁用调优插件实例 +void SysboostTuner::Disable() { + if (Unsubscribe(depTopic).code != OK) { + ERROR("[disable] unsubscribe dep topic error"); + } + for (auto it = configs->apps.begin(); it != configs->apps.end(); ++it) { AppConfig *app = *it; if (app->status != OPTIMIZED) { @@ -167,20 +167,14 @@ void sysboost_disable() } cleanup_configs(); - INFO("[disable] plugin " << TUNER_INSTANCE_NAME << " disabled"); + INFO("[disable] instance [" << TUNER_INSTANCE_NAME << "] disabled"); } -const struct DataRingBuf *sysboost_get_ring_buf() +/// @brief 调优插件主逻辑 +void SysboostTuner::Run() { - // 调优插件不需要向其他插件提供数据 - return nullptr; -} - -void sysboost_run(const struct Param *param) -{ - // 1. 刷新采样数据 - // 2. 检查优化条件 - // 3. 获取profile,实施优化 + // 1. 检查优化条件 + // 2. 获取profile,实施优化 static bool optimizing = false; if (configs == nullptr) { @@ -196,9 +190,6 @@ void sysboost_run(const struct Param *param) optimizing = true; - // step1: 刷新采样数据 - get_sampling_data_from_collector(param); - for (auto it = configs->apps.begin(); it != configs->apps.end(); ++it) { AppConfig *app = *it; // step2: 检查应用是否满足优化条件 @@ -217,17 +208,3 @@ void sysboost_run(const struct Param *param) optimizing = false; } - -struct Interface sysboost_tuner = { - .get_version = sysboost_get_version, - .get_name = sysboost_get_name, - .get_description = sysboost_get_description, - .get_dep = sysboost_get_dep, - .get_priority = sysboost_get_priority, - .get_type = sysboost_get_type, - .get_period = sysboost_get_period, - .enable = sysboost_enable, - .disable = sysboost_disable, - .get_ring_buf = sysboost_get_ring_buf, - .run = sysboost_run, -}; \ No newline at end of file diff --git a/src/startup_opt.cc b/src/startup_opt.cc index 5b2ad9c..5abb16f 100644 --- a/src/startup_opt.cc +++ b/src/startup_opt.cc @@ -7,13 +7,11 @@ #include #include -#include "boost/filesystem.hpp" +#include -#include "libkperf/pmu.h" -#include "libkperf/symbol.h" +#include +#include -// D-FOT -#include "interface.h" #include "utils.h" #include "configs.h" #include "records.h" @@ -159,7 +157,7 @@ int dump_app_addrs_to_file(AppConfig *app) return DFOT_ERROR; } - // 当前仅处理PMU_CYCLES_SAMPLING数据,性能事件固定为cycles + // 当前仅处理pmu_sampling_collector数据,性能事件固定为cycles fprintf(fp, "cycles\n"); for (auto it = app->profile.addrs.begin(); it != app->profile.addrs.end(); ++it) { fprintf(fp, "%lx %d\n", it->first, it->second.count); @@ -265,7 +263,7 @@ void dump_app_profile_to_file(AppConfig *app) ERROR("[run] fopen " << app->collected_profile << " error"); return; } - // 当前仅处理PMU_CYCLES_SAMPLING数据,性能事件固定为cycles + // 当前仅处理pmu_sampling_collector数据,性能事件固定为cycles fprintf(fp, "no_lbr cycles:\n"); for (auto it1 = app->profile.funcs.begin(); it1 != app->profile.funcs.end(); ++it1) { for (auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2) { @@ -411,7 +409,7 @@ void process_pmudata(struct PmuData *data, int len) } for (AppConfig* app : updated_apps) { - DEBUG("[run] collected addrs for [" << app->app_name + DEBUG("[update] collected addrs for [" << app->app_name << ": " << app->instances.size() - 1 << "]: " << app->profile.addrs.size()); -- 2.39.5 (Apple Git-154)