dlvhex  2.5.0
include/dlvhex2/Benchmarking.h
Go to the documentation of this file.
00001 /* dlvhex -- Answer-Set Programming with external interfaces.
00002  * Copyright (C) 2005-2007 Roman Schindlauer
00003  * Copyright (C) 2006-2015 Thomas Krennwallner
00004  * Copyright (C) 2009-2016 Peter Schüller
00005  * Copyright (C) 2011-2016 Christoph Redl
00006  * Copyright (C) 2015-2016 Tobias Kaminski
00007  * Copyright (C) 2015-2016 Antonius Weinzierl
00008  *
00009  * This file is part of dlvhex.
00010  *
00011  * dlvhex is free software; you can redistribute it and/or modify it
00012  * under the terms of the GNU Lesser General Public License as
00013  * published by the Free Software Foundation; either version 2.1 of
00014  * the License, or (at your option) any later version.
00015  *
00016  * dlvhex is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with dlvhex; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00024  * 02110-1301 USA.
00025  */
00026 
00035 #ifndef DLVHEX_H_BENCHMARKING_INCLUDED_1555
00036 #define DLVHEX_H_BENCHMARKING_INCLUDED_1555
00037 
00038 #include "dlvhex2/PlatformDefinitions.h"
00039 
00040 #include <boost/scope_exit.hpp>
00041                                  // seems to be required for scope_exit
00042 #include <boost/typeof/typeof.hpp>
00043 #include <boost/date_time/posix_time/posix_time.hpp>
00044 #include <boost/thread/mutex.hpp>
00045 #include <vector>
00046 #include <ostream>
00047 
00048 // Benchmarking is always compiled into dlvhex,
00049 // but benchmarking of dlvhex itself is only
00050 // activated if you configure with --enable-debug
00051 //
00052 // Plugins can use benchmarking of dlvhex by doing
00053 // #define DLVHEX_BENCHMARK
00054 // #include <dlvhex2/Benchmarking.h>
00055 // in a .cpp file that wants to use benchmarking.
00056 //
00057 // usage example:
00058 //
00059 // DLVHEX_BENCHMARK_REGISTER(sid1,"calling dlv");
00060 // DLVHEX_BENCHMARK_REGISTER(sid2,"fork+exec dlv");
00061 // DLVHEX_BENCHMARK_REGISTER(sid3,"parse dlv result");
00062 //
00063 // DLVHEX_BENCHMARK_START(sid1)
00064 //   DLVHEX_BENCHMARK_START(sid2)
00065 //   // fork and exec
00066 //   DLVHEX_BENCHMARK_STOP(sid2)
00067 //
00068 //   {
00069 //      DLVHEX_BENCHMARK_SCOPE(sid3)
00070 //      parse result
00071 //      ...
00072 //   }
00073 // DLVHEX_BENCHMARK_STOP(sid1)
00074 // DLVHEX_BENCHMARK_COUNT(sid4,someinteger)
00075 // DLVHEX_BENCHMARK_REGISTER_AND_START(sid6,"reg start")
00076 // {
00077 //   DLVHEX_BENCHMARK_REGISTER_AND_SCOPE(sid5,"reg scope")
00078 //   ...
00079 // }
00080 // DLVHEX_BENCHMARK_STOP(sid6)
00081 //
00082 // if you want to have a benchmark scope within a template, you need to use
00083 // DLVHEX_BENCHMARK_REGISTER_AND_SCOPE_TPL(sid7,"reg scope in template")
00084 //
00085 // you can also manage the stat IDs yourself
00086 // (e.g., for creating one instrumentation per custom external atom,
00087 //  not only one for some base class)
00088 // #if defined(DLVHEX_BENCHMARK)
00089 //   dlvhex::benchmark::ID myStoredSid =
00090 //     dlvhex::benchmark::BenchmarkController::Instance().getInstrumentationID("my message");
00091 // #endif
00092 //
00093 // invalidate(sid) and INVALIDATE is used to abort instrumentations that were started but should not be counted
00094 // (e.g., if there is no model, we will not have a time to first model)
00095 // invalidating a non-running counter does nothing
00096 //
00097 // there are two benchmark controllers that can be used:
00098 // * simple: (#define DLVHEX_BENCHMARK_SIMPLE)
00099 //   + fast and simple
00100 //   - counts overlapping instrumentalizations twice
00101 //     (not if they have the same name)
00102 //   - gives less intuitive timing results
00103 // * nesting-aware: (#define DLVHEX_BENCHMARK_NESTINGAWARE)
00104 //   - a bit more complex
00105 //   + counts "pure" time where an instrumentalization
00106 //     was the last activated one (uses a stack of instrumentalizations)
00107 //   + gives more intuitive timing results
00108 
00109 //#define DLVHEX_BENCHMARK_SIMPLE
00110 #define DLVHEX_BENCHMARK_NESTINGAWARE
00111 
00112 #if defined(DLVHEX_BENCHMARK)
00113 # define DLVHEX_BENCHMARK_REGISTER(sid,msg) \
00114     static DLVHEX_NAMESPACE benchmark::ID sid = DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().getInstrumentationID(msg)
00115 # define DLVHEX_BENCHMARK_START(sid) \
00116     DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().start(sid)
00117 # define DLVHEX_BENCHMARK_STOP(sid) \
00118     DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().stop(sid)
00119 # define DLVHEX_BENCHMARK_INVALIDATE(sid) \
00120     DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().invalidate(sid)
00121 # define DLVHEX_BENCHMARK_SUSPEND(sid) \
00122     DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().stop(sid,false)
00123 # define DLVHEX_BENCHMARK_COUNT(sid,num) \
00124     DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().count(sid,num)
00125 # define DLVHEX_BENCHMARK_SCOPE(sid) \
00126     DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().start(sid); \
00127     BOOST_SCOPE_EXIT( (sid) ) \
00128     { \
00129         DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().stop(sid); \
00130     } BOOST_SCOPE_EXIT_END
00131 # define DLVHEX_BENCHMARK_SUSPEND_SCOPE(sid) \
00132     DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().stop(sid,false); \
00133     BOOST_SCOPE_EXIT( (sid) ) \
00134     { \
00135         DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().start(sid); \
00136     } BOOST_SCOPE_EXIT_END
00137 # define DLVHEX_BENCHMARK_SCOPE_TPL(sid) \
00138     DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().start(sid); \
00139     BOOST_SCOPE_EXIT_TPL( (sid) ) \
00140     { \
00141         DLVHEX_NAMESPACE benchmark::BenchmarkController::Instance().stop(sid); \
00142     } BOOST_SCOPE_EXIT_END
00143 # define DLVHEX_BENCHMARK_REGISTER_AND_SCOPE(sid,msg) \
00144     DLVHEX_BENCHMARK_REGISTER(sid,msg); DLVHEX_BENCHMARK_SCOPE(sid);
00145 # define DLVHEX_BENCHMARK_REGISTER_AND_SCOPE_TPL(sid,msg) \
00146     DLVHEX_BENCHMARK_REGISTER(sid,msg); DLVHEX_BENCHMARK_SCOPE_TPL(sid);
00147 # define DLVHEX_BENCHMARK_REGISTER_AND_START(sid,msg) \
00148     DLVHEX_BENCHMARK_REGISTER(sid,msg); DLVHEX_BENCHMARK_START(sid);
00149 # define DLVHEX_BENCHMARK_REGISTER_AND_COUNT(sid,msg,num) \
00150     DLVHEX_BENCHMARK_REGISTER(sid,msg); DLVHEX_BENCHMARK_COUNT(sid,num);
00151 #else
00152 # define DLVHEX_BENCHMARK_REGISTER(sid,msg)               do { } while(0)
00153 # define DLVHEX_BENCHMARK_START(sid)                      do { } while(0)
00154 # define DLVHEX_BENCHMARK_STOP(sid)                       do { } while(0)
00155 # define DLVHEX_BENCHMARK_INVALIDATE(sid)                 do { } while(0)
00156 # define DLVHEX_BENCHMARK_SUSPEND(sid)                    do { } while(0)
00157 # define DLVHEX_BENCHMARK_SUSPEND_SCOPE(sid)              do { } while(0)
00158 # define DLVHEX_BENCHMARK_COUNT(sid,num)                  do { } while(0)
00159 # define DLVHEX_BENCHMARK_SCOPE(sid)                      do { } while(0)
00160 # define DLVHEX_BENCHMARK_SCOPE_TPL(sid)                  do { } while(0)
00161 # define DLVHEX_BENCHMARK_REGISTER_AND_SCOPE(sid,msg)     do { } while(0)
00162 # define DLVHEX_BENCHMARK_REGISTER_AND_SCOPE_TPL(sid,msg) do { } while(0)
00163 # define DLVHEX_BENCHMARK_REGISTER_AND_START(sid,msg)     do { } while(0)
00164 # define DLVHEX_BENCHMARK_REGISTER_AND_COUNT(sid,msg,num) do { } while(0)
00165 #endif                           // defined(DLVHEX_BENCHMARK)
00166 
00167 DLVHEX_NAMESPACE_BEGIN
00168 
00169 namespace benchmark
00170 {
00171 
00172     typedef unsigned ID;
00173     typedef unsigned Count;
00174     typedef boost::posix_time::ptime Time;
00175     typedef boost::posix_time::time_duration Duration;
00176 
00177     namespace simple
00178     {
00179 
00181         class DLVHEX_EXPORT BenchmarkController
00182         {
00183             public:
00185                 struct Stat
00186                 {
00188                     std::string name;
00190                     Count count;
00192                     Count level;
00194                     Count prints;
00196                     Time start;
00198                     Duration duration;
00200                     bool running;
00201 
00204                     Stat(const std::string& name);
00205                 };
00206 
00207             public:
00212                 inline std::ostream& printInSecs(std::ostream& o, const Duration& d, int width=0) const;
00213 
00214                 // comfort formatting
00218                 std::string count(const std::string& identifier, int width=0) const;
00222                 std::string duration(const std::string& identifier, int width=0) const;
00223 
00226                                  // inline for performance
00227                 inline void printInformation(const Stat& st);
00230                 inline void printInformationContinous(
00231                                  // inline for performance
00232                     Stat& st, const Duration& dur);
00233 
00234             public:
00235                 //
00238                 static BenchmarkController& Instance();
00239 
00243                 static void finish();
00244 
00248                 ~BenchmarkController();
00249 
00250                 //
00251                 // configure
00252                 //
00253 
00256                 void setOutput(std::ostream* o);
00259                 void setPrintInterval(Count skip);
00260 
00261                 //
00262                 // instrumentation points
00263                 //
00264 
00268                 ID getInstrumentationID(const std::string& name);
00273                                  // inline for performance
00274                 inline std::ostream& printCount(std::ostream& out, ID id);
00278                                  // inline for performance
00279                 inline std::ostream& printDuration(std::ostream& out, ID id);
00283                 inline const Stat& getStat(ID id) const { return instrumentations[id]; }
00284 
00285                 //
00286                 // record measured things
00287                 //
00288 
00289                 // stop and resume benchmarking
00291                 void suspend();
00293                 void resume();
00294 
00295                 // start timer
00298                                  // inline for performance
00299                 inline void start(ID id);
00305                                  // inline for performance
00306                 inline void stop(ID id, bool count=true);
00312                                  // inline for performance
00313                 inline void count(ID id, Count increment=1);
00318                 void invalidate(ID id);
00319 
00325                 void snapshot(ID id, ID intoID);
00326 
00332                 void snapshot(const std::string& fromstr, const std::string& tostr);
00333 
00334             private:
00338                 BenchmarkController();
00339 
00341                 ID myID;
00343                 ID maxID;
00345                 std::vector<Stat> instrumentations;
00347                 std::map<std::string, ID> name2id;
00348 
00350                 std::ostream* output;
00352                 Count printSkip;
00353 
00355                 boost::mutex mutex;
00357                 unsigned sus;
00358         };
00359 
00360         //inline
00361         std::ostream& BenchmarkController::printInSecs(std::ostream& out, const Duration& td, int width) const
00362         {
00363             long in_secs = (long)td.total_milliseconds();
00364 
00365             long secs = in_secs / 1000;
00366             long rest = in_secs % 1000;
00367 
00368             out << std::setw(width) << secs << ".";
00369 
00370             if (rest < 10) {
00371                 out << "00";
00372             }
00373             else if (rest < 100) {
00374                 out << "0";
00375             }
00376 
00377             return out << rest;
00378         }
00379 
00380         // print information about stat
00381         // inline for performance
00382         void BenchmarkController::printInformation(const Stat& st) {
00383             if( output ) {
00384                 (*output) <<
00385                     "BM:" << std::setw(30) << st.name <<
00386                     ": count:" << std::setw(8) << st.count;
00387                 (*output) <<
00388                     " total:";
00389                 printInSecs(*output, st.duration, 4) <<
00390                     "s avg:";
00391                 if( st.count > 0 ) {
00392                     printInSecs(*output, st.duration/st.count, 4);
00393                 }
00394                 else {
00395                     (*output) << "   -.---";
00396                 }
00397                 (*output) << std::endl;
00398             }
00399         }
00400 
00401         // print only count of ID
00402         std::ostream& BenchmarkController::printCount(std::ostream& out, ID id) {
00403             boost::mutex::scoped_lock lock(mutex);
00404             Stat& st = instrumentations[id];
00405             return out << st.count;
00406         }
00407 
00408         std::ostream& BenchmarkController::printDuration(std::ostream& out, ID id) {
00409             boost::mutex::scoped_lock lock(mutex);
00410             Stat& st = instrumentations[id];
00411             return printInSecs(out, st.duration);
00412         }
00413 
00414         // print continuous information about stat
00415         // inline for performance
00416         void BenchmarkController::printInformationContinous(Stat& st, const Duration& dur) {
00417             if( st.prints >= printSkip ) {
00418                 st.prints = 0;
00419                 if( output ) {
00420                     (*output) <<
00421                         "BM:" << std::setw(30) << st.name <<
00422                         ": count:" << std::setw(8) << st.count <<
00423                         " total:";
00424                     printInSecs(*output, st.duration, 4) << "s" <<
00425                         " last:";
00426                     printInSecs(*output, dur, 2) << "s" << ((st.running)?"(runs)":"") << std::endl;
00427                 }
00428             }
00429             else {
00430                 st.prints++;
00431             }
00432         }
00433 
00434         // inline for performance
00435         // start timer
00436         void BenchmarkController::start(ID id) {
00437             if (sus) return;
00438             boost::mutex::scoped_lock lock(mutex);
00439             Stat& st = instrumentations[id];
00440             if( !st.running ) {
00441                 st.start = boost::posix_time::microsec_clock::local_time();
00442                 st.running = true;
00443                 // running once -> level 1
00444                 st.level = 1;
00445             }
00446             else {
00447                 // increase nesting level
00448                 st.level++;
00449             }
00450         }
00451 
00452         // inline for performance
00453         // stop and record elapsed time, print stats
00454         void BenchmarkController::stop(ID id, bool count) {
00455             if (sus) return;
00456             boost::mutex::scoped_lock lock(mutex);
00457             Stat& st = instrumentations[id];
00458 
00459             if( st.running && st.level == 1 ) {
00460                 Duration dur = boost::posix_time::microsec_clock::local_time() - st.start;
00461                 st.duration += dur;
00462                 st.running = false;
00463                 if( count ) {
00464                     st.count++;
00465                     printInformationContinous(st,dur);
00466                 }
00467             }
00468             else if( st.running ) {
00469                 // decrease nesting level
00470                 st.level--;
00471             }
00472         }
00473 
00474         // record count (no time), print stats
00475         // inline for performance
00476         void BenchmarkController::count(ID id, Count increment) {
00477             if (sus) return;
00478             boost::mutex::scoped_lock lock(mutex);
00479             Stat& s = instrumentations[id];
00480             s.count += increment;
00481             // only count how often we count, otherwise we might spam
00482             s.prints ++;
00483             printInformationContinous(s,Duration());
00484         }
00485 
00486     }                            // namespace simple
00487 
00488     namespace nestingAware
00489     {
00490 
00492         class DLVHEX_EXPORT NestingAwareController
00493         {
00494             public:
00496                 struct Stat
00497                 {
00499                     std::string name;
00501                     Count count;
00503                     Duration duration;
00505                     Duration pureDuration;
00507                     Count level;
00509                     Time nextPrint;
00510 
00513                     Stat(const std::string& name, Duration printInterval);
00514                 };
00515                 struct Current
00516                 {
00518                     ID which;
00520                     Time firststart;
00522                     Time start;
00523 
00524                     Current(ID which);
00525                 };
00526 
00527             public:
00532                 inline std::ostream& printInSecs(std::ostream& o, const Duration& d, int width=0) const;
00533 
00534                 // comfort formatting
00538                 std::string count(const std::string& identifier, int width=0) const;
00542                 std::string duration(const std::string& identifier, int width=0) const;
00543 
00546                 void printInformation(const Stat& st);
00549                 inline void printInformationContinous(Stat& st, const Duration& dur);
00550 
00551             public:
00552                 //
00555                 static NestingAwareController& Instance();
00556 
00560                 static void finish();
00561 
00565                 ~NestingAwareController();
00566 
00567                 //
00568                 // configure
00569                 //
00570 
00573                 void setOutput(std::ostream* o);
00576                 void setPrintInterval(Count skip);
00577 
00578                 //
00579                 // instrumentation points
00580                 //
00581 
00585                 ID getInstrumentationID(const std::string& name);
00590                                  // inline for performance
00591                 inline std::ostream& printCount(std::ostream& out, ID id);
00595                                  // inline for performance
00596                 inline std::ostream& printDuration(std::ostream& out, ID id);
00600                 inline const Stat& getStat(ID id) const { return instrumentations[id]; }
00601 
00602                 //
00603                 // record measured things
00604                 //
00605 
00606                 // stop and resume benchmarking
00608                 void suspend();
00610                 void resume();
00611 
00612                 // start timer
00615                                  // inline for performance
00616                 inline void start(ID id);
00622                                  // inline for performance
00623                 inline void stop(ID id, bool count=true);
00629                                  // inline for performance
00630                 inline void count(ID id, Count increment=1);
00635                 void invalidate(ID id);
00636 
00642                 void snapshot(ID id, ID intoID);
00643 
00649                 void snapshot(const std::string& fromstr, const std::string& tostr);
00650 
00651             private:
00655                 NestingAwareController();
00656 
00658                 ID myID;
00660                 ID maxID;
00662                 std::vector<Stat> instrumentations;
00664                 std::map<std::string, ID> name2id;
00666                 std::vector<Current> current;
00667 
00669                 Duration printInterval;
00671                 std::ostream* output;
00672 
00674                 boost::mutex mutex;
00676                 unsigned sus;
00677         };
00678 
00679         //inline
00680         std::ostream& NestingAwareController::printInSecs(std::ostream& out, const Duration& td, int width) const
00681         {
00682             long in_secs = (long)td.total_milliseconds();
00683 
00684             long secs = in_secs / 1000;
00685             long rest = in_secs % 1000;
00686 
00687             out << std::setw(width) << secs << ".";
00688 
00689             if (rest < 10) {
00690                 out << "00";
00691             }
00692             else if (rest < 100) {
00693                 out << "0";
00694             }
00695 
00696             return out << rest;
00697         }
00698 
00699         // print only count of ID
00700         std::ostream& NestingAwareController::printCount(std::ostream& out, ID id) {
00701             boost::mutex::scoped_lock lock(mutex);
00702             Stat& st = instrumentations[id];
00703             return out << st.count;
00704         }
00705 
00706         std::ostream& NestingAwareController::printDuration(std::ostream& out, ID id) {
00707             boost::mutex::scoped_lock lock(mutex);
00708             Stat& st = instrumentations[id];
00709             return printInSecs(out, st.duration);
00710         }
00711 
00712         // print continuous information about stat
00713         // inline for performance
00714         void NestingAwareController::printInformationContinous(Stat& st, const Duration& dur) {
00715             if( !output )
00716                 return;
00717             Time now = boost::posix_time::microsec_clock::local_time();
00718             if( now > st.nextPrint ) {
00719                 st.nextPrint = now + printInterval;
00720                 (*output) <<
00721                     "BM:" << std::setw(30) << st.name <<
00722                     ": count:" << std::setw(8) << st.count <<
00723                     " total:";
00724                 printInSecs(*output, st.duration, 4) << "s" <<
00725                     " pure:";
00726                 printInSecs(*output, st.pureDuration, 4) << "s" <<
00727                     " last:";
00728                 printInSecs(*output, dur, 2) << "s" << std::endl;
00729             }
00730         }
00731 
00732         // inline for performance
00733         // start timer
00734         void NestingAwareController::start(ID id) {
00735             boost::mutex::scoped_lock lock(mutex);
00736             Stat& st = instrumentations[id];
00737 
00738             Time now = boost::posix_time::microsec_clock::local_time();
00739 
00740             st.level++;          // not running = 0, 1 = not nested
00741             if( !current.empty() ) {
00742                 // suspend previously active instrumentation (and record pure time elapsed)
00743                 Current& prevc = current.back();
00744                 Stat& prevst = instrumentations[prevc.which];
00745                 prevst.pureDuration += now - prevc.start;
00746             }
00747 
00748             // start new instrumentation
00749             current.push_back(Current(id));
00750             Current& c = current.back();
00751             c.firststart = now;
00752             c.start = now;
00753         }
00754 
00755         // inline for performance
00756         // stop and record elapsed time, print stats
00757         void NestingAwareController::stop(ID id, bool count) {
00758             boost::mutex::scoped_lock lock(mutex);
00759             Stat& st = instrumentations[id];
00760 
00761             Time now = boost::posix_time::microsec_clock::local_time();
00762 
00763             // currently active instrumentation
00764             Current& c = current.back();
00765             if( id != c.which )
00766                 // warn but ignore
00767                 std::cerr << "inconsistency: instrumentation '" << st.name <<
00768                     "' currently running but got stop() for '" << instrumentations[id].name <<
00769                     "'! (might cause subsequent errors)" << std::endl;
00770 
00771             // update pure duration
00772             st.pureDuration += now - c.start;
00773 
00774             // update overall duration, but only if not nested with itself
00775             // (this way neither pure nor overall duration is counted twice)
00776             Duration thisDuration;
00777             if( st.level == 1 ) {
00778                 // the continuously logged duration must be non-pure, otherwise we need
00779                 // to separately accumulate pureDuration since most recent start()
00780                 thisDuration = now - c.firststart;
00781                 st.duration += thisDuration;
00782             }
00783             if( count ) {
00784                 st.count++;
00785                 printInformationContinous(st, thisDuration);
00786             }
00787 
00788             // remove current instrumentation
00789             current.pop_back();
00790             st.level--;
00791 
00792             // leave function if there is no higher-level instrumentation running
00793             if( current.empty() )
00794                 return;
00795 
00796             // resume previous instrumentation
00797             Current& prevc = current.back();
00798             prevc.start = now;
00799         }
00800 
00801         // record count (no time), print stats
00802         // inline for performance
00803         void NestingAwareController::count(ID id, Count increment) {
00804             boost::mutex::scoped_lock lock(mutex);
00805             Stat& s = instrumentations[id];
00806             s.count += increment;
00807             printInformationContinous(s,Duration());
00808         }
00809 
00810     }                            // namespace nestingAware
00811 
00812     #if defined(DLVHEX_BENCHMARK_SIMPLE)
00813     typedef simple::BenchmarkController BenchmarkController;
00814     #elif defined(DLVHEX_BENCHMARK_NESTINGAWARE)
00815     typedef nestingAware::NestingAwareController BenchmarkController;
00816     #else
00817     # error Benchmarking is defined but neither SIMPLE nor NESTINGAWARE is chosen!
00818     #endif
00819 
00820 }                                // namespace benchmark
00821 
00822 
00823 DLVHEX_NAMESPACE_END
00824 #endif                           // DLVHEX_H_BENCHMARKING_INCLUDED_1555
00825 
00826 
00827 // vim:expandtab:ts=4:sw=4:
00828 // mode: C++
00829 // End: