Boost logo

Boost :

From: Ion Gaztañaga (ion_g_m_at_[hidden])
Date: 2005-04-24 14:04:16


For what I've seen in code, read_write_mutex has a lot of options regarding
reader/writer priorities and for that uses conditions and mutexes to offer
that functionality. The overhead is bigger than mutexes, but I think the
critical section you have chosen is very small, and where read_writer_mutex
shines is when you have to lock expensive operations (lookups for example,
in data-bases) with lots of readers. In that case, a mutex would serialize
all, but read_writer_mutex would allow concurrent
readers.

Ion

----- Original Message -----
From: "Peter Dimov" <pdimov_at_[hidden]>
To: "boost-devel" <boost_at_[hidden]>
Sent: Sunday, April 24, 2005 3:07 PM
Subject: [boost] [threads] read_write_mutex performance

> What are the design goals of read_write_mutex? (Lock proliferation aside
> for a moment.)
>
> My understanding has always been that read/write locks are an
> optimization, that is, a read/write lock-based algorithm should deliver
> better performance than the same algorithm with "ordinary" locks. Right?
>
> Wrong.
>
> The program at the end of this message demonstrates that in this specific
> (contrived?) case ordinary mutexes outperform a read/write mutex by a
> factor of 2.5 or more in almost every scenario, even when no writers are
> active!
>
> In some scenarios (16 readers, 4 writers, 10,000,000 iterations) the
> ordinary mutex case completes in under 8 seconds on my machine, but the
> read/write case exceeded my patience threshold.
>
> Am I missing something?
>
> --
> Peter Dimov
> http://www.pdimov.com
>
> #include <boost/thread.hpp>
> #include <boost/thread/read_write_mutex.hpp>
> #include <iostream>
> #include <vector>
> #include <time.h>
>
> //#define RWLOCK
>
> int const n = 1000000;
> int const n_readers = 16;
> int const n_writers = 0;
>
> std::vector<int> v;
>
> #ifdef RWLOCK
>
> boost::read_write_mutex mtx(
> boost::read_write_scheduling_policy::alternating_many_reads );
>
> #else
>
> boost::mutex mtx;
>
> #endif
>
> void reader_thread()
> {
> int m = 0;
>
> for( int i = 0; i < n; ++i )
> {
> #ifdef RWLOCK
>
> boost::read_write_mutex::scoped_read_lock lock( mtx );
>
> #else
>
> boost::mutex::scoped_lock lock( mtx );
>
> #endif
>
> m += v[ i ];
> }
>
> std::cout << m << std::endl;
> }
>
> void writer_thread()
> {
> for( int i = 0; i < n; ++i )
> {
> #ifdef RWLOCK
>
> boost::read_write_mutex::scoped_write_lock lock( mtx );
>
> #else
>
> boost::mutex::scoped_lock lock( mtx );
>
> #endif
>
> v[ i ] += i;
> }
> }
>
> int main()
> {
> v.resize( n );
>
> boost::thread_group group;
>
> clock_t t = clock();
>
> for( int i = 0; i < n_writers; ++i )
> {
> group.add_thread( new boost::thread( writer_thread ) );
> }
>
> for( int i = 0; i < n_readers; ++i )
> {
> group.add_thread( new boost::thread( reader_thread ) );
> }
>
> group.join_all();
>
> t = clock() - t;
>
> std::cout << static_cast<double>( t ) / CLOCKS_PER_SEC << '\n';
> }
>
>
>


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