1 /** 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef PANDA_RUNTIME_TOOLING_SAMPLER_SAMPLE_WRITER_H 17 #define PANDA_RUNTIME_TOOLING_SAMPLER_SAMPLE_WRITER_H 18 19 #include <iostream> 20 #include <string> 21 #include <fstream> 22 23 #include "libpandabase/os/thread.h" 24 25 #include "runtime/tooling/sampler/sample_info.h" 26 27 #include <unordered_set> 28 29 namespace ark::tooling::sampler { 30 31 /* 32 * ======================================================= 33 * ============= Sampler binary format ================== 34 * ======================================================= 35 * 36 * Writing with the fasters and more convenient format .aspt 37 * Then it should be converted to flamegraph 38 * 39 * .aspt - ark sampling profiler trace file, binary format 40 * 41 * .aspt consists of 2 type information: 42 * - module row (panda file and its pointer) 43 * - sample row (sample information) 44 * 45 * module row for 64-bits: 46 * first 8 byte is 0xFFFFFFFF (to recognize that it's not a sample row) 47 * next 8 byte is pointer module 48 * next 8 byte is size of panda file name 49 * next bytes is panda file name in ASCII symbols 50 * 51 * sample row for 64-bits: 52 * first 4 bytes is thread id of thread from sample was obtained 53 * next 4 bytes is thread status of thread from sample was obtained 54 * next 8 bytes is stack size 55 * next bytes is stack frame 56 * one stack frame is panda file ptr and file id 57 * 58 * Example for 64-bit architecture: 59 * 60 * Thread id Thread status Stack Size Managed stack frame id 61 * Sample row |___________|___________|________________|_____________------___________| 62 * 32 bits 32 bits 64 bits (128 * <stack size>) bits 63 * 64 * 0xFF..FF pointer checksum name size module path (ASCII str) 65 * Module row |__________|__________|__________|___________|_____________------___________| 66 * 64 bits 64 bits 32 bits 64 bits (8 * <name size>) bits 67 */ 68 class StreamWriter final { 69 public: StreamWriter(const char * filename)70 explicit StreamWriter(const char *filename) 71 { 72 /* 73 * This class instance should be used only from one thread 74 * It may lead to format invalidation 75 * This class wasn't made thread safe for performance reason 76 */ 77 writeStreamPtr_ = std::make_unique<std::ofstream>(filename, std::ios::binary); 78 ASSERT(writeStreamPtr_ != nullptr); 79 } 80 ~StreamWriter()81 ~StreamWriter() 82 { 83 writeStreamPtr_->flush(); 84 writeStreamPtr_->close(); 85 }; 86 87 PANDA_PUBLIC_API void WriteModule(const FileInfo &moduleInfo); 88 PANDA_PUBLIC_API void WriteSample(const SampleInfo &sample) const; 89 IsModuleWritten(const FileInfo & moduleInfo)90 bool IsModuleWritten(const FileInfo &moduleInfo) const 91 { 92 return writtenModules_.find(moduleInfo) != writtenModules_.end(); 93 } 94 95 NO_COPY_SEMANTIC(StreamWriter); 96 NO_MOVE_SEMANTIC(StreamWriter); 97 98 static constexpr uintptr_t MODULE_INDICATOR_VALUE = 0xFFFFFFFF; 99 100 private: 101 std::unique_ptr<std::ofstream> writeStreamPtr_; 102 std::unordered_set<FileInfo> writtenModules_; 103 }; 104 105 } // namespace ark::tooling::sampler 106 107 #endif // PANDA_RUNTIME_TOOLING_SAMPLER_SAMPLE_WRITER_H 108