Repository: google/filament
File: libs/utils/benchmark/benchmark_memcpy.cpp (C++)

Code before:
    };

    AlignedAllocator() noexcept = default;

    template<class U>
    explicit AlignedAllocator(const AlignedAllocator<U, Align>&) noexcept {}

    T* allocate(size_t const n) {
        size_t const bytes = n * sizeof(T);
        // std::aligned_alloc requires size to be a multiple of alignment.
        size_t const aligned_bytes = ((bytes + Align - 1) / Align) * Align;
        // Note: On Android (Bionic libc), this requires API Level 28+ (Android 9+)
        if (__builtin_available(android 28, *)) {
            void* ptr = std::aligned_alloc(Align, aligned_bytes);
            return static_cast<T*>(ptr);
        }
        return nullptr;
    }

    void deallocate(T* p, size_t) noexcept {
        std::free(p);
    }
};

template<typename T>
using PageAlignedVector = std::vector<T, AlignedAllocator<char, ALIGNMENT>>;

// ------------------------------------------------------------------------------------------------

static void BM_memcpy(benchmark::State& state) {
    // pinThreadToCore(7);
    int64_t const size = state.range(0);
    PageAlignedVector<char> src(size);
    PageAlignedVector<char> dst(size);

    // make all these pages resident
    memset(src.data(), 0, size);
    memset(dst.data(), 0, size);
    benchmark::ClobberMemory();

    {
        // PerformanceCounters const pc(state);
        for (auto _: state) {
            memcpy(dst.data(), src.data(), size);
            benchmark::DoNotOptimize(dst);
            benchmark::DoNotOptimize(src);
        }
    }
    state.SetBytesProcessed(int64_t(state.iterations()) * int64_t(size));
}


Review comment (suggestion):
```suggestion
using PageAlignedVector = std::vector<T, AlignedAllocator<T, ALIGNMENT>>;
```

Code after:
    struct rebind {
        using other = AlignedAllocator<U, Align>;
    };

    AlignedAllocator() noexcept = default;

    template<class U>
    explicit AlignedAllocator(const AlignedAllocator<U, Align>&) noexcept {}

    T* allocate(size_t const n) {
        size_t const bytes = n * sizeof(T);
        // std::aligned_alloc requires size to be a multiple of alignment.
        size_t const aligned_bytes = ((bytes + Align - 1) / Align) * Align;
        void* ptr = utils::aligned_alloc(aligned_bytes, Align);
        return static_cast<T*>(ptr);
    }

    void deallocate(T* p, size_t) noexcept {
        utils::aligned_free(p);
    }
};

template<typename T>
using PageAlignedVector = std::vector<T, AlignedAllocator<T, ALIGNMENT>>;

// ------------------------------------------------------------------------------------------------

static void BM_memcpy(benchmark::State& state) {
    // pinThreadToCore(7);
    int64_t const size = state.range(0);
    PageAlignedVector<char> src(size);
    PageAlignedVector<char> dst(size);

    // make all these pages resident
    memset(src.data(), 0, size);
    memset(dst.data(), 0, size);
    benchmark::ClobberMemory();

    {
        // PerformanceCounters const pc(state);
        for (auto _: state) {
            memcpy(dst.data(), src.data(), size);
            benchmark::DoNotOptimize(dst);
            benchmark::DoNotOptimize(src);
        }
    }
    state.SetBytesProcessed(int64_t(state.iterations()) * int64_t(size));
}

static void BM_memset(benchmark::State& state) {
    //pinThreadToCore(7);