Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion module/common/include/oops/str.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <algorithm>
#include <array>
#include <cstddef>
#include <limits>
Expand Down Expand Up @@ -217,7 +218,17 @@ std::string ToLower(std::string_view s) noexcept;
std::string ToUpper(std::string_view s) noexcept;

std::string Repeat(const std::string &str, std::size_t n);
std::string Elide(std::string_view s, std::size_t n);

template <typename Pred>
std::string RemoveIf(std::string_view s, Pred &&pred) {
std::string res{s};
res.erase(std::remove_if(res.begin(), res.end(), std::forward<Pred>(pred)), res.end());
return res;
}

inline std::string Remove(std::string_view s, std::string_view chars = SPACE) {
return RemoveIf(s, [&chars](char c) { return chars.find(c) != std::string_view::npos; });
}

// 后续使用lexcial_cast替代
template <typename T>
Expand Down
10 changes: 0 additions & 10 deletions module/common/src/str.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,4 @@ std::string Repeat(const std::string &str, std::size_t n) {
}
return res;
}

std::string Elide(std::string_view s, std::size_t n) {
if (s.size() <= n) {
return std::string{s};
}
if (n <= 3) {
return std::string(n, '.');
}
return std::string{s.substr(0, n - 3)} + "...";
}
} // namespace oops
4 changes: 2 additions & 2 deletions module/matrix/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ if(ENABLE_TEST)
target_link_libraries(oops_matrix_test_o PRIVATE oops_matrix_i gtest gmock)

