分析序列化代码
Posted
技术标签:
【中文标题】分析序列化代码【英文标题】:Profiling serialization code 【发布时间】:2011-06-02 05:04:50 【问题描述】:我运行了我的应用程序两次(在 VS ide 中)。第一次用了 33 秒。我取消了 obj.save 的注释,它调用了很多代码并且花了 87 秒。那是一些缓慢的序列化代码!我怀疑有两个问题。首先是我做下面的
template<class T> void Save_IntX(ostream& o, T v) o.write((char*)&v,sizeof(T));
我将这个模板调用了数十万次(也许没有那么多)。每个 .write() 是否使用可能会减慢速度的锁?也许我可以使用不需要锁定的内存蒸汽并转储它?我可以使用哪个不锁定的 ostream,并且可能取决于它仅在单个线程中使用?
另一个可疑的问题是我经常使用 dynamic_cast。但我不确定我是否可以解决这个问题。
这是一个将其转换为使用 fopen 而不是 ostream 后的快速分析会话。我想知道为什么我在这个列表中没有看到我的大部分函数,但正如你所看到的,write 仍然花费了最长的时间。注意:我只是意识到我的输出文件是半个演出。哎呀。也许这就是原因。
【问题讨论】:
您是否尝试过使用 C I/O 库?它可以比 C++ I/O 库快得多。由于您实际上只是将字节复制到输出流(而不是进行任何格式化),因此转换代码并对其进行测试应该很简单。 @James:我试过了。它把它降低到 68 秒,但这仍然是相当长的。但我会再次分析,看看为什么它仍然很慢 我假设 fwrite/ntdll/dynamic cast 占了我 93% 的时间。 (虽然 33/68 是 48% 而不是 7%,这很奇怪)我会假设大部分性能问题是文件瓶颈,我真的不应该担心。我可能会考虑恢复到 ostream 并搜索单线程内存流并尝试一下。 戳@James。我对个人资料图表感到很困惑,但我想我能做的不多了? 这是一个优化的版本,对吧? (我猜是的,考虑到大量“未知帧”)您使用的是检测分析还是采样分析?但是,如果您的输出是半 GB,那么是的,我希望将这么多数据写入磁盘需要时间。 【参考方案1】:很高兴您能弄清楚,但下次您进行分析时,您可能需要考虑以下几点:
采样模式下的 VS 分析器不会在 I/O 期间或任何其他程序阻塞时进行采样,因此它仅对 CPU 密集型分析非常有用。例如,如果它说一个例程包含 80% 的时间,但应用程序实际上只计算了 10% 的时间,那么 80% 实际上只有 8%。因此,对于任何不受 CPU 限制的工作,您都需要使用分析器的检测模式。
假设您这样做了,在所有这些数据列中,重要的是“包含百分比”,因为这是例程的真实成本,如果可以避免,那就是多少总时间会减少。
在所有这些数据行中,可能重要的是包含您的例程的行,因为您的例程是唯一可以做任何事情的行。如果您的代码是在没有调试信息的情况下编译的,那么看起来“未知帧”可能是您的代码。一般来说,使用调试信息进行概要分析,使其快速,然后删除调试信息是一个好主意。
【讨论】:
通过调试信息,我假设您的意思是我自己的调试,而不是在调试模式下编译。 @acidzombie24:我的意思是分析器必须知道例程的名称和(最好)行号,就像调试器一样。以上是关于分析序列化代码的主要内容,如果未能解决你的问题,请参考以下文章
JSON反序列化泛型对象;泛型是变化的,如何写出通用代码?(源码分析)