Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 4 additions & 26 deletions ddtrace/internal/datadog/profiling/stack_v2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,30 +47,9 @@ if(NOT Threads_FOUND OR NOT CMAKE_USE_PTHREADS_INIT)
message(FATAL_ERROR "pthread compatible library not found")
endif()

# Add echion
set(ECHION_COMMIT
"43432c5c0a89617b06533215a15d0d6ffbbfd02b" # https://github.com/P403n1x87/echion/commit/43432c5c0a89617b06533215a15d0d6ffbbfd02b
CACHE STRING "Commit hash of echion to use")
FetchContent_Declare(
echion
GIT_REPOSITORY "https://github.com/P403n1x87/echion.git"
GIT_TAG ${ECHION_COMMIT})
FetchContent_GetProperties(echion)

if(NOT echion_POPULATED)
FetchContent_Populate(echion)
endif()

# Specify the target C-extension that we want to build
add_library(
${EXTENSION_NAME} SHARED
${echion_SOURCE_DIR}/echion/frame.cc
${echion_SOURCE_DIR}/echion/render.cc
${echion_SOURCE_DIR}/echion/danger.cc
src/sampler.cpp
src/stack_renderer.cpp
src/stack_v2.cpp
src/thread_span_links.cpp)
add_library(${EXTENSION_NAME} SHARED src/echion/danger.cc src/echion/frame.cc src/sampler.cpp src/stack_renderer.cpp
src/stack_v2.cpp src/thread_span_links.cpp)

# Add common config
add_ddup_config(${EXTENSION_NAME})
Expand All @@ -82,7 +61,6 @@ add_cppcheck_target(
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/include/util
${CMAKE_CURRENT_SOURCE_DIR}/..
${echion_SOURCE_DIR}
SRC
${CMAKE_CURRENT_SOURCE_DIR}/src)

Expand All @@ -93,8 +71,8 @@ target_compile_definitions(${EXTENSION_NAME} PRIVATE UNWIND_NATIVE_DISABLE)
target_include_directories(
${EXTENSION_NAME} PRIVATE .. # include dd_wrapper from the root in order to make its paths transparent in the code
include)
target_include_directories(${EXTENSION_NAME} SYSTEM PRIVATE ${echion_SOURCE_DIR} ${Python3_INCLUDE_DIRS}
include/vendored include/util)
target_include_directories(${EXTENSION_NAME} SYSTEM PRIVATE ${Python3_INCLUDE_DIRS} echion include/vendored
include/util)

# Echion sources need to be given the current platform
if(APPLE)
Expand Down
110 changes: 110 additions & 0 deletions ddtrace/internal/datadog/profiling/stack_v2/echion/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
Language: Cpp
BasedOnStyle: Google
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: Never
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// This file is part of "echion" which is released under MIT.
//
// Copyright (c) 2023 Gabriele N. Tornetta <phoenix1987@gmail.com>.

#pragma once

#include <functional>
#include <list>
#include <memory>
#include <unordered_map>

#include <echion/errors.h>

#define CACHE_MAX_ENTRIES 2048

template <typename K, typename V>
class LRUCache
{
public:
LRUCache(size_t capacity) : capacity(capacity) {}

Result<std::reference_wrapper<V>> lookup(const K& k);

void store(const K& k, std::unique_ptr<V> v);

private:
size_t capacity;
std::list<std::pair<K, std::unique_ptr<V>>> items;
std::unordered_map<K, typename std::list<std::pair<K, std::unique_ptr<V>>>::iterator> index;
};

template <typename K, typename V>
void LRUCache<K, V>::store(const K& k, std::unique_ptr<V> v)
{
// Check if cache is full
if (items.size() >= capacity)
{
index.erase(items.back().first);
items.pop_back();
}

// Insert the new item at front of the list
items.emplace_front(k, std::move(v));

// Insert in the map
index[k] = items.begin();
}

template <typename K, typename V>
Result<std::reference_wrapper<V>> LRUCache<K, V>::lookup(const K& k)
{
auto itr = index.find(k);
if (itr == index.end())
return ErrorKind::LookupError;

// Move to the front of the list
items.splice(items.begin(), items, itr->second);

return std::reference_wrapper<V>(*(itr->second->second.get()));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// This file is part of "echion" which is released under MIT.
//
// Copyright (c) 2023 Gabriele N. Tornetta <phoenix1987@gmail.com>.

#pragma once

#define PY_SSIZE_T_CLEAN
#include <Python.h>

// Sampling interval
inline unsigned int interval = 1000;

// CPU Time mode
inline int cpu = 0;

// For cpu time mode, Echion only unwinds threads that're running by default.
// Set this to false to unwind all threads.
inline bool ignore_non_running_threads = true;

// Maximum number of frames to unwind
inline unsigned int max_frames = 2048;

// ----------------------------------------------------------------------------
static PyObject* set_interval(PyObject* Py_UNUSED(m), PyObject* args)
{
unsigned int new_interval;
if (!PyArg_ParseTuple(args, "I", &new_interval))
return NULL;

interval = new_interval;

Py_RETURN_NONE;
}

// ----------------------------------------------------------------------------
inline void _set_cpu(int new_cpu)
{
cpu = new_cpu;
}

// ----------------------------------------------------------------------------
inline void _set_ignore_non_running_threads(bool new_ignore_non_running_threads)
{
ignore_non_running_threads = new_ignore_non_running_threads;
}

// ----------------------------------------------------------------------------
static PyObject* set_cpu(PyObject* Py_UNUSED(m), PyObject* args)
{
int new_cpu;
if (!PyArg_ParseTuple(args, "p", &new_cpu))
return NULL;

_set_cpu(new_cpu);

Py_RETURN_NONE;
}

// ----------------------------------------------------------------------------
static PyObject* set_max_frames(PyObject* Py_UNUSED(m), PyObject* args)
{
unsigned int new_max_frames;
if (!PyArg_ParseTuple(args, "I", &new_max_frames))
return NULL;

max_frames = new_max_frames;

Py_RETURN_NONE;
}
Loading
Loading