为什么chrome://tracing的两个函数重叠在一起
为什么chrome://tracing的两个函数重叠在一起,有没有大佬帮我看看代码如下:
// #include "HeaderFolder\Timer.h"
#include <iostream>
#include <string>
#include <chrono>
#include <algorithm>
#include <fstream>
#include <cmath>
#include <thread>
struct ProfileResult
{
std::string Name;
long long Start, End;
uint32_t ThreadID;
};
struct InstrumentationSession
{
std::string Name;
};
struct Instrumentor
{
private:
InstrumentationSession* m_CurrentSession;
std::ofstream m_OutpuyStream;
int m_ProfileCount;
public:
Instrumentor()
: m_CurrentSession(nullptr), m_ProfileCount(0)
{
}
void BeginSession(const std::string& name, const std::string& filepath = "results.json")
{
m_OutpuyStream.open(filepath);
WriteHeader();
m_CurrentSession = new InstrumentationSession{ name };
}
void EndSession()
{
WriteFooter();
m_OutpuyStream.close();
delete m_CurrentSession;
m_CurrentSession = nullptr;
m_ProfileCount = 0;
}
void WriteProfile(const ProfileResult& result)
{
if (m_ProfileCount++ > 0)
m_OutpuyStream << ",";
std::string name = result.Name;
std::replace(name.begin(), name.end(), '"', '\'');
m_OutpuyStream << "{";
m_OutpuyStream << "\"cat\":\"function\",";
m_OutpuyStream << "\"dur\":" << (result.End - result.Start) << ",";
m_OutpuyStream << "\"name\":\"" << name << "\",";
m_OutpuyStream << "\"ph\":\"X\",";
m_OutpuyStream << "\"pid\":0,";
m_OutpuyStream << "\"tid\":" << result.ThreadID << ",";
m_OutpuyStream << "\"ts\":" << result.Start;
m_OutpuyStream << "}";
m_OutpuyStream.flush();
}
void WriteHeader()
{
m_OutpuyStream << "{\"otherData\": {},\"traceEvents\":[";
m_OutpuyStream.flush();
}
void WriteFooter()
{
m_OutpuyStream << "]}";
m_OutpuyStream.flush();
}
static Instrumentor& Get()
{
static Instrumentor* instance = new Instrumentor();
return *instance;
}
};
class InstrumentationTimer
{
public:
InstrumentationTimer(const char* name)
: m_Name(name), m_Stopped(false)
{
m_StartTimepoint = std::chrono::high_resolution_clock::now();
}
~InstrumentationTimer()
{
if (!m_Stopped)
Stop();
}
void Stop()
{
auto endTimepoint = std::chrono::high_resolution_clock::now();
long long start = std::chrono::time_point_cast<std::chrono::milliseconds>(m_StartTimepoint).time_since_epoch().count();
long long end = std::chrono::time_point_cast<std::chrono::milliseconds>(endTimepoint).time_since_epoch().count();
uint32_t threadID = std::hash<std::thread::id>{}(std::this_thread::get_id());
Instrumentor::Get().WriteProfile({ m_Name, start, end, threadID });
m_Stopped = true;
}
private:
const char* m_Name;
std::chrono::high_resolution_clock::time_point m_StartTimepoint; // std::chrono::high_resolution_clock::time_point | std::chrono::time_point<std::chrono::steady_clock>
bool m_Stopped;
};
#define PROFING true
#if PROFING
#define PROFILE_SCOPE(name) InstrumentationTimer timer##__LINE__(name)
#define PROFILE_FUNCTION() PROFILE_SCOPE(__FUNCSIG__)
#else
#define PROFILE_SCOPE(name)
#endif
namespace Benchmark {
void PrintFunction(int value)
{
PROFILE_FUNCTION();
for (int i = 0; i < 1000; i++)
std::cout << "Hello World! #" << (i + value) << std::endl;
}
void PrintFunction()
{
PROFILE_FUNCTION();
for (int i = 0; i < 1000; i++)
std::cout << "Hello World! #" << sqrt(i) << std::endl;
}
void RunBenchmarks()
{
PROFILE_FUNCTION();
std::cout << "Running Banchmarks...\n";
PrintFunction(2);
PrintFunction();
}
}
int main()
{
Instrumentor::Get().BeginSession("Profile");
Benchmark::RunBenchmarks();
Instrumentor::Get().EndSession();
std::cin.get();
}
还有这个生成的json文件:
{
"otherData": {},
"traceEvents": [
{
"cat": "function",
"dur": 86,
"name": "void __cdecl Benchmark::PrintFunction(int)",
"ph": "X",
"pid": 0,
"tid": 3404007327,
"ts": 14619163
},
{
"cat": "function",
"dur": 123,
"name": "void __cdecl Benchmark::PrintFunction(void)",
"ph": "X",
"pid": 0,
"tid": 3404007327,
"ts": 14619249
},
{
"cat": "function",
"dur": 209,
"name": "void __cdecl Benchmark::RunBenchmarks(void)",
"ph": "X",
"pid": 0,
"tid": 3404007327,
"ts": 14619163
}
]
}
这个json文件中有两个的“ts”时一样的!!!
怎么解决这个问题?急!
file:///D:/lixxl/Pictures/Screenshots/Screenshot%202024-07-24%20145010.png
{:10_266:}
首先,欢迎来到鱼油的编程小课堂!我们今天要聊聊在 `chrome://tracing` 中看到的函数重叠现象。这就像糖果铺里你一不小心把两个糖捏在一起了,结果吃起来怪怪的。
根据你提供的代码,描述了一个简单的性能分析工具。对`ProfileResult`结构体来说,每次测量的开始和结束时间是关键。问题可能出现在以下几个方面:
1. **时间戳不准确**:如果计算开始 (`Start`) 和结束 (`End`) 时间的代码逻辑有问题,比如调用顺序错误或者没有正确记录时间,就会导致多个函数的时间戳重叠。
2. **没有足够的分隔**:如果在记录每个函数执行的过程时,没有为每个函数创建单独的 `ProfileResult` 实例,可能会将多个函数的执行结果写到同一个记录中,从而在最终输出时导致重叠。
3. **并发执行**:如果你的函数是多线程执行的,而你没有为每个线程的执行结果设置适当的锁或管理机制,这样多个线程的执行记录可能会交错在一起,表现为重叠。
4. **WriteProfile方法缺失**:你提供的代码片段在 `WriteProfile` 方法的实现上似乎没完整展示,确保这个方法能够正确地将每个函数的执行信息写入输出流中。如果这里没搞清楚,重叠问题就会出现。
修复这个问题的建议:
- 确保你在记录 `Start` 和 `End` 时使用的是准确的时间获取方法(比如用高精度计时器)。
- 确保每个测量都生成新的 `ProfileResult`,并且在写入时做好数据管理。
- 如果涉及多线程,看看是否需要加锁来防止数据竞争。
总之,要想在 `chrome://tracing` 中看到无重叠的函数表现,就像想要在糖果铺里找到完好无损的糖果,一定要注意细节哦!希望这些小建议能帮助到你,如果还有问题,随时问我!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-7-24 15:02
首先,欢迎来到鱼油的编程小课堂!我们今天要聊聊在 `chrome://tracing` 中看到的函数重叠现象。这就像糖果 ...
有代码吗 Sky天曰 发表于 2024-07-24 16:15
有代码吗
当然可以!下面是一个简化版的 `InstrumentationSession` 和 `Instrumentor` 的代码示例,加入了一些细节以帮助你避免函数重叠的问题。我们还补充了 `WriteProfile` 的完整实现和线程安全性考虑。
#include <iostream>
#include <fstream>
#include <string>
#include <chrono>
#include <mutex>
struct ProfileResult {
std::string Name;
long long Start, End;
uint32_t ThreadID;
};
struct InstrumentationSession {
std::string Name;
};
class Instrumentor {
private:
InstrumentationSession* m_CurrentSession;
std::ofstream m_OutputStream;
int m_ProfileCount;
std::mutex m_Mutex; // 用于多线程保护
public:
Instrumentor()
: m_CurrentSession(nullptr), m_ProfileCount(0) {}
void BeginSession(const std::string& name, const std::string& filepath = "results.json") {
std::lock_guard<std::mutex> lock(m_Mutex); // 保护代码块
m_OutputStream.open(filepath);
WriteHeader();
m_CurrentSession = new InstrumentationSession{ name };
}
void EndSession() {
std::lock_guard<std::mutex> lock(m_Mutex); // 保护代码块
WriteFooter();
m_OutputStream.close();
delete m_CurrentSession;
m_CurrentSession = nullptr;
m_ProfileCount = 0;
}
void WriteProfile(const ProfileResult& result) {
std::lock_guard<std::mutex> lock(m_Mutex); // 保护代码块
if (m_ProfileCount++ > 0) {
m_OutputStream << ",";
}
m_OutputStream << "{";
m_OutputStream << "\"name\":\"" << result.Name << "\",";
m_OutputStream << "\"cat\":\"function\",";
m_OutputStream << "\"ph\":\"X\",";
m_OutputStream << "\"ts\":" << result.Start << ",";
m_OutputStream << "\"dur\":" << (result.End - result.Start) << ",";
m_OutputStream << "\"pid\":0,";
m_OutputStream << "\"tid\":" << result.ThreadID;
m_OutputStream << "}";
}
private:
void WriteHeader() {
m_OutputStream << "[";
}
void WriteFooter() {
m_OutputStream << "]";
}
};
// 使用示例
void FunctionToProfile(Instrumentor& instrumentor) {
auto start = std::chrono::high_resolution_clock::now();
// 假设这里是要测量的代码
std::this_thread::sleep_for(std::chrono::milliseconds(100));
auto end = std::chrono::high_resolution_clock::now();
long long startTime = std::chrono::duration_cast<std::chrono::microseconds>(start.time_since_epoch()).count();
long long endTime = std::chrono::duration_cast<std::chrono::microseconds>(end.time_since_epoch()).count();
instrumentor.WriteProfile({ "FunctionToProfile", startTime, endTime, std::this_thread::get_id() });
}
int main() {
Instrumentor instrumentor;
instrumentor.BeginSession("Profile Session");
// 这里可以启动多个线程来测试
FunctionToProfile(instrumentor);
instrumentor.EndSession();
return 0;
}
### 代码解释:
1. **多线程保护**:用 `std::mutex` 来确保在多线程环境下写入文件时不会发生数据竞争。
2. **时间戳的获取**:使用高分辨率时钟捕获开始和结束时间,并计算出持续时间,以防止函数重叠。
3. **`WriteProfile` 方法**:正确地格式化每个函数的执行结果并写入输出流,这将有助于降低输出重叠的风险。
在实际应用中,确保你调用 `BeginSession` 和 `EndSession` 的时候要匹配,并在它们之间的代码段使用 `WriteProfile` 来记录各个函数的执行情况。
希望这个代码示例能帮助你清晰地理解如何避免函数重叠问题!如果还有疑问,随时问我!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
[1]