如何(单元)测试一个函数是否无锁
How to (unit) test if a function is lock free ?
我想在我的代码中添加几个单元测试,也因为我加载插件,我并不总是能够访问我正在运行的代码。我真正想检查的测试是我调用的函数是否无锁?
是否有钩子或方法来测试在我的程序中的a点和B点之间是否调用了非锁自由函数?
另一个不太复杂的函数是如何挂钩所有调用锁定函数(如锁,系统调用…)。我知道如何在windows上挂钩调用malloc,但不知道其他。
谢谢你的帮助
你不能。
您可以替换pthread_lock
的不同实现,但代码可以直接调用例如futex
,如果您替换它,代码仍然可以直接调用syscall(SYS_futex,...)
。您可以分析代码或使用strace
之类的东西来检测所有此类调用,但这仍然不能告诉您代码是否在汇编中实现了自己的自定义自旋锁。
我很确定,如果不检测锁或类似的东西,您就无法做到这一点。
在测试中调用锁定函数会导致与生产代码中不同的行为(可能只有在启用"用于识别测试的特殊测试模式"时)的情况下会出现很多情况——例如,在lock方法中添加一个100ms的睡眠,然后尝试使用另一个锁定函数,并将时间与"无锁竞争"进行比较。
或者我们可以保留调用锁的计数,并查看函数之前和之后的计数是否相同(或者如果函数应该调用lock
一定次数,则增加了预期的数量)。
但是一种不侵入锁定机制的通用方法,我很确定这是不可能的。
当然,代码审查和关于哪些代码调用了锁,哪些代码没有调用锁的清晰文档也是有用的——好的审查者可以发现错误。正如其他人已经回答的那样,不可能测试该算法是否无锁。但是,可以测试它在多线程环境中的行为是否一致。我在这方面的经验是只使用无锁队列(这是我自己写的,但基于一篇学术论文),所以我的测试是基于一个队列,这可能对你有用,也可能对你没用。
我使用了多个线程来测试这个队列。
- 线程安全:队列不能在重载下崩溃
- 速度:在高负载下响应时间如何变化
- 一致性:队列不能丢失项目。
在我的测试中,我还改变了读者和作者的数量。队列的行为将根据读取器与写入器的比例而有所不同。读数多于写数通常会导致队列几乎为空,反之则会导致队列不断扩大,直到写数停止写入。
第2点可能会引起您的兴趣,因为您可以根据负载下响应时间的变化来判断算法是否无锁。如果响应时间在高负载下保持快速,则可以推断该算法是无锁的。或者至少,如果它不是,它就会按照它是。
- 函数是否可以访问传递给main()的参数
- 根据某个函数是否存在启用模板
- 无论如何,我可以确定构造函数是否存在吗?
- 在 nullptr 上调用无状态类的非静态成员函数是否合法?
- 如何检查函数是否在LLVM Instrumentation pass的ModulePass的系统头文件中定义?
- 如果 C 函数仍然可以间接执行(通过回调函数),那么将它声明为静态函数是否是一种不好的做法?
- 在对象构造期间,将指向尚未构造的子对象的指针传递给另一个子对象的构造函数是否危险?
- 某些 boost::asio 异步函数是否将处理程序连接到操作,以便处理程序被触发一次?
- 调用 erase() 函数是否也会在擦除元素之前更改迭代器值?
- 由并发无序映射查找线程调用的函数是否安全?
- 使用静态成员函数而不是普通函数是否有任何开销?
- 从其存储的回调中删除 std::函数是否安全
- 析构函数是否会自动调用 delete[] C++?
- 构造函数是否有一种现代C++方法来了解其'container'类?
- 循环中本地对象的析构函数是否保证在下一次迭代之前被调用?
- 移动构造函数是否C++过时?
- 在 c++ 中将对象设置为等于同一类的构造函数是否有效?
- 此函数是否会在C++中创建内存泄漏?
- 具有默认值的单个参数构造函数是否与默认构造函数相同?
- 如何检测构造函数是否与抛出的析构函数无关