mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
change StoringTimer to be thread safe and use fixed char strings to identify timing points
This may not be at all useful, but the existing implementation was completely useless because of a lack of thread safety
This commit is contained in:
parent
7ce43739e8
commit
0dddd75429
6 changed files with 72 additions and 36 deletions
|
|
@ -21,6 +21,7 @@
|
||||||
#ifndef __ardour_cycle_timer_h__
|
#ifndef __ardour_cycle_timer_h__
|
||||||
#define __ardour_cycle_timer_h__
|
#define __ardour_cycle_timer_h__
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
@ -68,31 +69,38 @@ class LIBARDOUR_API CycleTimer {
|
||||||
class LIBARDOUR_API StoringTimer
|
class LIBARDOUR_API StoringTimer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StoringTimer (int);
|
StoringTimer ();
|
||||||
void ref ();
|
void ref ();
|
||||||
void check (int);
|
void check (char const * const what);
|
||||||
#ifndef NDEBUG
|
void dump (std::ostream&);
|
||||||
void dump (std::string const &);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
static void dump_all (std::string const &);
|
||||||
|
static StoringTimer* thread_st();
|
||||||
|
static void dump_all ();
|
||||||
|
|
||||||
|
private:
|
||||||
cycles_t _current_ref;
|
cycles_t _current_ref;
|
||||||
int* _point;
|
|
||||||
|
char const * const thread;
|
||||||
|
char const ** _what;
|
||||||
cycles_t* _value;
|
cycles_t* _value;
|
||||||
cycles_t* _ref;
|
cycles_t* _ref;
|
||||||
int _points;
|
int _points;
|
||||||
int _max_points;
|
|
||||||
|
static int _max_points;
|
||||||
|
static StoringTimer* all_timers[2048]; /* size relates to thread count */
|
||||||
|
static std::atomic<int> st_cnt;
|
||||||
|
thread_local static int st_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef PT_TIMING
|
#ifdef PT_TIMING
|
||||||
extern StoringTimer ST;
|
#define PT_TIMING_REF StoringTimer::thread_st()->ref();
|
||||||
#define PT_TIMING_REF ST.ref();
|
#define PT_TIMING_CHECK(w) StoringTimer::thread_st()->check(w);
|
||||||
#define PT_TIMING_CHECK(x) ST.check(x);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PT_TIMING
|
#ifndef PT_TIMING
|
||||||
#define PT_TIMING_REF
|
#define PT_TIMING_REF
|
||||||
#define PT_TIMING_CHECK(x)
|
#define PT_TIMING_CHECK(w)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __ardour_cycle_timer_h__ */
|
#endif /* __ardour_cycle_timer_h__ */
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@ AudioEngine::process_callback (pframes_t nframes)
|
||||||
Port::set_speed_ratio (1.0);
|
Port::set_speed_ratio (1.0);
|
||||||
|
|
||||||
PT_TIMING_REF;
|
PT_TIMING_REF;
|
||||||
PT_TIMING_CHECK (1);
|
PT_TIMING_CHECK ("process callback in");
|
||||||
|
|
||||||
/// The number of samples that will have been processed when we've finished
|
/// The number of samples that will have been processed when we've finished
|
||||||
pframes_t next_processed_samples;
|
pframes_t next_processed_samples;
|
||||||
|
|
@ -588,7 +588,7 @@ AudioEngine::process_callback (pframes_t nframes)
|
||||||
|
|
||||||
_processed_samples = next_processed_samples;
|
_processed_samples = next_processed_samples;
|
||||||
|
|
||||||
PT_TIMING_CHECK (2);
|
PT_TIMING_CHECK ("process callback out");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "pbd/error.h"
|
#include "pbd/error.h"
|
||||||
|
#include "pbd/pthread_utils.h"
|
||||||
#include "ardour/cycle_timer.h"
|
#include "ardour/cycle_timer.h"
|
||||||
|
|
||||||
#include "ardour/libardour_visibility.h"
|
#include "ardour/libardour_visibility.h"
|
||||||
|
|
@ -78,28 +79,45 @@ get_mhz()
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
StoringTimer::StoringTimer (int N)
|
int StoringTimer::_max_points = 64 * 1024;
|
||||||
|
StoringTimer* StoringTimer::all_timers[2048];
|
||||||
|
std::atomic<int> StoringTimer::st_cnt;
|
||||||
|
|
||||||
|
thread_local int StoringTimer::st_index = st_cnt.fetch_add (1);
|
||||||
|
|
||||||
|
StoringTimer::StoringTimer ()
|
||||||
|
: thread (strdup (pthread_name()))
|
||||||
{
|
{
|
||||||
_point = new int[N];
|
_what = new char const *[_max_points];
|
||||||
_value = new cycles_t[N];
|
_value = new cycles_t[_max_points];
|
||||||
_ref = new cycles_t[N];
|
_ref = new cycles_t[_max_points] ;
|
||||||
_max_points = N;
|
|
||||||
_points = 0;
|
_points = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
void
|
void
|
||||||
StoringTimer::dump (string const & file)
|
StoringTimer::dump_all (string const & file)
|
||||||
{
|
{
|
||||||
ofstream f (file.c_str ());
|
ofstream f (file.c_str ());
|
||||||
|
|
||||||
f << min (_points, _max_points) << "\n";
|
|
||||||
f << get_mhz () << "\n";
|
f << get_mhz () << "\n";
|
||||||
for (int i = 0; i < min (_points, _max_points); ++i) {
|
f << "There were " << st_cnt.load() << " thread timers\n";
|
||||||
f << _point[i] << " " << _ref[i] << " " << _value[i] << "\n";
|
|
||||||
|
for (size_t i = 0; i < (sizeof (all_timers) / sizeof (all_timers[0])); ++i) {
|
||||||
|
if (all_timers[i]) {
|
||||||
|
all_timers[i]->dump (f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StoringTimer::dump (std::ostream& f)
|
||||||
|
{
|
||||||
|
f << thread << ' ' << _points << "\n";
|
||||||
|
|
||||||
|
for (int i = 0; i < min (_points, _max_points); ++i) {
|
||||||
|
f << '\t' << _what[i] << " " << _ref[i] << " " << _value[i] << " delta " << _value[i] - _ref[i] << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
StoringTimer::ref ()
|
StoringTimer::ref ()
|
||||||
|
|
@ -108,8 +126,10 @@ StoringTimer::ref ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
StoringTimer::check (int p)
|
StoringTimer::check (char const * const what)
|
||||||
{
|
{
|
||||||
|
cerr << pthread_name() << " @ " << pthread_self() << ' ' << thread << " check " << what << " @ " << _points << endl;
|
||||||
|
|
||||||
if (_points == _max_points) {
|
if (_points == _max_points) {
|
||||||
++_points;
|
++_points;
|
||||||
return;
|
return;
|
||||||
|
|
@ -117,15 +137,20 @@ StoringTimer::check (int p)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_point[_points] = p;
|
_what[_points] = what;
|
||||||
_value[_points] = get_cycles ();
|
_value[_points] = get_cycles ();
|
||||||
_ref[_points] = _current_ref;
|
_ref[_points] = _current_ref;
|
||||||
|
|
||||||
++_points;
|
++_points;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PT_TIMING
|
StoringTimer*
|
||||||
StoringTimer ST (64 * 1024);
|
StoringTimer::thread_st()
|
||||||
#endif
|
{
|
||||||
|
if (all_timers[st_index] == 0) {
|
||||||
|
all_timers[st_index] = new StoringTimer;
|
||||||
|
}
|
||||||
|
return all_timers[st_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@
|
||||||
#include "ardour/buffer_set.h"
|
#include "ardour/buffer_set.h"
|
||||||
#include "ardour/capturing_processor.h"
|
#include "ardour/capturing_processor.h"
|
||||||
#include "ardour/debug.h"
|
#include "ardour/debug.h"
|
||||||
|
#include "ardour/cycle_timer.h"
|
||||||
#include "ardour/delivery.h"
|
#include "ardour/delivery.h"
|
||||||
#include "ardour/disk_reader.h"
|
#include "ardour/disk_reader.h"
|
||||||
#include "ardour/disk_writer.h"
|
#include "ardour/disk_writer.h"
|
||||||
|
|
@ -345,6 +346,7 @@ Route::process_output_buffers (BufferSet& bufs,
|
||||||
samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes,
|
samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes,
|
||||||
bool gain_automation_ok, bool run_disk_reader)
|
bool gain_automation_ok, bool run_disk_reader)
|
||||||
{
|
{
|
||||||
|
PT_TIMING_CHECK ("route-pob-in");
|
||||||
/* Caller must hold process lock */
|
/* Caller must hold process lock */
|
||||||
assert (!AudioEngine::instance()->process_lock().trylock());
|
assert (!AudioEngine::instance()->process_lock().trylock());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@
|
||||||
#include "ardour/butler.h"
|
#include "ardour/butler.h"
|
||||||
#include "ardour/click.h"
|
#include "ardour/click.h"
|
||||||
#include "ardour/control_protocol_manager.h"
|
#include "ardour/control_protocol_manager.h"
|
||||||
|
#include "ardour/cycle_timer.h"
|
||||||
#include "ardour/data_type.h"
|
#include "ardour/data_type.h"
|
||||||
#include "ardour/debug.h"
|
#include "ardour/debug.h"
|
||||||
#include "ardour/disk_reader.h"
|
#include "ardour/disk_reader.h"
|
||||||
|
|
@ -502,7 +503,7 @@ Session::Session (AudioEngine &eng,
|
||||||
Session::~Session ()
|
Session::~Session ()
|
||||||
{
|
{
|
||||||
#ifdef PT_TIMING
|
#ifdef PT_TIMING
|
||||||
ST.dump ("ST.dump");
|
StoringTimer::dump_all ("ST.dump");
|
||||||
#endif
|
#endif
|
||||||
destroy ();
|
destroy ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ Session::fail_roll (pframes_t nframes)
|
||||||
int
|
int
|
||||||
Session::no_roll (pframes_t nframes)
|
Session::no_roll (pframes_t nframes)
|
||||||
{
|
{
|
||||||
PT_TIMING_CHECK (4);
|
PT_TIMING_CHECK ("no roll in");
|
||||||
|
|
||||||
samplepos_t end_sample = _transport_sample + floor (nframes * _transport_fsm->transport_speed());
|
samplepos_t end_sample = _transport_sample + floor (nframes * _transport_fsm->transport_speed());
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
@ -186,7 +186,7 @@ Session::no_roll (pframes_t nframes)
|
||||||
DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
|
DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
|
||||||
_process_graph->routes_no_roll( nframes, _transport_sample, end_sample, non_realtime_work_pending());
|
_process_graph->routes_no_roll( nframes, _transport_sample, end_sample, non_realtime_work_pending());
|
||||||
} else {
|
} else {
|
||||||
PT_TIMING_CHECK (10);
|
PT_TIMING_CHECK ("nograph no roll in");
|
||||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||||
|
|
||||||
if ((*i)->is_auditioner()) {
|
if ((*i)->is_auditioner()) {
|
||||||
|
|
@ -199,10 +199,10 @@ Session::no_roll (pframes_t nframes)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PT_TIMING_CHECK (11);
|
PT_TIMING_CHECK ("nograph no roll out");
|
||||||
}
|
}
|
||||||
|
|
||||||
PT_TIMING_CHECK (5);
|
PT_TIMING_CHECK ("no roll out");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -330,7 +330,7 @@ Session::calc_preroll_subcycle (samplecnt_t ns) const
|
||||||
void
|
void
|
||||||
Session::process_with_events (pframes_t nframes)
|
Session::process_with_events (pframes_t nframes)
|
||||||
{
|
{
|
||||||
PT_TIMING_CHECK (3);
|
PT_TIMING_CHECK ("p-with-e in");
|
||||||
|
|
||||||
SessionEvent* ev;
|
SessionEvent* ev;
|
||||||
pframes_t this_nframes;
|
pframes_t this_nframes;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue