- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个简单的基准测试来演示 busywait 线程的性能。它以两种模式运行:第一种模式简单地按顺序获取两个时间点,第二种模式遍历 vector 并测量迭代的持续时间。我看到 clock::now() 的两次连续调用平均需要大约 50 纳秒,通过 vector 的一次平均迭代需要大约 100 纳秒。但有时这些操作的执行会有很大的延迟:第一种情况大约 50 微秒,第二种情况 10 毫秒 (!)。
测试在单个独立核心上运行,因此不会发生上下文切换。我还在程序的开头调用了 mlockall,因此我假设页面错误不会影响性能。
还应用了以下其他优化:
环境:
System details:
Default Archlinux kernel:
5.1.9-arch1-1-ARCH #1 SMP PREEMPT Tue Jun 11 16:18:09 UTC 2019 x86_64 GNU/Linux
that has following PREEMPT and HZ settings:
CONFIG_HZ_300=y
CONFIG_HZ=300
CONFIG_PREEMPT=y
Hardware details:
RAM: 256GB
CPU(s): 28
On-line CPU(s) list: 0-27
Thread(s) per core: 1
Core(s) per socket: 14
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 79
Model name: Intel(R) Xeon(R) CPU E5-2690 v4 @ 2.60GHz
Stepping: 1
CPU MHz: 3200.011
CPU max MHz: 3500.0000
CPU min MHz: 1200.0000
BogoMIPS: 5202.68
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 35840K
NUMA node0 CPU(s): 0-13
NUMA node1 CPU(s): 14-27
示例代码:
struct TData
{
std::vector<char> Data;
TData() = default;
TData(size_t aSize)
{
for (size_t i = 0; i < aSize; ++i)
{
Data.push_back(i);
}
}
};
using TBuffer = std::vector<TData>;
TData DoMemoryOperation(bool aPerform, const TBuffer& aBuffer, size_t& outBufferIndex)
{
if (!aPerform)
{
return TData {};
}
const TData& result = aBuffer[outBufferIndex];
if (++outBufferIndex == aBuffer.size())
{
outBufferIndex = 0;
}
return result;
}
void WarmUp(size_t aCyclesCount, bool aPerform, const TBuffer& aBuffer)
{
size_t bufferIndex = 0;
for (size_t i = 0; i < aCyclesCount; ++i)
{
auto data = DoMemoryOperation(aPerform, aBuffer, bufferIndex);
}
}
void TestCycle(size_t aCyclesCount, bool aPerform, const TBuffer& aBuffer, Measurings& outStatistics)
{
size_t bufferIndex = 0;
for (size_t i = 0; i < aCyclesCount; ++i)
{
auto t1 = std::chrono::steady_clock::now();
{
auto data = DoMemoryOperation(aPerform, aBuffer, bufferIndex);
}
auto t2 = std::chrono::steady_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count();
outStatistics.AddMeasuring(diff, t2);
}
}
int Run(int aCpu, size_t aDataSize, size_t aBufferSize, size_t aCyclesCount, bool aAllocate, bool aPerform)
{
if (mlockall(MCL_CURRENT | MCL_FUTURE))
{
throw std::runtime_error("mlockall failed");
}
std::cout << "Test parameters"
<< ":\ndata size=" << aDataSize
<< ",\nnumber of elements=" << aBufferSize
<< ",\nbuffer size=" << aBufferSize * aDataSize
<< ",\nnumber of cycles=" << aCyclesCount
<< ",\nallocate=" << aAllocate
<< ",\nperform=" << aPerform
<< ",\nthread ";
SetCpuAffinity(aCpu);
TBuffer buffer;
if (aPerform)
{
buffer.resize(aBufferSize);
std::fill(buffer.begin(), buffer.end(), TData { aDataSize });
}
WaitForKey();
std::cout << "Running..."<< std::endl;
WarmUp(aBufferSize * 2, aPerform, buffer);
Measurings statistics;
TestCycle(aCyclesCount, aPerform, buffer, statistics);
statistics.Print(aCyclesCount);
WaitForKey();
if (munlockall())
{
throw std::runtime_error("munlockall failed");
}
return 0;
}
收到以下结果:第一:
StandaloneTests --run_test=MemoryAccessDelay --cpu=19 --data-size=280 --size=67108864 --count=1000000000 --allocate=1 --perform=0
Test parameters:
data size=280,
number of elements=67108864,
buffer size=18790481920,
number of cycles=1000000000,
allocate=1,
perform=0,
thread 14056 on cpu 19
Statistics: min: 16: max: 18985: avg: 18
0 - 10 : 0 (0 %): -
10 - 100 : 999993494 (99 %): min: 40: max: 117130: avg: 40
100 - 1000 : 946 (0 %): min: 380: max: 506236837: avg: 43056598
1000 - 10000 : 5549 (0 %): min: 56876: max: 70001739: avg: 7341862
10000 - 18985 : 11 (0 %): min: 1973150818: max: 14060001546: avg: 3644216650
第二个:
StandaloneTests --run_test=MemoryAccessDelay --cpu=19 --data-size=280 --size=67108864 --count=1000000000 --allocate=1 --perform=1
Test parameters:
data size=280,
number of elements=67108864,
buffer size=18790481920,
number of cycles=1000000000,
allocate=1,
perform=1,
thread 3264 on cpu 19
Statistics: min: 36: max: 4967479: avg: 48
0 - 10 : 0 (0 %): -
10 - 100 : 964323921 (96 %): min: 60: max: 4968567: avg: 74
100 - 1000 : 35661548 (3 %): min: 122: max: 4972632: avg: 2023
1000 - 10000 : 14320 (0 %): min: 1721: max: 33335158: avg: 5039338
10000 - 100000 : 130 (0 %): min: 10010533: max: 1793333832: avg: 541179510
100000 - 1000000 : 0 (0 %): -
1000000 - 4967479 : 81 (0 %): min: 508197829: max: 2456672083: avg: 878824867
任何想法是什么导致如此巨大的延误以及如何对其进行调查?
最佳答案
在:
TData DoMemoryOperation(bool aPerform, const TBuffer& aBuffer, size_t& outBufferIndex);
它返回一个 std::vector<char>
按值(value)。这涉及内存分配和数据复制。内存分配可以执行系统调用( brk
或 mmap
)和 memory mappings related syscalls are notorious for being slow .
当计时包括系统调用时,不能期望低方差。
您可能希望使用 /usr/bin/time --verbose <app>
运行您的应用程序或 perf -ddd <app>
查看页面错误和上下文切换的次数。
关于c++ - 运行简单代码时出现巨大的延迟峰值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56871923/
我通过在共享首选项中使用 GSON 将其转换为 json 来存储我的复杂对象。但是在检索它时,无法获得预期的字符串。 代码 这里 holderListCustomizationMap 是对象的复杂映射
因此,我正在尝试对大于可用RAM的gz压缩文件执行某种面向行的操作,因此排除了将其首先读取为字符串的情况。问题是,如何在rust(缺少gunzip file.gz|./my-rust-program)
我试图更好地理解为什么具有潜在大精度的大数字处理不一致,特别是在 JavaScript 及其本地化工具(例如 ECMA-402/Intl)中。我假设这与 float 的使用有关,但我想了解限制在哪里和
我们有一个 5GB 的 csv 文件,这是我们业务的主列表。 有多个类别,每个类别包含数千条记录。我们的目标是将每个类别导出为其自己的 csv 文件。 我们如何运行查询并导出数据? 运行 OSX。有没
基于上一个问题 ( see here ),我试图通过 xmlEventParse 读取许多大型 xml 文件,同时保存节点变化数据。使用此示例 xml:https://www.nlm.nih.gov/
我正在开发一个系统,它加载一个巨大的 CSV 文件(超过 100 万行)并保存到数据库中。每行也有超过一千个字段。 CSV 文件被视为一个批处理,每一行都被视为其子对象。在添加对象的过程中,每个对象都
借助node-google模块 我编写了一个简单的 Node 模块来为我的网络应用程序启用“文本网络搜索”功能,并在我的一个 View 中显示结果。 由于在来自同一 IP 的少量查询后 Google
我有相当大的 4D 阵列 [20x20x40x15000],我使用 h5py 将其作为 HDF5 文件保存到磁盘.现在的问题是我想计算整个数组的平均值,即使用: numpy.average(HDF5_
我在遗留代码库中连接巨大的 CString 时遇到问题。 CStrings 可以包含 base64 编码的文件,因此可能很大。在某些时候,这些 CString 会像这样连接起来: result +=
我正在尝试让我的服务器提供来自另一台服务器的巨大文件。但是,为了保护我的凭据免受该远程服务器的攻击,我不能简单地将请求者重定向到文件 url;另一方面,虽然使用 StreamingHttpRespon
感谢对此的任何见解,我有 2 个问题: 1) 弄清楚为什么我的本地数据库 oplog 庞大且不断增长 2) 安全删除(或重置)我的 local.oplog 以释放 18 GB 的浪费空间 场景:我一直
我的预期任务:获取大量数据(1 GB 及更多大小)json 字符串,操作(进行一些格式化、解析 json、重组 json 数据)并写入新格式化的 json 字符串作为响应。处理这种情况的更好方法是什么
我做了一个小的 Angular 4 应用程序,但我不知道如何应用 tree shaking 和 aot 编译。我运行的命令如下: ng build --prod --aot 但我得到的结果仍然很大,供
我是一名优秀的程序员,十分优秀!