Skip to content

Commit

Permalink
Merge pull request #60 from albertziegenhagel/tools
Browse files Browse the repository at this point in the history
Improve tools
  • Loading branch information
albertziegenhagel committed May 1, 2024
2 parents 6d03ff8 + b1cc22f commit d1e4a7b
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ jobs:
with:
name: snail-tools-${{ matrix.arch }}-${{ matrix.platform }}
path: |
${{ github.workspace }}/install/tools/bin/app_*
${{ github.workspace }}/install/tools/bin/snail-tool-*
${{ github.workspace }}/install/tools/bin/info.txt
deploy-head:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/clang-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Run clang-format
uses: DoozyX/clang-format-lint-action@v0.16.2
with:
source: './snail ./tests ./apps'
source: './snail ./tests ./tools'
exclude: './snail/common/third_party'
extensions: 'cpp,hpp'
clangFormatVersion: 16
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ add_subdirectory(snail)

if(SNAIL_BUILD_TOOLS)
# Just for testing/development
add_subdirectory(apps)
add_subdirectory(tools)
endif()

# =======
Expand Down
20 changes: 0 additions & 20 deletions apps/CMakeLists.txt

This file was deleted.

54 changes: 41 additions & 13 deletions snail/etl/etl_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <iostream>
#include <queue>
#include <stdexcept>
#include <utility>

#include <snail/common/cast.hpp>

Expand Down Expand Up @@ -67,7 +68,9 @@ struct next_event_priority_info

