diff options
| author | kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> | 2024-06-04 18:24:12 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-04 18:24:12 -0700 |
| commit | bacf73cc68af8b7654cc920b07635f926b785b84 (patch) | |
| tree | 23b466be471d1c188ce893f4ce2b934e7f6a2b77 /source | |
| parent | 1141b8243c4ff00c59e927b0c33dbffaea29db4c (diff) | |
Add APIs to get profile of compile time (#4242)
* Add APIs to get profile of compile time
Add serial time measurement
Add profiler to measure lots of stages in slang compilation, and it
can accumulate the time spent in each thread in multi-threads case and
finally report a serial timing info.
* Add invocation times to the profiler
* Simplify the profiler and provide a 'clear' option
Change the profiler design to only return the thread_local
profiler to user.
We create a ISlangProfiler interface to carry the thread_local
variable PerformanceProfilerImpl profiler to user.
In addition, we provide a new option in the input parameter to
control whether or not user want to clear the previous profile
data. So spGetCompileProfile() can always returns a fresh new
profiling data.
* Change to use slang container List
Stop using std::vector, instead use slang's container List.
Generate a UUID for ISlangProfiler
Diffstat (limited to 'source')
| -rw-r--r-- | source/core/slang-performance-profiler.cpp | 75 | ||||
| -rw-r--r-- | source/core/slang-performance-profiler.h | 31 | ||||
| -rw-r--r-- | source/slang/slang-api.cpp | 10 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.h | 1 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 19 |
5 files changed, 130 insertions, 6 deletions
diff --git a/source/core/slang-performance-profiler.cpp b/source/core/slang-performance-profiler.cpp index 7ca33f615..f8e934491 100644 --- a/source/core/slang-performance-profiler.cpp +++ b/source/core/slang-performance-profiler.cpp @@ -3,11 +3,6 @@ namespace Slang { - struct FuncProfileInfo - { - int invocationCount = 0; - std::chrono::nanoseconds duration = std::chrono::nanoseconds::zero(); - }; class PerformanceProfilerImpl : public PerformanceProfiler { public: @@ -39,9 +34,14 @@ namespace Slang for (auto func : data) { out << func.key << ": \t"; - out << func.value.invocationCount << "\t" << func.value.duration.count() / 1000000.0f << "\n"; + auto milliseconds = std::chrono::duration_cast< std::chrono::milliseconds >(func.value.duration); + out << func.value.invocationCount << "\t" << milliseconds.count() << "ms\n"; } } + virtual void clear() override + { + data.clear(); + } }; PerformanceProfiler* Slang::PerformanceProfiler::getProfiler() @@ -49,4 +49,67 @@ namespace Slang thread_local static PerformanceProfilerImpl profiler = PerformanceProfilerImpl(); return &profiler; } + + SlangProfiler::SlangProfiler(PerformanceProfiler* profiler) + { + PerformanceProfilerImpl* profilerImpl = static_cast<PerformanceProfilerImpl*>(profiler); + size_t entryCount = profilerImpl->data.getCount(); + + m_profilEntries.reserve(entryCount); + + int index = 0; + for (auto func : profilerImpl->data) + { + ProfileInfo profileEntry {}; + size_t strSize = std::min(sizeof(profileEntry.funcName) - 1, strlen(func.key)); + + if (strSize > 0) + { + strncpy_s(profileEntry.funcName, strSize, func.key, strSize); + } + profileEntry.invocationCount = func.value.invocationCount; + profileEntry.duration = func.value.duration; + + m_profilEntries.insert(index, profileEntry); + index++; + } + } + + ISlangUnknown* SlangProfiler::getInterface(const Guid& guid) + { + if(guid == SlangProfiler::getTypeGuid()) + return static_cast<ISlangUnknown*>(this); + else + return nullptr; + } + + size_t SlangProfiler::getEntryCount() + { + return m_profilEntries.getCount(); + } + + const char* SlangProfiler::getEntryName(uint32_t index) + { + if (index >= (uint32_t)m_profilEntries.getCount()) + return nullptr; + + return m_profilEntries[index].funcName; + } + + long SlangProfiler::getEntryTimeMS(uint32_t index) + { + if (index >= (uint32_t)m_profilEntries.getCount()) + return 0; + + auto milliseconds = std::chrono::duration_cast< std::chrono::milliseconds >(m_profilEntries[index].duration); + return (long)milliseconds.count(); + } + + uint32_t SlangProfiler::getEntryInvocationTimes(uint32_t index) + { + if (index >= (uint32_t)m_profilEntries.getCount()) + return 0; + + return m_profilEntries[index].invocationCount; + } } diff --git a/source/core/slang-performance-profiler.h b/source/core/slang-performance-profiler.h index 323940ade..f7c62bb45 100644 --- a/source/core/slang-performance-profiler.h +++ b/source/core/slang-performance-profiler.h @@ -3,10 +3,19 @@ #include "slang-string.h" #include <chrono> +#include <vector> +#include "../../slang-com-helper.h" +#include "../core/slang-list.h" namespace Slang { +struct FuncProfileInfo +{ + int invocationCount = 0; + std::chrono::nanoseconds duration = std::chrono::nanoseconds::zero(); +}; + struct FuncProfileContext { const char* funcName = nullptr; @@ -19,6 +28,7 @@ public: virtual FuncProfileContext enterFunction(const char* funcName) = 0; virtual void exitFunction(FuncProfileContext context) = 0; virtual void getResult(StringBuilder& out) = 0; + virtual void clear() = 0; public: static PerformanceProfiler* getProfiler(); }; @@ -36,6 +46,27 @@ struct PerformanceProfilerFuncRAIIContext } }; +struct SlangProfiler: public ISlangProfiler, public RefObject +{ +public: + SLANG_REF_OBJECT_IUNKNOWN_ALL + struct ProfileInfo + { + char funcName[256] = {0}; + int invocationCount = 0; + std::chrono::nanoseconds duration = std::chrono::nanoseconds::zero(); + }; + SlangProfiler(PerformanceProfiler * profiler); + ISlangUnknown* getInterface(const Guid& guid); + + virtual SLANG_NO_THROW size_t SLANG_MCALL getEntryCount() override; + virtual SLANG_NO_THROW const char* SLANG_MCALL getEntryName(uint32_t index) override; + virtual SLANG_NO_THROW long SLANG_MCALL getEntryTimeMS(uint32_t index) override; + virtual SLANG_NO_THROW uint32_t SLANG_MCALL getEntryInvocationTimes(uint32_t index) override; +private: + List<ProfileInfo> m_profilEntries; +}; + #define SLANG_PROFILE PerformanceProfilerFuncRAIIContext _profileContext(__func__) } diff --git a/source/slang/slang-api.cpp b/source/slang/slang-api.cpp index a4ae92bf9..250b9edf3 100644 --- a/source/slang/slang-api.cpp +++ b/source/slang/slang-api.cpp @@ -798,6 +798,16 @@ SLANG_API SlangResult spCompileRequest_getEntryPoint( return request->getEntryPoint(entryPointIndex, outEntryPoint); } +/*! @see slang::ICompileRequest::getCompileTimeProfile */ +SLANG_API SlangResult spGetCompileTimeProfile( + slang::ICompileRequest* request, + ISlangProfiler** compileTimeProfile, + bool shouldClear) +{ + SLANG_ASSERT(request); + return request->getCompileTimeProfile(compileTimeProfile, shouldClear); +} + // Get the output code associated with a specific translation unit SLANG_API char const* spGetTranslationUnitSource( slang::ICompileRequest* /*request*/, diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index fd12a71a3..16f1b9187 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -2782,6 +2782,7 @@ namespace Slang virtual SLANG_NO_THROW void SLANG_MCALL setSkipSPIRVValidation(bool value) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setTargetUseMinimumSlangOptimization(int targetIndex, bool value) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setIgnoreCapabilityCheck(bool value) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCompileTimeProfile(ISlangProfiler** compileTimeProfile, bool isClear); void setTrackLiveness(bool v); diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 66e75a282..f820bf8cd 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -6245,6 +6245,25 @@ void const* EndToEndCompileRequest::getEntryPointCode(int entryPointIndex, size_ return (void*)blob->getBufferPointer(); } +SlangResult EndToEndCompileRequest::getCompileTimeProfile(ISlangProfiler** compileTimeProfile, bool shouldClear) +{ + if (compileTimeProfile == nullptr) + { + return SLANG_E_INVALID_ARG; + } + + SlangProfiler* profiler = new SlangProfiler(PerformanceProfiler::getProfiler()); + + if (shouldClear) + { + PerformanceProfiler::getProfiler()->clear(); + } + + ComPtr<ISlangProfiler> result(profiler); + *compileTimeProfile = result.detach(); + return SLANG_OK; +} + static SlangResult _getEntryPointResult( EndToEndCompileRequest* req, int entryPointIndex, |
