[SAGA-RG] profiling

Andre Merzky andre at merzky.net
Sat Jan 23 17:58:39 CST 2010


Hia folx, 

Having too much time (*ahem-lack-of-focus-ahem*), I run a profiler
against saga-job.  Attached is the result.  The command line was:

  ./saga-job run fork://localhost /bin/date

Walltime is consistently about 2 seconds, while a simple test
program just doing fork/exec takes no measurable time.  Now, this is
of course not fair comparision, but I wanted to know where the time
is spent anyway.  

The profiler gave me the figure attached as saga_job.prof_1.pdf .
It turns out that most time is in fact spent in boost::uuid, which
gets called a whopping 125 times, eating abouyt 89% of the run time.
To me it looks like it is trying to re-seed the random number
generator over and over again?  

So, I took the liberty to implement a much more stupid uuid
generator, which simply assigns an integer as uuid (see attached
uuid.hpp, which replaces saga/impl/engine/uuid.hpp), and indeed the
runtime for the same command line decreases to about 0.5 seconds,
which are now mostly spent in ini file parsing and adaptor loading,
as it should be (see saga_job.prof_2.pdf).  Morover, that time
should be constant per application instance, whereas the uuid time
was likely proportional to the number of SAGA calls (or objects)
used by the application.

Now, I am not claiming that we should use this overly simple uuid
generator (although it should create 4.294.967.295 unique IDs per
application instance), but in any case, the uuid generator could do
with some improvement.  I did not really understand the boost code
well enough to see why the seeding is triggered so often, but maybe
Hartmut has an idea, or someone else comes up with a cheap
alternative.

Cheers, Andre.




-- 
Nothing is ever easy.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: saga_job.prof_1.pdf
Type: application/pdf
Size: 11047 bytes
Desc: not available
Url : http://www.ogf.org/pipermail/saga-rg/attachments/20100124/71d23b6a/attachment-0002.pdf 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: saga_job.prof_2.pdf
Type: application/pdf
Size: 10814 bytes
Desc: not available
Url : http://www.ogf.org/pipermail/saga-rg/attachments/20100124/71d23b6a/attachment-0003.pdf 
-------------- next part --------------
//  Copyright (c) 2005-2009 Hartmut Kaiser
// 
//  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)

#ifndef SAGA_IMPL_ENGINE_UUID_HPP
#define SAGA_IMPL_ENGINE_UUID_HPP

#include <string>
#include <iosfwd>

#include <boost/thread.hpp>
#include <boost/thread/once.hpp>

#include <saga/saga/util.hpp>
#include <saga/saga/exception.hpp>
#include <saga/impl/exception.hpp>

///////////////////////////////////////////////////////////////////////////////
namespace saga { namespace impl {

  ///////////////////////////////////////////////////////////////////////////////
  class uuid 
  {
    private:
      mutable unsigned long int uuid_;

      ///////////////////////////////////////////////////////////////////////////////

      static int & cnt_instance (void)
      {
        static int cnt;
        cnt++;

        // FIXME: should print a warning here
        if ( cnt == ULONG_MAX )
        {
          // avoid zero
          cnt = 1;
        }

        return cnt;
      }

      static void cnt_init (void)
      {
        int cnt = cnt_instance ();
        cnt = 0;
      }

      static void initialize_cnt (void)
      {
        static boost::once_flag been_here_cnt = BOOST_ONCE_INIT;
        boost::call_once (cnt_init, been_here_cnt);
      }

      ///////////////////////////////////////////////////////////////////////////////

      static boost::mutex & mutex_instance (void)
      {
        static boost::mutex mutex;
        return mutex;
      }

      static void mutex_init (void)
      {
        mutex_instance ();
      }

      static void initialize_mutex (void)
      {
        static boost::once_flag been_here_mtx = BOOST_ONCE_INIT;
        boost::call_once (mutex_init, been_here_mtx);
      }

      ///////////////////////////////////////////////////////////////////////////////

      static void from_string (int               & id, 
                               std::string const & str)
      {
        id = boost::lexical_cast <int> (str);

        // if ( sscanf (str, "%lu", id) != 1 )
        // {
        //   // nothing found - revert to fallback zero
        //   // This will cause an exception in ensure_is_initialized
        //   id = 0;
        // }
      }

      static bool is_null (int const & id)
      {
        return ( id == 0 );
      }

      ///////////////////////////////////////////////////////////////////////////////


    public:
      uuid (void) 
        : uuid_ (0)
      {
      }

      uuid (char const * uuid_str)  
      {
        create (uuid_str);
      }

      void ensure_is_initialized (void) const
      {
        if ( is_null (uuid_) )
        {
          create ();
        }

        if ( is_null (uuid_) )
        {
          SAGA_THROW_NO_OBJECT ("Could not create UUID for this object", 
                                saga::NoSuccess);
        }
      }

      std::string string (void) const
      {
        ensure_is_initialized ();
        return boost::lexical_cast <std::string> (uuid_);
      }

      // create new uuid from scratch
      void create (void) const
      {
        initialize_mutex ();
        boost::mutex::scoped_lock lock (mutex_instance ());

        initialize_cnt ();
        uuid_ = cnt_instance ();
      }

      // create new uuid from string
      void create (char const * str) const
      {
        initialize_mutex ();
        boost::mutex::scoped_lock lock (mutex_instance ());

        from_string (uuid_, str);
      }

      // comparison operators
      friend bool operator== (uuid const & lhs, uuid const & rhs)
      {
        lhs.ensure_is_initialized();
        rhs.ensure_is_initialized();

        return lhs.uuid_ == rhs.uuid_;
      }

      friend bool operator!= (uuid const & lhs, uuid const & rhs)
      {
        return !(lhs == rhs);
      }

      friend bool operator< (uuid const & lhs, uuid const & rhs)
      {
        lhs.ensure_is_initialized();
        rhs.ensure_is_initialized();

        return lhs.uuid_ < rhs.uuid_;
      }

      friend bool operator> (uuid const & lhs, uuid const & rhs)
      {
        lhs.ensure_is_initialized();
        rhs.ensure_is_initialized();

        return lhs.uuid_ > rhs.uuid_;
      }

      friend bool operator<= (uuid const & lhs, uuid const & rhs)
      {
        return !(lhs > rhs);
      }

      friend bool operator>= (uuid const & lhs, uuid const & rhs)
      {
        return !(lhs < rhs);
      }
  };

  uuid const null_uuid = uuid ();

  ///////////////////////////////////////////////////////////////////////////////
} }   // namespace saga::impl

#endif // SAGA_SAGA_ENGINE_UUID_UUID_HPP



More information about the saga-rg mailing list