Skip to content

Commit 3438223

Browse files
WIP: Add pruning dead pid - draft static method
1 parent b6da372 commit 3438223

File tree

3 files changed

+68
-39
lines changed

3 files changed

+68
-39
lines changed

examples/cpp/pyperf/PyPerfNativeStackTrace.cc

+37-29
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <sys/uio.h>
99
#include <errno.h>
1010
#include <unistd.h>
11+
#include <cxxabi.h>
1112
#include <cstdio>
1213
#include <cstring>
1314
#include <sstream>
@@ -31,13 +32,15 @@ time_t NativeStackTrace::now;
3132
UnwindCache NativeStackTrace::cache;
3233

3334

35+
3436
NativeStackTrace::NativeStackTrace(uint32_t pid, const unsigned char *raw_stack,
3537
size_t stack_len, uintptr_t ip, uintptr_t sp) : error_occurred(false) {
3638
NativeStackTrace::stack = raw_stack;
3739
NativeStackTrace::stack_len = stack_len;
3840
NativeStackTrace::ip = ip;
3941
NativeStackTrace::sp = sp;
4042
NativeStackTrace::now = time(NULL);
43+
logInfo(2,"DEBUGIZA: Welcome in NativeStackTrace, pid=%d\n", pid);
4144

4245
if (stack_len == 0) {
4346
return;
@@ -56,11 +59,11 @@ NativeStackTrace::NativeStackTrace(uint32_t pid, const unsigned char *raw_stack,
5659
int res;
5760

5861
// Pseudo-proactive way of implementing TTL - whenever any call is made, all expired entries are removed
59-
cache_eviction(cache);
62+
cache_eviction();
6063

6164
// Check whether the entry for the process ID is presented in the cache
62-
if (!is_cached(cache, pid)) {
63-
logInfo(3,"The given key %d is not presented in the cache\n", pid);
65+
if (!is_cached(pid)) {
66+
logInfo(2,"The given key %d is not presented in the cache\n", pid);
6467

6568
as = unw_create_addr_space(&my_accessors, 0);
6669
upt = _UPT_create(pid);
@@ -82,12 +85,12 @@ NativeStackTrace::NativeStackTrace(uint32_t pid, const unsigned char *raw_stack,
8285
}
8386

8487
// Put to the cache
85-
cache_put(cache, pid, cursor, as, upt);
88+
cache_put(pid, cursor, as, upt);
8689

8790
} else {
88-
logInfo(3,"Found entry for the given key %d in the cache\n", pid);
91+
logInfo(2,"Found entry for the given key %d in the cache\n", pid);
8992
// Get from the cache
90-
UnwindCacheEntry cached_entry = cache_get(cache, pid);
93+
UnwindCacheEntry cached_entry = cache_get(pid);
9194
cursor = cached_entry.cursor;
9295
as = cached_entry.as;
9396
upt = cached_entry.upt;
@@ -137,6 +140,11 @@ NativeStackTrace::NativeStackTrace(uint32_t pid, const unsigned char *raw_stack,
137140

138141
}
139142

143+
void NativeStackTrace::Prune_dead_pid(uint32_t dead_pid) {
144+
logInfo(2, "DEBUGIZA: D. Try to call cache_delete %d\n", dead_pid);
145+
cache_delete_key(dead_pid);
146+
}
147+
140148
void NativeStackTrace::cleanup(void *upt, unw_addr_space_t as) {
141149
if (upt) {
142150
_UPT_destroy(upt);
@@ -230,75 +238,75 @@ bool NativeStackTrace::error_occured() const {
230238
return error_occurred;
231239
}
232240

233-
bool NativeStackTrace::is_cached(const UnwindCache &map, const uint32_t &key) {
241+
bool NativeStackTrace::is_cached(const uint32_t &key) {
234242
try {
235-
map.at(key);
243+
cache.at(key);
236244
return true;
237245
}
238246
catch (const std::out_of_range&) {
239-
logInfo(3, "No entry for %d in the cache\n", key);
247+
logInfo(2, "No entry for %d in the cache\n", key);
240248
}
241249
return false;
242250
}
243251

244-
UnwindCacheEntry NativeStackTrace::cache_get(const UnwindCache &map, const uint32_t &key) {
245-
const UnwindCacheEntry & entry = map.at(key);
252+
UnwindCacheEntry NativeStackTrace::cache_get(const uint32_t &key) {
253+
const UnwindCacheEntry & entry = cache.at(key);
246254
return entry;
247255
}
248256

249257
// cache_put adds a new entry to the unwind cache if the capacity allows
250-
void NativeStackTrace::cache_put(UnwindCache &mp, const uint32_t &key, const unw_cursor_t cursor, const unw_addr_space_t as, void *upt) {
258+
void NativeStackTrace::cache_put(const uint32_t &key, const unw_cursor_t cursor, const unw_addr_space_t as, void *upt) {
251259
// Check available capacity
252260
if (cache_size() > NativeStackTrace::CacheMaxSizeMB*1024*1024 - cache_single_entry_size()) {
253-
logInfo(3, "The cache usage is %.2f MB, close to reaching the max memory usage (%d MB)\n", cache_size_KB()/1024, NativeStackTrace::CacheMaxSizeMB);
254-
logInfo(3, "Skipping adding an entry for %d to the cache\n", key);
261+
logInfo(2, "The cache usage is %.2f MB, close to reaching the max memory usage (%d MB)\n", cache_size_KB()/1024, NativeStackTrace::CacheMaxSizeMB);
262+
logInfo(2, "Skipping adding an entry for %d to the cache\n", key);
255263
return;
256264
}
257265

258266
UnwindCacheEntry entry = {cursor, as, upt, now};
259-
mp[key] = entry;
260-
logInfo(3, "New entry for %d was added to the cache\n", key);
267+
cache[key] = entry;
268+
logInfo(2, "New entry for %d was added to the cache\n", key);
261269
}
262270

263271
// cache_delete_key removes the element from the cache and destroys unwind address space and UPT
264272
// to ensure that all memory and other resources are freed up
265-
bool NativeStackTrace::cache_delete_key(UnwindCache &mp, const uint32_t &key) {
273+
bool NativeStackTrace::cache_delete_key(const uint32_t &key) {
266274
UnwindCacheEntry e;
267275
try {
268-
e = cache_get(mp, key);
276+
e = cache_get(key);
269277
}
270278
catch (const std::out_of_range&) {
271-
logInfo(3, "Failed to delete entry for %d: no such key in the cache\n", key);
279+
logInfo(2, "Failed to delete entry for %d: no such key in the cache\n", key);
272280
return false;
273281
}
274282

275-
mp.erase(key);
283+
cache.erase(key);
276284
cleanup(e.upt, e.as);
277-
logInfo(3, "The entry for %d was deleted from the cache\n", key);
285+
logInfo(2, "The entry for %d was deleted from the cache\n", key);
278286
return true;
279287
}
280288

281289
// cache_single_entry_size returns the number of bytes taken by single entry
282-
uint32_t NativeStackTrace::cache_single_entry_size() const {
290+
uint32_t NativeStackTrace::cache_single_entry_size() {
283291
return sizeof(decltype(cache)::key_type) + sizeof(decltype(cache)::mapped_type);
284292
}
285293

286294
// cache_size returns the number of bytes currently in use by the cache
287-
uint32_t NativeStackTrace::cache_size() const {
295+
uint32_t NativeStackTrace::cache_size() {
288296
return sizeof(cache) + cache.size()*cache_single_entry_size();
289297
}
290298

291299
// cache_size_KB returns the number of kilobytes currently in use by the cache
292-
float NativeStackTrace::cache_size_KB() const {
300+
float NativeStackTrace::cache_size_KB() {
293301
return cache_size()/1024;
294302
}
295303

296304
// cache_eviction removes elements older than 5 minutes (CacheMaxTTL=300)
297-
void NativeStackTrace::cache_eviction(UnwindCache &mp) {
305+
void NativeStackTrace::cache_eviction() {
298306
std::vector<uint32_t> keys_to_delete;
299307
float _prev_cache_size = cache_size_KB();
300308

301-
for(std::map<uint32_t, UnwindCacheEntry>::iterator iter = mp.begin(); iter != mp.end(); ++iter)
309+
for(std::map<uint32_t, UnwindCacheEntry>::iterator iter = cache.begin(); iter != cache.end(); ++iter)
302310
{
303311
uint32_t k = iter->first;
304312
const UnwindCacheEntry & e = iter->second;
@@ -310,13 +318,13 @@ void NativeStackTrace::cache_eviction(UnwindCache &mp) {
310318

311319
// Delete expired entries
312320
for( size_t i = 0; i < keys_to_delete.size(); i++ ) {
313-
cache_delete_key(mp, keys_to_delete[i]);
321+
cache_delete_key(keys_to_delete[i]);
314322
}
315323

316324
if (keys_to_delete.size() > 0) {
317325
float _cache_size = cache_size_KB();
318-
logInfo(3,"Evicted %d item(s) from the cache\n", keys_to_delete.size());
319-
logInfo(3,"The cache usage after eviction action is %.2f KB (released %.2f KB)\n", _cache_size, _prev_cache_size - _cache_size);
326+
logInfo(2,"Evicted %d item(s) from the cache\n", keys_to_delete.size());
327+
logInfo(2,"The cache usage after eviction action is %.2f KB (released %.2f KB)\n", _cache_size, _prev_cache_size - _cache_size);
320328
}
321329
}
322330

examples/cpp/pyperf/PyPerfNativeStackTrace.h

+12-10
Original file line numberDiff line numberDiff line change
@@ -22,44 +22,46 @@ typedef struct {
2222

2323
typedef std::map<uint32_t, UnwindCacheEntry> UnwindCache;
2424

25+
2526
class NativeStackTrace {
2627
public:
2728
explicit NativeStackTrace(uint32_t pid, const uint8_t *raw_stack,
2829
size_t stack_len, uintptr_t ip, uintptr_t sp);
2930

31+
static void Prune_dead_pid(uint32_t dead_pid);
3032
std::vector<std::string> get_stack_symbol() const;
3133
bool error_occured() const;
3234
private:
3335
std::vector<std::string> symbols;
3436
bool error_occurred;
37+
static UnwindCache cache;
3538

3639
static const uint8_t *stack;
3740
static size_t stack_len;
3841
static uintptr_t ip;
3942
static uintptr_t sp;
4043
static time_t now;
4144

42-
static UnwindCache cache;
4345
static const uint16_t CacheMaxSizeMB;
4446
static const uint16_t CacheMaxTTL;
4547

46-
uint32_t cache_size() const;
47-
uint32_t cache_single_entry_size() const;
48-
float cache_size_KB() const;
48+
static uint32_t cache_size();
49+
static uint32_t cache_single_entry_size();
50+
static float cache_size_KB();
4951

5052
static int access_reg(unw_addr_space_t as, unw_regnum_t regnum,
5153
unw_word_t *valp, int write, void *arg);
5254

5355
static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp,
5456
int write, void *arg);
5557

56-
void cleanup(void *upt, unw_addr_space_t as);
58+
static void cleanup(void *upt, unw_addr_space_t as);
5759

58-
bool is_cached(const UnwindCache &map, const uint32_t &key);
59-
void cache_put(UnwindCache &map, const uint32_t &key, const unw_cursor_t cursor, const unw_addr_space_t as, void *upt);
60-
UnwindCacheEntry cache_get(const UnwindCache &map, const uint32_t &key);
61-
bool cache_delete_key(UnwindCache &map, const uint32_t &key);
62-
void cache_eviction(UnwindCache &map);
60+
bool is_cached(const uint32_t &key);
61+
void cache_put(const uint32_t &key, const unw_cursor_t cursor, const unw_addr_space_t as, void *upt);
62+
static UnwindCacheEntry cache_get(const uint32_t &key);
63+
static bool cache_delete_key(const uint32_t &key);
64+
static void cache_eviction();
6365
};
6466

6567
} // namespace pyperf

examples/cpp/pyperf/PyPerfProfiler.cc

+19
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "PyPerfLoggingHelper.h"
3030
#include "PyPerfVersion.h"
3131
#include "PyPerfProc.h"
32+
#include "PyPerfNativeStackTrace.h"
3233
#include "bcc_elf.h"
3334
#include "bcc_proc.h"
3435
#include "bcc_syms.h"
@@ -235,20 +236,38 @@ bool PyPerfProfiler::populatePidTable() {
235236
auto pid_config_map = bpf_.get_hash_table<int, PidData>(kPidCfgTableName);
236237

237238
logInfo(3, "Pruning dead pids\n");
239+
logInfo(2, "DEBUGIZA: Pruning dead pids\n");
238240
auto pid_config_keys = pid_config_map.get_keys_offline();
239241
for (const auto pid : pid_config_keys) {
242+
logInfo(2, "DEBUGIZA: Pruning dead pid=%d\n", pid);
240243
auto pos = std::find(pids.begin(), pids.end(), pid);
241244
if (pos == pids.end()) {
245+
// no element found
246+
logInfo(2, "DEBUGIZA: A. Pruning dead\n");
247+
logInfo(2, "DEBUGIZA: A1. sizeof(pid_config_map)=%d\n", pid_config_keys.size());
248+
logInfo(2, "DEBUGIZA: A1. sizeof(pids)=%d\n", pids.size());
242249
pid_config_map.remove_value(pid);
250+
NativeStackTrace::Prune_dead_pid(pid);
251+
// logInfo(2, "DEBUGIZA: A2. sizeof(pid_config_map)=%d\n", pid_config_map.size());
252+
logInfo(2, "DEBUGIZA: A2. sizeof(pids)=%d\n", pids.size());
243253
}
244254
else {
255+
logInfo(2, "DEBUGIZA: B Pruning dead wszedl\n");
245256
result = true;
257+
// logInfo(2, "DEBUGIZA: B1. sizeof(pid_config_map)=%d\n", pid_config_map.size);
258+
logInfo(2, "DEBUGIZA: B1. sizeof(pids)=%d\n", pids.size());
259+
260+
// erase to avoid re-population (see below)
246261
pids.erase(pos);
262+
// logInfo(2, "DEBUGIZA: B2. sizeof(pid_config_map)=%d\n", pid_config_map.size());
263+
logInfo(2, "DEBUGIZA: B2. sizeof(pids)=%d\n", pids.size());
264+
247265
}
248266
}
249267

250268
logInfo(3, "Populating pid table\n");
251269
for (const auto pid : pids) {
270+
// update only those pids that have not been observed before
252271
PidData pidData;
253272

254273
if (!tryTargetPid(pid, pidData)) {

0 commit comments

Comments
 (0)