Boost logo

Boost :

Subject: Re: [boost] [Test] Regression by using to Boost.Timer v2, Boost.Test is not header-only anymore
From: Barend Gehrels (barend_at_[hidden])
Date: 2015-01-14 16:13:54


Hi,

I changed the subject because it is not about Thread only.

So as far as I understand, Boost.Test has moved from Boost.Timer v1
(2001) to Boost.Timer v2 (2011). Boost.Timer v2 depends on Boost.Chrono,
which optionally can be compiled header-only, and on Boost.System. But
Boost.Timer itself has no option to be compiled header-only (AFAIU). So
basically the regression is in Boost.Timer, which now requires linking.
But because that is already introduced in 2011, it cannot be called a
sudden regression. However, the influence on Boost.Test is quite large.

We use Boost.Test (the header-only option) since 2007 and wish to keep
it header-only. I know what to do to make it compile (link with
Boost.Timer) but that is an unwished option for several reasons, so: a
regression.

Rest of my answer below.

Vicente J. Botet Escriba schreef op 14-1-2015 om 20:35:
> Le 14/01/15 18:10, Raffi Enficiaud a écrit :
>>
>> Please also note that there is a clash in the new and old timer API:
>>
>> http://www.boost.org/development/tests/develop/developer/output/Sandia-clang-boost-bin-v2-libs-geometry-test-algorithms-buffer-multi_point_buffer-test-clang-darwin-4-2-1-debug.html
>>
>>
>> It is impossible to use the old and new API at the same time, as
>> there is a
>> namespace in the old API and a class in the new API with the same name.
>> In boost.test we chose to use the new one and drop support for the
>> old one.
>> This was of course before we discovered that so many problem raised.
>>
>> I made the changes in boost.geometry, I am preparing a pull request for
>> addressing these issues.

As discussed on github, I have noticed it. Thanks for the PR.

>> Some other libraries also suffer from this apparently:
>> - asio: looks like linking at the same time to shared and static
>> version of
>> system, might be generated by the changes in boost.test (I have to
>> look further)
>> - atomic: link missing
>> - circular_buffer: link missing
>> - lockfree: same as asio
>> - numeric/ublas: link missing
>> - pool: maybe the same as asio
>> - tr1 : unclear what is happening here
>> - regex: link missing
>> - random: link missing
>>
>>
>> The problems seen on geometry/extension do not seem to be produced by
>> the
>> changes in boost.test:
>> http://www.boost.org/development/tests/develop/developer/geometry-extensions.html
>>

These are indeed unrelated to Boost.Test

>>
>> BTW, it is hard to see the problems created by a range of commits.
>> How to
>> proceed? For instance, there are problems in boost.icl
>> http://www.boost.org/development/tests/develop/developer/output/Sandia-clang-boost-bin-v2-libs-icl-test-chrono_interval_set_mixed-test-clang-darwin-4-2-1-debug-link-static.html
>>
>> and I do not know if they were provoked by the changes in boost.test.
>>
>>
>> Tests in geometry/test/robustness/overlay/linear_areal do not compile
>> on my
>> machine.
>> Also there is an indirect inclusion of boost.timer from
>> ./include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
>> ./include/boost/geometry/algorithms/detail/overlay/overlay.hpp
>>
>> which produces a clash in the use of boost.timer.
>>
>>
> I suggest you to :
> * rollback your changes related to Boost.Timer, this should make all
> the libraries to work as before.
> * create a branch on which you move to the new Timer interface and you
> maybe need to link to (it would be preferable to don't need it).
> * Announce the breaking change on this ML (yes there is a breaking
> change if the user needs to link to Boost.Timer and didn't needed it
> before).
> * If the breaking change is accepted, propose PR for each one of the
> libraries :(
>
> I understand that this is more work than breaking all the users code,
> but at the end you will gain.
>
> HTH,
> Vicente
>
> P.S. I don't know what is the state of the Boost.Test develop branch,
> but if I were you (I'm not) I would follow the advice given by others
> in other threads:
> * Rename the develop branch to a feature branch.
> * Create a develop branch from the master branch.
> * Fix the major issues on the develop branch in parallel with the
> development of the new big feature.
> * When the feature is ready, merge it to develop and then to master.

I agree with this recommended way of working.

As mentioned above, the regression is due to Boost.Timer v2 which is
incompatable with V1, and not header-only anymore. I understand the wish
to advance to a new version of Boost.Timer. However, the problems should
be solved.

The first question I asked myself: why is Boost.Test timing anyway? It
is doing regression tests and checking results, but should that be
timed? It looks good to display the timings, but is it essential? So
maybe it is an option to avoid the usage of Boost.Timer at all.

Then I tried to solve my problems (all my projects do not work anymore
because I don't use b2 but QtCreator projects, and I depend heavily on
Boost.Test). I created a stub in test/utils/timer.hpp, avoiding the
usage of Boost.Timer at all. See below for this adapted version, the
essention is: with a define BOOST_TEST_DONT_USE_TIMER the complete
Boost.Timer functionality is excluded, while all the rest of Boost.Test
is still working. This solves my personal problems.

1) So that is suggestion one: create an option to avoid the usage of
Boost.Timer, which solves all compatibility and linking problems.

2) If this is possible and the dependency is only in one file, it should
be possible to use Boost.Chrono directly instead of Boost.Timer. Because
Boost.Timer v2 is AFAIU a wrapper around Boost.Chrono, and Boost.Chrono
is, conditionally, usable as header-only (according to the docs). So
that is suggestion number two: use Boost.Chrono.

3) Suggestion three is that the regression in Boost.Timer, dated 2011,
should be fixed. Why is it not possible to use Boost.Timer header-only?
It was possible before! But that is probably not up to the Boost.Test team.

