【C++项目】高并发内存池项目第七讲多线程并发执行情况下的性能分析以及复杂问题的调试技巧

000000

项目源代码:高并发内存池

1.调试代码及分析

#include"ConcurrentAlloc.h"
#include"ObjectPool.h"
#include"Common.h"
void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
	std::vector<std::thread> vthread(nworks);
	std::atomic<size_t> malloc_costtime(0);
	std::atomic<size_t> free_costtime(0);
	for (size_t k = 0; k < nworks; ++k)
	{
		vthread[k] = std::thread([&, k]() {
			std::vector<void*> v;
			v.reserve(ntimes);
			for (size_t j = 0; j < rounds; ++j)
			{
				size_t begin1 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					//v.push_back(malloc(16));
					v.push_back(malloc((16 + i) % 8192 + 1));
				}
				size_t end1 = clock();
				size_t begin2 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					free(v[i]);
				}
				size_t end2 = clock();
				v.clear();
				malloc_costtime += (end1 - begin1);
				free_costtime += (end2 - begin2);
			}
			});
	}
	for (auto& t : vthread)
	{
		t.join();
	}
	printf("%u个线程并发执行%u轮次,每轮次malloc %u次: 花费:%u ms\n",
		nworks, rounds, ntimes, malloc_costtime.load());
	printf("%u个线程并发执行%u轮次,每轮次free %u次: 花费:%u ms\n",
		nworks, rounds, ntimes, free_costtime.load());
	printf("%u个线程并发malloc&free %u次,总计花费:%u ms\n",
		nworks, nworks * rounds * ntimes, malloc_costtime.load() + free_costtime.load());
}
// 单轮次申请释放次数 线程数 轮次
void BenchmarkConcurrentMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
	std::vector<std::thread> vthread(nworks);
	std::atomic<size_t> malloc_costtime(0);
	std::atomic<size_t> free_costtime (0);
	for (size_t k = 0; k < nworks; ++k)
	{
		vthread[k] = std::thread([&]() {
			std::vector<void*> v;
			v.reserve(ntimes);
			for (size_t j = 0; j < rounds; ++j)
			{
				size_t begin1 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					//v.push_back(ConcurrentAlloc(16));
					v.push_back(ConcurrentAlloc((16 + i) % 8192 + 1));
				}
				size_t end1 = clock();
				size_t begin2 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					ConcurrentFree(v[i]);
				}
				size_t end2 = clock();
				v.clear();
				malloc_costtime += (end1 - begin1);
				free_costtime += (end2 - begin2);
			}
			});
	}
	for (auto& t : vthread)
	{
		t.join();
	}
	printf("%u个线程并发执行%u轮次,每轮次concurrent alloc %u次: 花费:%u ms\n",
		nworks, rounds, ntimes, malloc_costtime.load());
	printf("%u个线程并发执行%u轮次,每轮次concurrent dealloc %u次: 花费:%u ms\n",
		nworks, rounds, ntimes, free_costtime.load());
	printf("%u个线程并发concurrent alloc&dealloc %u次,总计花费:%u ms\n",
		nworks, nworks * rounds * ntimes, malloc_costtime.load() + free_costtime.load());
}
int main()
{
	size_t n = 10000;
	cout << "==========================================================" << endl;
		
	BenchmarkConcurrentMalloc(n, 4, 10);
	cout << endl << endl;
	BenchmarkMalloc(n, 4, 10);
	cout << "==========================================================" << endl;
		
	return 0;
}

创建了4个进程,每个进程执行10轮次,每次申请释放1w次,分析自己实现的内存池和系统提供的malloc、free之间的性能差距。

  • 运行结果:
    000

1.2VS下性能工具分析

链接: VS性能分析工具介绍
00
0

2.复杂问题的调试技巧

2.1调用堆栈

00在打了断点情况下去调试,可以调出函数的调用堆栈,通过调用堆栈可以查看函数的前后调用关系。
02
可以看看这篇博客: C语言–调用堆栈及栈区内存使用

2.2条件断点

条件断点是一种在代码调试过程中使用的调试工具,它允许在满足特定条件时中断程序的执行,而不仅仅是在达到特定代码行时中断。条件断点对于帮助程序员诊断和解决问题非常有用,特别是在复杂的应用程序中。

以下是条件断点的一些关键特点和用途:

中断条件:条件断点允许您指定一个中断触发的条件。这通常是一个布尔表达式,当该表达式的值为真时,程序执行会中断。例如, 可以在循环中设置条件断点,以便在循环的第10次迭代时中断。

条件断点的位置:条件断点可以设置在代码的特定行或特定函数的入口处。它可以帮助 精确定位需要调试的代码部分。

日志和操作:一些调试工具允许 在条件断点触发时记录日志或执行自定义操作。这对于收集调试信息或执行特定操作以诊断问题非常有用。

计数条件断点: 还可以设置条件断点以在满足特定条件的情况下中断,例如当某个计数器达到指定值时。这对于跟踪迭代或事件发生次数非常有用。

临时条件断点:一些调试器允许您设置临时条件断点,这意味着它们只会在一次触发后自动删除,而不会影响以后的执行。

忽略计数: 可以设置条件断点,使其在满足条件时连续中断多次,或者在满足条件后中断一次后自动忽略后续的满足条件。

条件断点在以下情况下非常有用:

当 希望在特定情况下中断程序执行,例如找到数组中的特定值或在某个变量达到特定值时。
当 希望追踪特定事件的发生次数,以便诊断问题或优化性能。
当 需要记录某些状态或信息以帮助调试。
使用条件断点可以显著提高调试的效率,因为它允许 仅在特定条件下中断程序,而不是每次执行都中断。这有助于减少调试的干扰,同时更快地解决问题。不同的集成开发环境(IDE)和调试器提供条件断点的不同实现方式,但通常都有类似的功能。

  • 实例
    当使用条件断点时, 可以设置中断条件来根据特定的条件来触发断点。这是一个示例,演示如何在C++中使用条件断点来中断程序的执行:

假设 有一个简单的C++程序,它计算斐波那契数列,并且 想要在计算到第n个斐波那契数时中断程序的执行。

#include <iostream>

int Fibonacci(int n) {
    if (n <= 1) {
        return n;
    }
    return Fibonacci(n - 1) + Fibonacci(n - 2);
}

int main() {
    int n = 10;  // 设置要计算的斐波那契数的位置
    int result = Fibonacci(n);
    std::cout << "Fibonacci(" << n << ") = " << result << std::endl;
    return 0;
}

现在,假设 希望在计算到第5个斐波那契数时中断程序的执行。使用条件断点, 可以执行以下步骤:

在 的集成开发环境(IDE)中,打开源文件,并找到Fibonacci函数的调用,即 Fibonacci(n)。

在该行代码上设置条件断点。具体设置方法因IDE而异,但通常右键单击该行代码,选择 “添加条件断点” 或类似选项。

在条件断点设置对话框中,输入中断条件,例如 n == 5。这将使程序在 n 的值等于5时中断。

运行程序。当程序执行到第5个斐波那契数的计算时,它将中断执行,让 检查程序状态和调试问题。

这就是一个简单的例子,演示如何使用条件断点来在满足特定条件时中断程序的执行。 可以根据 的需要定义更复杂的中断条件,以帮助诊断和解决问题。条件断点是调试复杂应用程序时的强大工具,因为它们可以帮助 仅在特定情况下中断程序,而不是每次执行都中断。

调试技巧相关博客:
链接: VS断点调试技巧

本篇博客就介绍到这,创作不易点赞支持~
0

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值