(fwData): improve the API of ::fwData::Array
What does this MR do?
Simplifies Array API by moving the methods from the helper to the data itself:
- deprecate
::fwDataTools::helper::Array
- integrate the useful methods from the helper to ::fwData::Array
- deprecate the component attribute
- add
Iterators<Type>
andConstIterator<Type>
to iterate through the array buffer
How to test it?
- Launch
fwDataTest
to check the new API. - Launch all the unit tests and applications to check that the old API is not broken.
Some results
I made some benchmark for the iterators. In Debug, it is 3 times less performant that iterating on the buffer itself because the iterator methods are not properly inlined. In Release, it take the same time.
Tested code
Click to expand
::fwData::Array::sptr array = ::fwData::Array::New();
::fwData::Array::SizeType size = {512, 512, 512};
//::fwData::Array::SizeType size = {1000, 1000, 1000};
array->resize(size, ::fwTools::Type::s_UINT32, true);
auto lock = array->lock();
std::fill(array->begin<std::uint32_t>(), array->end<std::uint32_t>(), 0);
::fwDataTools::helper::Array helper(array);
std::uint32_t count = 0;
double dt1 = 0;
double dt2 = 0;
double dt3 = 0;
double dt4 = 0;
const size_t NB_ITERATION = 15;
const size_t NB_ELTS = array->getNumberOfElements();
std::vector<std::uint32_t> vect(NB_ELTS, 0);
std::vector<std::array<double, 4> > results;
for (size_t i = 0; i < NB_ITERATION; ++i)
{
const auto t0 = ::fwCore::HiResClock::getTimeInMilliSec();
count = 0;
{
auto buff = helper.begin<std::uint32_t>();
const auto buffEnd = helper.end<std::uint32_t>();
for(; buff != buffEnd; ++buff)
{
*buff = ++count;
}
}
const auto t1 = ::fwCore::HiResClock::getTimeInMilliSec();
count = 0;
{
auto iter = array->begin<std::uint32_t>();
const auto endItr = array->end<std::uint32_t>();
for(; iter != endItr; ++iter)
{
*iter = ++count;
}
}
const auto t2 = ::fwCore::HiResClock::getTimeInMilliSec();
count = 0;
{
auto buff = helper.begin<std::uint32_t>();
for (size_t i = 0; i < NB_ELTS; ++i)
{
*buff = ++count;
++buff;
}
}
const auto t3 = ::fwCore::HiResClock::getTimeInMilliSec();
count = 0;
{
auto iter = array->begin<std::uint32_t>();
for (size_t i = 0; i < NB_ELTS; ++i)
{
*iter = ++count;
++iter;
}
}
const auto t4 = ::fwCore::HiResClock::getTimeInMilliSec();
const auto d1 = t1-t0;
const auto d2 = t2-t1;
const auto d3 = t3-t2;
const auto d4 = t4-t3;
dt1 += d1;
dt2 += d2;
dt3 += d3;
dt4 += d4;
const std::array<double, 4> d = {d1, d2, d3, d4};
results.push_back(d);
}
dt1 /= NB_ITERATION;
dt2 /= NB_ITERATION;
dt3 /= NB_ITERATION;
dt4 /= NB_ITERATION;
std::stringstream str;
str << "| buffer `for(buff!=buffEnd...)` | iterator `for(it != itEnd...)` | buffer `for(i...)` | iterator for(i ...)` |";
str << "\n| ------------------------------ | ------------------------------ | ------------------ | -------------------- |";
for (const auto& res: results)
{
str << "\n| " <<
std::setw(30) << std::setfill(' ') << res[0] << " | " <<
std::setw(30) << std::setfill(' ') << res[1] << " | " <<
std::setw(18) << std::setfill(' ') << res[2] << " | " <<
std::setw(20) << std::setfill(' ') << res[3] << " | ";
}
str << "\n| ------------------------------ | ------------------------------ | ------------------ | -------------------- |";
str << "\n| " <<
std::setw(30) << std::setfill(' ') << dt1 << " | " <<
std::setw(30) << std::setfill(' ') << dt2 << " | " <<
std::setw(18) << std::setfill(' ') << dt3 << " | " <<
std::setw(20) << std::setfill(' ') << dt4 << " | ";
OSLM_LOG("total duration: \n" << str.str());
Sight project to execute the benchmark on your PC
Results
array 512x512x512 | without iterator buff != buffEnd
|
iterator it != itEnd
|
array for i...
|
iterator for i ...
|
---|---|---|---|---|
Debug (Linux) | ~221.267 ms | ~626.467 ms | ~253.467 ms | ~458 ms |
Debug (Linux) with asserts | ~222.133 ms | ~725 ms | ~251.8 ms | ~608.333 ms |
Release (Linux) | ~42.5333 ms | ~42.0667 ms | ~42.2 ms | ~45.6667 ms |
Debug (macOS) | ~287.533 ms | ~1039.33 ms | ~256.667 ms | ~729.467 ms |
Debug (macOS) with asserts | ~275.4 ms | ~1045.73 ms | ~241.933 ms | ~877.6 ms |
Release (macOS) | ~64.8 ms | ~62.4 ms | ~61.6 ms | ~66.8 ms |
Release (windows-msvc 2017) | ~69.133 ms | ~258.667 ms | ~56.8 ms | ~244.133 ms |
Debug (windows-msvc 2017) | ~315.8 ms | ~4864 ms | ~301.733 ms | ~3645.73 ms |
array 1000x1000x1000 | without iterator buff != buffEnd
|
iterator it != itEnd
|
array for i...
|
iterator for i ...
|
---|---|---|---|---|
Debug (Linux) | ~1653.8 ms | ~4675.8 ms | ~1890.73 ms | ~3409 ms |
Debug (Linux) with asserts | ~1663.87 ms | ~5398.33 ms | ~1873.2 ms | ~4557.6 ms |
Release (Linux) | ~290.2 ms | ~291.4 ms | ~291.13 3ms | ~320.667 ms |
Associated Issues/Merge Requests
- Issues
- Fixes #68 (closed)