Android NDK : vector. resize() 太慢,与分配有关?

标签 android c++ android-ndk

我在 Android NDK 中遇到了非常奇怪的事情。

我有一个循环

#include <chrono>
#include <android/log.h>
#include <vector>

while (true)
    {
        const int sz = 2048*2048*3;
        std::vector<unsigned char> v;
        {
            auto startTime = std::chrono::system_clock::now();
            v.resize(sz);
            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - startTime);
            __android_log_print(ANDROID_LOG_ERROR, "READFILE 1", "v.resize(%d) time : %lld\n", sz, duration.count());
        }
        {
            auto startTime = std::chrono::system_clock::now();
            v.resize(0);
            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - startTime);
            __android_log_print(ANDROID_LOG_ERROR, "READFILE 2", "v.resize(0) time : %lld\n", duration.count());
        }
        {
            auto startTime = std::chrono::system_clock::now();
            v.resize(sz);
            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - startTime);
            __android_log_print(ANDROID_LOG_ERROR, "READFILE 3", "v.resize(%d) time : %lld\n", sz, duration.count());
        }
    }

我得到了一个日志:

34.4171: v.resize(12582912) time : 845977
34.9682: v.resize(0) time : 550995
35.5293: v.resize(12582912) time : 561165
36.6121: v.resize(12582912) time : 530845
37.1612: v.resize(0) time : 548528
37.7183: v.resize(12582912) time : 556559
38.7811: v.resize(12582912) time : 515162
39.3312: v.resize(0) time : 550630
39.8883: v.resize(12582912) time : 556319
40.9711: v.resize(12582912) time : 530739
41.5182: v.resize(0) time : 546654
42.0733: v.resize(12582912) time : 554924
43.1321: v.resize(12582912) time : 511659
43.6802: v.resize(0) time : 547084
44.2373: v.resize(12582912) time : 557001
45.3201: v.resize(12582912) time : 530313

所以,首先

  1. 如您所见,仅 resize(0) 就花费了 550 毫秒...应该是 最多 1 微秒而非 MILLI
  2. 其次,为什么 resize(size) 再次需要 550 毫秒 如果 vector 的容量没有改变?

这是两个非常奇怪的行为。

如果您不相信我,欢迎您自行查看这段代码:)但只需在 Android NDK 上查看,而不是 Visual Studio项目,因为它在那里可以正常工作。

看起来确实像bug...

或者我做错了什么?

编辑

我检查了如果转到 resize() 方法,我会进入这样的循环

template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
void
__vector_base<_Tp, _Allocator>::__destruct_at_end(pointer __new_last) _NOEXCEPT
{
    pointer __soon_to_be_end = __end_;
    while (__new_last != __soon_to_be_end)
        __alloc_traits::destroy(__alloc(), _VSTD::__to_raw_pointer(--__soon_to_be_end));
    __end_ = __new_last;
}

因此,这意味着有一个循环遍历调整大小范围内的每个元素并调用 destroy

如果你持有的不是具有析构函数的平凡对象,那么没有问题,但是如果你持有 vector (就像我的例子) int 对象,这些对象是平凡的并且它们没有析构函数,所以......这是非常奇怪的行为,如何从实际上没有析构函数的对象调用析构函数?

看起来像是编译器错误吗?

最佳答案

首先,许多库功能的实现强烈依赖于编译器优化。删除容器中的对象可以调用 destroy ,而对于普通可破坏的对象则不会执行任何操作。如果它什么都不做,那么所有逻辑都将被编译器优化掉。 STL 中销毁对象涉及大量逻辑,just take a look 。本质上调用 destroy 是为了确保它处理所有情况,包括自定义分配器。它必须进行编译,因此对于普通类型,它必须解析为已定义的内容,并且不执行任何操作仍然是已定义的内容。只是让代码尽可能干净。单一职责,释放器决定如何以及是否需要销毁对象。

至于您的主要问题,您使用优化吗?这是第一个也是最重要的问题。任何未经优化的代码都只能保证可以工作。对于未优化的代码,即使引用提供的复杂性也可能不同。可以清楚地看到第一次重新分配花费了几乎两倍的时间,其余的都相当稳定。

您在进行此类其他操作时是否有更好的体验?您是否尝试过与普通数组性能进行比较?

关于Android NDK : vector. resize() 太慢,与分配有关?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58745415/

相关文章:

java - 即使实例化后静态字段仍为空

java - 无法访问 Activity 内的成员对象

android - Cordova 没有找到avd

c++ - 参数包的递归迭代

c++ - 访问冲突读取位置 fprintf

Android 库 : java. lang.UnsatisfiedLinkError:dlopen 失败:找不到库 "libgnuSTL_shared.so"

android - 错误 : requestFeature() must be called before adding content - Still won't work

android - 如何在Android中存储 token ?

c++ - 哈希示例 - 多余的代码

Android Ndk 重复文件异常