You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
9.4 KiB
C++
241 lines
9.4 KiB
C++
/*
|
|
Copyright 2005-2014 Intel Corporation. All Rights Reserved.
|
|
|
|
This file is part of Threading Building Blocks. Threading Building Blocks is free software;
|
|
you can redistribute it and/or modify it under the terms of the GNU General Public License
|
|
version 2 as published by the Free Software Foundation. Threading Building Blocks is
|
|
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
See the GNU General Public License for more details. You should have received a copy of
|
|
the GNU General Public License along with Threading Building Blocks; if not, write to the
|
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
As a special exception, you may use this file as part of a free software library without
|
|
restriction. Specifically, if other files instantiate templates or use macros or inline
|
|
functions from this file, or you compile this file and link it with other files to produce
|
|
an executable, this file does not by itself cause the resulting executable to be covered
|
|
by the GNU General Public License. This exception does not however invalidate any other
|
|
reasons why the executable file might be covered by the GNU General Public License.
|
|
*/
|
|
|
|
#ifndef _TBB_tbb_statistics_H
|
|
#define _TBB_tbb_statistics_H
|
|
|
|
/**
|
|
This file defines parameters of the internal statistics collected by the TBB
|
|
library (currently by the task scheduler only).
|
|
|
|
Statistics is accumulated separately in each thread and is dumped when
|
|
the scheduler instance associated with the given thread is destroyed.
|
|
For apps with multiple master threads or with the same master repeatedly
|
|
initializing and then deinitializing task scheduler this results in TBB
|
|
workers statistics getting inseparably mixed.
|
|
|
|
Therefore statistics is accumulated in arena slots, and should be dumped
|
|
when arena is destroyed. This separates statistics collected for each
|
|
scheduler activity region in each master thread.
|
|
|
|
With the current RML implementation (TBB 2.2, 3.0) to avoid complete loss of
|
|
statistics data during app shutdown (because of lazy workers deinitialization
|
|
logic) set __TBB_STATISTICS_EARLY_DUMP macro to write the statistics at the
|
|
moment a master thread deinitializes its scheduler. This may happen a little
|
|
earlier than the moment of arena destruction resulting in the following undesired
|
|
(though usually tolerable) effects:
|
|
- a few events related to unsuccessful stealing or thread pool activity may be lost,
|
|
- statistics may be substantially incomplete in case of FIFO tasks used in
|
|
the FAF mode.
|
|
|
|
Macro __TBB_STATISTICS_STDOUT and global variable __TBB_ActiveStatisticsGroups
|
|
defined below can be used to configure the statistics output.
|
|
|
|
To add new counter:
|
|
1) Insert it into the appropriate group range in statistics_counters;
|
|
2) Insert the corresponding field title into StatFieldTitles (preserving
|
|
relative order of the fields).
|
|
|
|
To add new counters group:
|
|
1) Insert new group bit flag into statistics_groups;
|
|
2) Insert the new group title into StatGroupTitles (preserving
|
|
relative order of the groups).
|
|
3) Add counter belonging to the new group as described above
|
|
**/
|
|
|
|
#include "tbb/tbb_stddef.h"
|
|
|
|
#ifndef __TBB_STATISTICS
|
|
#define __TBB_STATISTICS 0
|
|
#endif /* __TBB_STATISTICS */
|
|
|
|
#if __TBB_STATISTICS
|
|
|
|
#include <string.h> // for memset
|
|
|
|
//! Dump counters into stdout as well.
|
|
/** By default statistics counters are written to the file "statistics.txt" only. **/
|
|
#define __TBB_STATISTICS_STDOUT 1
|
|
|
|
//! Dump only totals for all threads in the given arena
|
|
/** By default statistics counters for each arena slot are dumped separately, as
|
|
well as the subtotal for workers. **/
|
|
#define __TBB_STATISTICS_TOTALS_ONLY 1
|
|
|
|
//! Dump statistics for an arena when its master completes
|
|
/** By default (when this macro is not set) the statistics is sent to output when
|
|
arena object is destroyed. But with the current lazy workers termination
|
|
logic default behavior may result in loosing all statistics output. **/
|
|
#define __TBB_STATISTICS_EARLY_DUMP 1
|
|
|
|
#define GATHER_STATISTIC(x) (x)
|
|
|
|
namespace tbb {
|
|
namespace internal {
|
|
|
|
//! Groups of statistics counters.
|
|
/** The order of enumerators must be the same as the order of the corresponding
|
|
field groups in the statistics_counters structure. **/
|
|
enum statistics_groups {
|
|
sg_task_allocation = 0x01,
|
|
sg_task_execution = 0x02,
|
|
sg_stealing = 0x04,
|
|
sg_affinity = 0x08,
|
|
sg_arena = 0x10,
|
|
sg_market = 0x20,
|
|
sg_prio = 0x40,
|
|
sg_prio_ex = 0x80,
|
|
// List end marker. Insert new groups only before it.
|
|
sg_end
|
|
};
|
|
|
|
//! Groups of counters to output
|
|
const uintptr_t __TBB_ActiveStatisticsGroups = sg_task_execution | sg_stealing | sg_affinity | sg_arena | sg_market;
|
|
|
|
//! A set of various statistics counters that are updated by the library on per thread basis.
|
|
/** All the fields must be of the same type (statistics_counters::counter_type).
|
|
This is necessary to allow reinterpreting this structure as an array. **/
|
|
struct statistics_counters {
|
|
typedef long counter_type;
|
|
|
|
// Group: sg_task_allocation
|
|
// Counters in this group can have negative values as the tasks migrate across
|
|
// threads while the associated counters are updated in the current thread only
|
|
// to avoid data races
|
|
|
|
//! Number of tasks allocated and not yet destroyed
|
|
counter_type active_tasks;
|
|
//! Number of task corpses stored for future reuse
|
|
counter_type free_list_length;
|
|
//! Number of big tasks allocated during the run
|
|
/** To find total number of tasks malloc'd, compute (big_tasks+my_small_task_count) */
|
|
counter_type big_tasks;
|
|
|
|
// Group: sg_task_execution
|
|
|
|
//! Number of tasks executed
|
|
counter_type tasks_executed;
|
|
//! Number of elided spawns
|
|
counter_type spawns_bypassed;
|
|
|
|
// Group: sg_stealing
|
|
|
|
//! Number of tasks successfully stolen
|
|
counter_type steals_committed;
|
|
//! Number of failed stealing attempts
|
|
counter_type steals_failed;
|
|
//! Number of failed attempts to lock victim's task pool
|
|
counter_type thieves_conflicts;
|
|
//! Number of times thief backed off because of the collision with the owner
|
|
counter_type thief_backoffs;
|
|
|
|
// Group: sg_affinity
|
|
|
|
//! Number of tasks received from mailbox
|
|
counter_type mails_received;
|
|
//! Number of affinitized tasks executed by the owner
|
|
/** Goes as "revoked" in statistics printout. **/
|
|
counter_type proxies_executed;
|
|
//! Number of affinitized tasks intercepted by thieves
|
|
counter_type proxies_stolen;
|
|
//! Number of proxy bypasses by thieves during stealing
|
|
counter_type proxies_bypassed;
|
|
//! Number of affinitized tasks executed by the owner via scheduler bypass mechanism
|
|
counter_type affinity_ignored;
|
|
|
|
// Group: sg_arena
|
|
|
|
//! Number of times the state of arena switched between "full" and "empty"
|
|
counter_type gate_switches;
|
|
//! Number of times workers left an arena and returned into the market
|
|
counter_type arena_roundtrips;
|
|
// !Average concurrency level of this arena
|
|
counter_type avg_arena_concurrency;
|
|
//! Average assigned priority
|
|
counter_type avg_assigned_workers;
|
|
|
|
// Group: sg_market
|
|
|
|
//! Number of times workers left the market and returned into RML
|
|
counter_type market_roundtrips;
|
|
|
|
// Group; sg_prio
|
|
|
|
//! Number of arena priority switches
|
|
counter_type arena_prio_switches;
|
|
//! Number of market priority switches
|
|
counter_type market_prio_switches;
|
|
//! Number of arena priority switches
|
|
counter_type arena_prio_resets;
|
|
//! Number of reference priority source fixups to avoid deadlock
|
|
counter_type prio_ref_fixups;
|
|
//! Average arena priority
|
|
counter_type avg_arena_prio;
|
|
//! Average market priority
|
|
counter_type avg_market_prio;
|
|
|
|
// Group; sg_prio_ex
|
|
|
|
//! Number of times local task pools were winnowed
|
|
counter_type prio_winnowings;
|
|
//! Number of times secondary task pools were searched for top priority tasks
|
|
counter_type prio_reloads;
|
|
//! Number of times secondary task pools were abandoned by quitting workers
|
|
counter_type prio_orphanings;
|
|
//! Number of tasks offloaded into secondary task pools
|
|
counter_type prio_tasks_offloaded;
|
|
//! Number of tasks reloaded from secondary task pools
|
|
counter_type prio_tasks_reloaded;
|
|
|
|
// Constructor and helpers
|
|
|
|
statistics_counters() { reset(); }
|
|
|
|
void reset () { memset( this, 0, sizeof(statistics_counters) ); }
|
|
|
|
counter_type& field ( size_t index ) { return reinterpret_cast<counter_type*>(this)[index]; }
|
|
|
|
const counter_type& field ( size_t index ) const { return reinterpret_cast<const counter_type*>(this)[index]; }
|
|
|
|
static size_t size () { return sizeof(statistics_counters) / sizeof(counter_type); }
|
|
|
|
const statistics_counters& operator += ( const statistics_counters& rhs ) {
|
|
for ( size_t i = 0; i < size(); ++i )
|
|
field(i) += rhs.field(i);
|
|
return *this;
|
|
}
|
|
}; // statistics_counters
|
|
|
|
static const size_t workers_counters_total = (size_t)-1;
|
|
static const size_t arena_counters_total = (size_t)-2;
|
|
|
|
void dump_statistics ( const statistics_counters& c, size_t id );
|
|
|
|
} // namespace internal
|
|
} // namespace tbb
|
|
|
|
#else /* !__TBB_STATISTICS */
|
|
|
|
#define GATHER_STATISTIC(x) ((void)0)
|
|
|
|
#endif /* !__TBB_STATISTICS */
|
|
|
|
#endif /* _TBB_tbb_statistics_H */
|