ardupilot/libraries/AP_HAL_Linux/Perf.h
Lucas De Marchi 619ce23799 AP_HAL_Linux: Perf: rework integration with other tools
The idea is to leave the internal perf enabled all the time, like it is
in PX4, and then allow the integration with lttng on top. Next step
would be to runtime enable/disable only the perf counters we are
interested in.

This also changes the structure so it's easy to allow another thread to
pull data from the Perf object. A rw lock protects from addition of new
counters and an atomic unsigned int allows other threads to do a
lockless copy of the data.

In order for this to work the allocation was changed to use a single
memory pool instead of returning a calloc'ed data for each perf counter.
Since most of our counters are of ' elapsed' type, don't bother using a
smaller struct for the 'count' type
2016-06-23 19:06:30 -03:00

98 lines
2.3 KiB
C++

/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
/*
* Copyright (C) 2016 Intel Corporation. All rights reserved.
*
* This file is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This file 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <atomic>
#include <limits.h>
#include <pthread.h>
#include <vector>
#include "AP_HAL_Linux.h"
#include "Perf_Lttng.h"
#include "Thread.h"
#include "Util.h"
namespace Linux {
class Perf_Counter {
using perf_counter_type = AP_HAL::Util::perf_counter_type;
using perf_counter_t = AP_HAL::Util::perf_counter_t;
public:
Perf_Counter(perf_counter_type type_, const char *name_)
: name{name_}
, type{type_}
#ifdef HAVE_LTTNG_UST
, lttng{name_}
#endif
, least{ULONG_MAX}
{
}
const char *name;
#ifdef HAVE_LTTNG_UST
Perf_Lttng lttng;
#endif
perf_counter_type type;
uint64_t count;
/* Everything below is in nanoseconds */
uint64_t start;
uint64_t total;
uint64_t least;
uint64_t most;
double mean;
double m2;
};
class Perf {
using perf_counter_type = AP_HAL::Util::perf_counter_type;
using perf_counter_t = AP_HAL::Util::perf_counter_t;
public:
~Perf();
static Perf *get_instance();
perf_counter_t add(perf_counter_type type, const char *name);
void begin(perf_counter_t pc);
void end(perf_counter_t pc);
void count(perf_counter_t pc);
unsigned int get_update_count() { return _update_count; }
private:
static Perf *_instance;
Perf();
std::vector<Perf_Counter> _perf_counters;
/* synchronize addition of new perf counters */
pthread_rwlock_t _perf_counters_lock;
/* allow to check if memory pool has changed */
std::atomic<unsigned int> _update_count;
};
}