# 用例路径定义
set(OOPS_CASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/test/case")
target_compile_definitions(oops_matrix_test_o PRIVATE "OOPS_CASE_DIR=\"${OOPS_CASE_DIR}\"")
set(OOPS_MATRIX_CASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/test/case")
target_compile_definitions(oops_matrix_test_o PRIVATE "OOPS_MATRIX_CASE_DIR=\"${OOPS_MATRIX_CASE_DIR}\"")

# 构建模块测试程序
add_executable(oops_matrix_test)
Expand Down
2 changes: 1 addition & 1 deletion module/matrix/test/test_matrix_market_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using namespace oops;
namespace fs = std::filesystem;

inline const fs::path CASE_DIR{OOPS_CASE_DIR};
inline const fs::path CASE_DIR{OOPS_MATRIX_CASE_DIR};

TEST(Coo, ReadCoo) {
std::ifstream iss(CASE_DIR / "m_coo_real_sym.mtx");
Expand Down
4 changes: 4 additions & 0 deletions module/profiling/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ if(ENABLE_TEST)
add_library(oops_profiling_test_o OBJECT ${TEST_SRC})
target_link_libraries(oops_profiling_test_o PRIVATE oops_profiling_i gtest)

# 用例路径定义
set(OOPS_PROFILING_CASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/test/case")
target_compile_definitions(oops_profiling_test_o PRIVATE "OOPS_PROFILING_CASE_DIR=\"${OOPS_PROFILING_CASE_DIR}\"")

# 构建模块测试程序
add_executable(oops_profiling_test)
set_target_properties(oops_profiling_test PROPERTIES OUTPUT_NAME test_profiling)
Expand Down
1 change: 1 addition & 0 deletions module/profiling/include/oops/system_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ struct Info {

[[nodiscard]] Info Get();
[[nodiscard]] Info Get(const FieldMask &field_mask);
[[nodiscard]] Info Get(std::istream &is);
[[nodiscard]] Info Get(std::istream &is, const FieldMask &field_mask);
std::ostream &operator<<(std::ostream &os, const Info &info);
} // namespace cpuinfo
Expand Down
85 changes: 49 additions & 36 deletions module/profiling/src/system_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ std::string GetCmdOutput(const std::string &cmd) {

// 解析和格式化字段的特化注册
template <typename T>
bool ParseField(std::string_view s, T &t, std::string_view ctx = "{}") {
bool ParseField(std::string_view s, T &t, std::string_view ctx) {
auto scan_res{scn::scan<T>(s, ctx)};
if (scan_res) {
t = scan_res->value();
Expand All @@ -51,28 +51,23 @@ bool ParseField(std::string_view s, T &t, std::string_view ctx = "{}") {
}

template <typename T>
std::string FormatField(const T &t, std::string_view ctx = "{}") {
std::string FormatField(const T &t, std::string_view ctx) {
return fmt::format(ctx, t);
}

// std::string特化:默认ctx升级为整行scanset,避免空格截断(如model name)
template <>
bool ParseField(std::string_view s, std::string &t, std::string_view ctx) {
auto scan_res{scn::scan<std::string>(s, ctx == "{}" ? std::string_view{"{:[^\n]}"} : ctx)};
if (scan_res) {
t = std::move(scan_res->value());
}
return bool{scan_res};
bool ParseField(std::string_view s, std::string &t, std::string_view) {
t = s;
return true;
}

// std::vector<std::string>特化:空格分割的标志列表(如cpuinfo的flags)
template <>
bool ParseField(std::string_view s, std::vector<std::string> &v, std::string_view) {
v.clear();
for (auto token : Split(s)) {
v.emplace_back(token);
}
return !v.empty();
return true;
}

template <>
Expand All @@ -89,37 +84,57 @@ std::string FormatField(const std::vector<std::string> &v, std::string_view) {
return s;
}

// bool特化:scn支持0/1/true/false,补充yes/no形式(如cpuinfo的fpu字段)
// bool特化,支持在ctx中定义代表true和false的字符串,例如"true/false"或"yes/no"
template <>
bool ParseField(std::string_view s, bool &b, std::string_view ctx) {
auto scan_res{scn::scan<bool>(s, ctx)};
if (scan_res) {
b = scan_res->value();
return true;
s = Strip(s);

// 默认值
std::string_view t{"1"};
std::string_view f{"0"};

auto pos{ctx.find('/')};
if (pos != std::string_view::npos) {
t = Strip(ctx.substr(0, pos));
f = Strip(ctx.substr(pos + 1));
}
std::string_view v{Strip(s)};
if (v == "yes") {

if (s == t) {
b = true;
return true;
}
if (v == "no") {
if (s == f) {
b = false;
return true;
}
return false;
}

template <>
std::string FormatField(const bool &b, std::string_view ctx) {
// 默认值
std::string_view t{"1"};
std::string_view f{"0"};

auto pos{ctx.find('/')};
if (pos != std::string_view::npos) {
t = Strip(ctx.substr(0, pos));
f = Strip(ctx.substr(pos + 1));
}
return std::string{b ? t : f};
}

// Storage特化
template <typename R, typename P>
bool ParseField(std::string_view s, Storage<R, P> &storage, std::string_view ctx = "{}") {
bool ParseField(std::string_view s, Storage<R, P> &storage, std::string_view ctx) {
R r{};
auto res{ParseField<R>(s, r, ctx)};
storage = Storage<R, P>{r};
return res;
}

template <typename R, typename P>
std::string FormatField(const Storage<R, P> &storage, std::string_view ctx = "{}") {
std::string FormatField(const Storage<R, P> &storage, std::string_view ctx) {
return FormatField(storage.Count(), ctx);
}

Expand Down Expand Up @@ -254,12 +269,11 @@ class KeyValueParser {
}

std::string_view value{Strip(line.substr(pos + 1))};
if (value.empty()) {
continue;
if (ParseMemberPtrVar(value, it->member_ptr_var, object, it->parse_ctx)) {
parsed |= it->field;
} else {
std::cerr << "Error: parse field '" << it->key << "' with value '" << value << "' failed" << std::endl;
}

ParseMemberPtrVar(value, it->member_ptr_var, object, it->parse_ctx);
parsed |= it->field;
if (parsed == field_mask) {
break; // 已解析全量
}
Expand All @@ -276,18 +290,15 @@ class KeyValueParser {
return parsed;
}

// key-value渲染不是表格,不做列对齐,统一规则:key + delim + 空格 + value(+ 空格 + suffix)
void Format(std::ostream &os, const Struct &object, const EnumBitset<Field> &field_mask = ~EnumBitset<Field>{}) {
for (const auto &entry : field_table_) {
if (field_mask.Test(entry.field)) {
std::string value{FormatMemberPtrVar(entry.member_ptr_var, object, entry.format_ctx)};
if (!value.empty()) {
os << entry.key << delim_ << ' ' << value;
if (!entry.suffix.empty()) {
os << ' ' << entry.suffix;
}
os << '\n';
os << entry.key << delim_ << ' ' << value;
if (!entry.suffix.empty()) {
os << ' ' << entry.suffix;
}
os << '\n';
}
}
}
Expand Down Expand Up @@ -585,10 +596,10 @@ KeyValueParser<
{Field::CPU_CORES, "cpu cores", &Entry::cpu_cores},
{Field::APICID, "apicid", &Entry::apicid},
{Field::INITIAL_APICID, "initial apicid", &Entry::initial_apicid},
{Field::FPU, "fpu", &Entry::fpu},
{Field::FPU_EXCEPTION, "fpu_exception", &Entry::fpu_exception},
{Field::FPU, "fpu", &Entry::fpu, "", "yes/no", "yes/no"},
{Field::FPU_EXCEPTION, "fpu_exception", &Entry::fpu_exception, "", "yes/no", "yes/no"},
{Field::CPUID_LEVEL, "cpuid level", &Entry::cpuid_level},
{Field::WP, "wp", &Entry::wp},
{Field::WP, "wp", &Entry::wp, "", "yes/no", "yes/no"},
{Field::FLAGS, "flags", &Entry::flags},
{Field::BUGS, "bugs", &Entry::bugs},
{Field::BOGOMIPS, "bogomips", &Entry::bogomips},
Expand All @@ -612,6 +623,8 @@ Info Get(std::istream &is, const FieldMask &field_mask) {

Info Get() { return Get(~FieldMask{}); }

Info Get(std::istream &is) { return Get(is, ~FieldMask{}); }

Info Get(const FieldMask &field_mask) {
std::ifstream ifs("/proc/cpuinfo");
return Get(ifs, field_mask);
Expand Down
54 changes: 54 additions & 0 deletions module/profiling/test/case/iZbp159dyz8itphnzxoylkZ/cpuinfo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 85
model name : Intel(R) Xeon(R) Platinum
stepping : 4
microcode : 0x1
cpu MHz : 2499.998
cache size : 33792 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 22
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch pti fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit mmio_stale_data retbleed gds bhi its
bogomips : 4999.99
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
power management:

processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 85
model name : Intel(R) Xeon(R) Platinum
stepping : 4
microcode : 0x1
cpu MHz : 2499.998
cache size : 33792 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 22
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch pti fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit mmio_stale_data retbleed gds bhi its
bogomips : 4999.99
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
power management:

Loading
Loading