buffer_info read_buffer(std::ifstream& file_stream,
std::streampos buffer_start_pos,
std::array<std::byte, max_buffer_size>& buffer_data)
std::array<std::byte, max_buffer_size>& buffer_data,
const etl_file::header_data& file_header_,
event_observer& callbacks)
{
file_stream.seekg(buffer_start_pos);
file_stream.read(reinterpret_cast<char*>(buffer_data.data()), common::narrow_cast<std::streamsize>(buffer_data.size()));
Expand All @@ -86,6 +89,8 @@ buffer_info read_buffer(std::ifstream& file_stream,

const auto header = parser::wmi_buffer_header_view(header_buffer);

callbacks.handle_buffer(file_header_, header);

if(header.wnode().buffer_size() > total_buffer.size())
{
throw std::runtime_error(std::format(
Expand All @@ -101,6 +106,13 @@ buffer_info read_buffer(std::ifstream& file_stream,
read_bytes));
}

if((header.buffer_flag() & std::to_underlying(parser::etw_buffer_flag::compressed)) != 0)
{
throw std::runtime_error(std::format(
"Unsupported ETL file: Buffer {} is marked as compressed, but compressed buffers are not yet supported.",
header.wnode().sequence_number()));
}

const auto payload_size = header.wnode().saved_offset() - parser::wmi_buffer_header_view::static_size;
const auto payload_buffer = total_buffer.subspan(parser::wmi_buffer_header_view::static_size, payload_size);

Expand Down Expand Up @@ -303,25 +315,37 @@ void etl_file::open(const std::filesystem::path& file_path)

const auto buffer_header = parser::wmi_buffer_header_view(file_buffer);

assert(buffer_header.buffer_type() == parser::etw_buffer_type::header);
if(buffer_header.buffer_type() != parser::etw_buffer_type::header)
{
throw std::runtime_error("Invalid ETL file: invalid buffer header type");
}

if(read_bytes < buffer_header.wnode().saved_offset())
{
throw std::runtime_error("Invalid ETL file: insufficient size for buffer");
}

[[maybe_unused]] const auto marker = parser::generic_trace_marker_view(file_buffer.subspan(parser::wmi_buffer_header_view::static_size));
assert(marker.is_trace_header() && marker.is_trace_header_event_trace() && !marker.is_trace_message());
assert(marker.header_type() == parser::trace_header_type::system32 ||
marker.header_type() == parser::trace_header_type::system64);
const auto marker = parser::generic_trace_marker_view(file_buffer.subspan(parser::wmi_buffer_header_view::static_size));
if(!marker.is_trace_header() || !marker.is_trace_header_event_trace() || marker.is_trace_message())
{
throw std::runtime_error("Invalid ETL file: invalid trace marker");
}
if(marker.header_type() != parser::trace_header_type::system32 &&
marker.header_type() != parser::trace_header_type::system64)
{
throw std::runtime_error("Invalid ETL file: invalid trace header type");
}

const auto system_trace_header = parser::system_trace_header_view(file_buffer.subspan(
parser::wmi_buffer_header_view::static_size));

// the first record needs to be a event-trace-header
assert(system_trace_header.packet().group() == parser::event_trace_group::header);
assert(system_trace_header.packet().type() == 0);
assert(system_trace_header.version() == 2);
if(system_trace_header.packet().group() != parser::event_trace_group::header ||
system_trace_header.packet().type() != 0 ||
system_trace_header.version() != 2)
{
throw std::runtime_error("Invalid ETL file: invalid initial event trace header record.");
}

const auto header_event = parser::event_trace_v2_header_event_view(file_buffer.subspan(
parser::wmi_buffer_header_view::static_size +
Expand Down Expand Up @@ -419,7 +443,10 @@ void etl_file::process(event_observer& callbacks)

processor_data.current_buffer_info = read_buffer(file_stream_,
remaining_buffers.back().start_pos,
processor_data.current_buffer_data);
processor_data.current_buffer_data,
header_,
callbacks);

remaining_buffers.pop_back();

event_queue.push(next_event_priority_info{
Expand Down Expand Up @@ -454,8 +481,6 @@ void etl_file::process(event_observer& callbacks)
const auto buffer_exhausted = buffer_info.current_payload_offset >= buffer_info.payload_buffer.size();
if(buffer_exhausted)
{
callbacks.handle_buffer(header_, parser::wmi_buffer_header_view(buffer_info.header_buffer));

auto& remaining_buffers = processor_data.remaining_buffers;

// If there are no remaining buffers for this processor, stop extracting events for it.
Expand All @@ -465,7 +490,10 @@ void etl_file::process(event_observer& callbacks)
// Keep in mind, that `remaining_buffers` is sorted.
buffer_info = read_buffer(file_stream_,
remaining_buffers.back().start_pos,
processor_data.current_buffer_data);
processor_data.current_buffer_data,
header_,
callbacks);

remaining_buffers.pop_back();
}

Expand Down
2 changes: 1 addition & 1 deletion third-party/gtest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG b796f7d44681514f58a683a3a71ff17c94edb0c1 # v1.13.0
GIT_TAG f8d7d77c06936315286eb55f8de22cd23c188571 # v1.14.0
SYSTEM
)

Expand Down
23 changes: 23 additions & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@


add_executable(snail_tool_etl etl_file.cpp)
target_link_libraries(snail_tool_etl PRIVATE compile_options etl utf8cpp)
set_target_properties(snail_tool_etl PROPERTIES OUTPUT_NAME "snail-tool-etl")

add_executable(snail_tool_perf_data perf_data_file.cpp)
target_link_libraries(snail_tool_perf_data PRIVATE compile_options perf_data)
set_target_properties(snail_tool_perf_data PROPERTIES OUTPUT_NAME "snail-tool-perfdata")

add_executable(snail_tool_analysis analysis.cpp)
target_link_libraries(snail_tool_analysis PRIVATE compile_options analysis)
set_target_properties(snail_tool_analysis PROPERTIES OUTPUT_NAME "snail-tool-analysis")

install(
TARGETS
snail_tool_etl
snail_tool_perf_data
snail_tool_analysis
COMPONENT
tools
RUNTIME DESTINATION bin
)
File renamed without changes.
18 changes: 17 additions & 1 deletion apps/etl_file.cpp → tools/etl_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,14 @@ int main(int argc, char* argv[])
return EXIT_FAILURE;
}

std::cout << std::format(" start_time: {}\n", file.header().start_time);
std::cout << std::format(" end_time: {}\n", file.header().end_time);
std::cout << std::format(" start_time_qpc_ticks: {}\n", file.header().start_time_qpc_ticks);
std::cout << std::format(" qpc_frequency: {}\n", file.header().qpc_frequency);
std::cout << std::format(" pointer_size: {}\n", file.header().pointer_size);
std::cout << std::format(" number_of_processors: {}\n", file.header().number_of_processors);
std::cout << std::format(" number_of_buffers: {}\n", file.header().number_of_buffers);

counting_event_observer observer;

std::size_t sample_count = 0;
Expand Down Expand Up @@ -1054,7 +1062,15 @@ int main(int argc, char* argv[])
}

std::cout << "\n";
file.process(observer);
try
{
file.process(observer);
}
catch(const std::exception& e)
{
std::cerr << std::format("Failed to process ETL file: {}\n", e.what());
return EXIT_FAILURE;
}

std::cout << "\n";
std::cout << "Number of samples:\n";
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit d1e4a7b

Please sign in to comment.