OK - in the meantime I see the message which just comes in now, it is
rolled-back. However, maybe you can do something with these suggestions.

Regards, Barend

// (C) Copyright Jamie Allsop 2015.

// Distributed under the Boost Software License, Version 1.0.

// (See accompanying file LICENSE_1_0.txt or copy at

//http://www.boost.org/LICENSE_1_0.txt)

// Seehttp://www.boost.org/libs/test for the library home page.

//

// Description : timer and elapsed types

// ***************************************************************************

#ifndef BOOST_TEST_UTILS_TIMER_HPP

#define BOOST_TEST_UTILS_TIMER_HPP

#if !defined(BOOST_TEST_DONT_USE_TIMER)

#include <boost/test/unit_test_parameters.hpp>

#include <boost/timer/timer.hpp>

#include <sstream>

#endif

namespace boost {

namespace unit_test {

// ************************************************************************** //

// ************** opaque timer and elapsed types ************** //

// ************************************************************************** //

#if !defined(BOOST_TEST_DONT_USE_TIMER)

typedef boost::timer::cpu_timer timer_t;

typedef boost::timer::cpu_times elapsed_t;

typedef boost::timer::nanosecond_type nanoseconds_t;

inline long microsecond_cpu_time( elapsed_t elapsed )

{

     return ( elapsed.user + elapsed.system )/1000;

}

inline std::string deprecated_hrf_format( elapsed_t elapsed )

{

     std::ostringstream output;

     long duration = microsecond_cpu_time( elapsed );

     if( duration % 1000 == 0 )

     {

         output << duration/1000 << "ms";

     }

     else

     {

         output << duration << "mks";

     }

     return output.str();

}

inline std::string to_string( elapsed_t elapsed )

{

     if( runtime_config::deprecated_timer_format() )

     {

         return deprecated_hrf_format( elapsed );

     }

     return boost::timer::format( elapsed, 9, "%ws wall, %us user + %ss system = %ts CPU (%p%)" );

}

inline std::string to_xml( elapsed_t elapsed )

{

     std::ostringstream output;

     output << "<TestingTime>" << microsecond_cpu_time( elapsed ) << "</TestingTime>"

            << "<CpuTime>" << ( elapsed.user + elapsed.system ) << "</CpuTime>"

            << "<WallTime>" << elapsed.wall << "</WallTime>"

            << "<UserTime>" << elapsed.user << "</UserTime>"

            << "<SystemTime>" << elapsed.system << "</SystemTime>";

     return output.str();

}

inline bool has_time( const elapsed_t& elapsed )

{

     if( runtime_config::deprecated_timer_format() )

     {

         return elapsed.user != 0 || elapsed.system != 0 ;

     }

     return elapsed.wall != 0 || elapsed.user != 0 || elapsed.system != 0;

}

#else

typedef int elapsed_t;

inline bool has_time( const elapsed_t& elapsed ) { return false; }

inline std::string to_xml( elapsed_t elapsed ) { return ""; }

inline std::string to_string( elapsed_t elapsed ) { return ""; }

struct timer_t

{

     void stop() {}

     elapsed_t elapsed() const { return 0; }

};

#endif

//____________________________________________________________________________//

} // namespace unit_test

} // namespace boost

#endif // BOOST_TEST_UTILS_TIMER_HPP


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk