Commit 7afea3ff authored by Laurentiu Nicola's avatar Laurentiu Nicola

ENH: Add otbStopwatch replacing itk::TimeProbe

The itk::TimeProbe constructor ends up calling
itkResourceProbe::GetSystemInformation, which reads things like the
hostname, the number of CPUs and so on. On Linux it parses /proc/cpuinfo
for that information.

OTB doesn't really need all those fields for a simple timer that's only
used in a couple of places. This commit adds a replacement for that.

As for the benchmarks, 100 000 instantiations of itk::TimeProbe take
about 9.5 s on my computer. I suspect it's somewhat slower on a server
with more CPUs. So this doesn't bring a huge performance improvement,
but it might help in cases where a large number of high-resolution
images are being read. The time for the same number of otb::Stopwatch
instantiations is 4 ms.

The context for this change is a project where we process time series of
medium to high resolution images over large areas. The TimeProbe in
otbGDALImageIO was sometimes showing in the profiles.

A relevant discussion can be found at
https://groups.google.com/d/msg/otb-developers/IvsFzSgRojo/0sMeEIZgCQAJ .
parent 14935049
/*
* Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
*
* This file is part of Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef otbStopwatch_h
#define otbStopwatch_h
#include <cstdint>
#include "OTBCommonExport.h"
namespace otb
{
/** \class Stopwatch
* \brief Stopwatch timer.
*
* A simple class for measuring elapsed time.
*
*
* \ingroup OTBCommon
*/
class OTBCommon_EXPORT Stopwatch final
{
public:
/** Standard class typedefs. */
typedef Stopwatch Self;
/** Represents a duration measured in milliseconds */
typedef uint64_t DurationType;
/** Constructs a timer instance */
Stopwatch();
/** Start the timer if not already running */
void Start();
/** Stop the timer if running */
void Stop();
/** Reset the timer */
void Reset();
/** Reset and restart the timer */
void Restart();
/** Get the total duration, excluding the current iteration */
DurationType GetElapsedMilliseconds() const;
/** Returns whether the stopwatch is running */
bool IsRunning() const;
/** Creates and starts a new stopwatch instance */
static Stopwatch StartNew();
private:
typedef uint64_t TimepointType;
TimepointType GetTimestamp() const;
DurationType GetRunningElapsedTime() const;
TimepointType m_StartTime;
DurationType m_ElapsedMilliseconds;
bool m_IsRunning;
};
} // namespace otb
#endif
......@@ -27,10 +27,11 @@ set(OTBCommon_SRC
otbConfigurationManager.cxx
otbStandardOneLineFilterWatcher.cxx
otbWriterWatcherBase.cxx
otbStopwatch.cxx
)
add_library(OTBCommon ${OTBCommon_SRC})
target_link_libraries(OTBCommon
target_link_libraries(OTBCommon
${OTBITK_LIBRARIES}
)
......
/*
* Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
*
* This file is part of Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <chrono>
#include "otbStopwatch.h"
namespace otb
{
Stopwatch
::Stopwatch()
: m_ElapsedMilliseconds(), m_IsRunning()
{
}
void
Stopwatch
::Start()
{
if (!this->m_IsRunning)
{
this->m_IsRunning = true;
this->m_StartTime = this->GetTimestamp();
}
}
void
Stopwatch
::Stop()
{
if (this->m_IsRunning)
{
this->m_ElapsedMilliseconds += GetRunningElapsedTime();
this->m_IsRunning = false;
}
}
void
Stopwatch
::Reset()
{
this->m_ElapsedMilliseconds = 0;
this->m_IsRunning = false;
}
void
Stopwatch
::Restart()
{
this->m_ElapsedMilliseconds = 0;
this->m_IsRunning = true;
this->m_StartTime = this->GetTimestamp();
}
Stopwatch::DurationType
Stopwatch
::GetElapsedMilliseconds() const
{
auto result = this->m_ElapsedMilliseconds;
if (this->m_IsRunning)
result += this->GetRunningElapsedTime();
return result;
}
bool
Stopwatch
::IsRunning() const
{
return this->m_IsRunning;
}
Stopwatch
Stopwatch
::StartNew()
{
Stopwatch sw;
sw.Start();
return sw;
}
inline
Stopwatch::TimepointType
Stopwatch
::GetTimestamp() const
{
auto now = std::chrono::steady_clock::now();
return std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
}
inline
Stopwatch::DurationType
Stopwatch
::GetRunningElapsedTime() const
{
return this->GetTimestamp() - this->m_StartTime;
}
}
......@@ -37,6 +37,7 @@ otbConfigurationManagerTest.cxx
otbStandardFilterWatcherNew.cxx
otbStandardOneLineFilterWatcherTest.cxx
otbStandardWriterWatcher.cxx
otbStopwatchTest.cxx
)
add_executable(otbCommonTestDriver ${OTBCommonTests})
......@@ -167,6 +168,9 @@ otb_add_test(NAME coTuSystemTests_IsA_Methods COMMAND otbCommonTestDriver
${OTB_DATA_ROOT}
)
otb_add_test(NAME coTuStopwatchTests COMMAND otbCommonTestDriver
otbStopwatchTest)
otb_add_test(NAME coTvParseHdfSubsetName COMMAND otbCommonTestDriver
otbParseHdfSubsetName)
......
......@@ -31,6 +31,7 @@ void RegisterTests()
REGISTER_TEST(otbRectangle);
REGISTER_TEST(otbImageRegionNonUniformMultidimensionalSplitterNew);
REGISTER_TEST(otbSystemTest);
REGISTER_TEST(otbStopwatchTest);
REGISTER_TEST(otbParseHdfSubsetName);
REGISTER_TEST(otbParseHdfFileName);
REGISTER_TEST(otbImageRegionSquareTileSplitterNew);
......
/*
* Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
*
* This file is part of Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cassert>
#include <iostream>
#include <cstdlib>
#if 0
#include <unistd.h>
#include "itkTimeProbe.h"
#endif
#include "itkMacro.h"
#include "otbStopwatch.h"
int otbStopwatchTest(int itkNotUsed(argc), char * itkNotUsed(argv)[])
{
otb::Stopwatch sw;
assert( !sw.IsRunning() );
assert( sw.GetElapsedMilliseconds() == 0 );
sw.Start();
assert( sw.IsRunning() );
sw.Stop();
sw.Reset();
assert( !sw.IsRunning() );
assert( sw.GetElapsedMilliseconds() == 0 );
sw = otb::Stopwatch::StartNew();
assert( sw.IsRunning() );
sw.Stop();
#if 0
// We have no portable sleep() and otbThreads is not linked here
sw.Start();
usleep(500 * 1000);
sw.Stop();
assert( sw.GetElapsedMilliseconds() > 450 && sw.GetElapsedMilliseconds() < 550 );
sw.Start();
usleep(500 * 1000);
sw.Stop();
assert( sw.GetElapsedMilliseconds() > 900 && sw.GetElapsedMilliseconds() < 1100 );
sw.Restart();
usleep(500 * 1000);
sw.Stop();
assert( sw.GetElapsedMilliseconds() > 450 && sw.GetElapsedMilliseconds() < 550 );
const int iterations = 100000;
sw.Restart();
for (int i = 0; i < iterations; i++)
{
itk::TimeProbe chrono;
chrono.Start();
chrono.Stop();
}
std::cerr << "itk::TimeProbe time: " << sw.GetElapsedMilliseconds() << std::endl;
sw.Restart();
for (int i = 0; i < iterations; i++)
{
auto chrono = otb::Stopwatch::StartNew();
chrono.Stop();
}
std::cerr << "otb::Stopwatch time: " << sw.GetElapsedMilliseconds() << std::endl;
#endif
return EXIT_SUCCESS;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment