From 897310f6fb709713298efea7ea772687de7fb67a Mon Sep 17 00:00:00 2001 From: Ryan Lai Date: Tue, 1 Dec 2020 20:26:18 -0800 Subject: [PATCH] Add suspend handler with new telemetry event for UWP scenarios (#5907) * Add suspend handler with new telemetry event * Fix build warning * Use cppwinrt from nuget * Restore nuget packages * add dependencies * Add nuget_helpers * Cleaned up * Clean up * Comment * Add dependencies for the rest * Remove unused line * Update activation string * PR comment to remove ALL --- cmake/nuget_helpers.cmake | 57 ++++++++++++++++++++ cmake/winml.cmake | 22 ++++++++ packages.config | 3 +- winml/dll/module.cpp | 5 +- winml/lib/Api.Ort/OnnxruntimeEnvironment.cpp | 24 ++++++++- winml/lib/Api.Ort/OnnxruntimeEnvironment.h | 6 ++- winml/lib/Common/inc/WinMLTelemetryHelper.h | 1 + winml/lib/Telemetry/WinMLTelemetryHelper.cpp | 10 ++++ 8 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 cmake/nuget_helpers.cmake diff --git a/cmake/nuget_helpers.cmake b/cmake/nuget_helpers.cmake new file mode 100644 index 0000000000..62a222390d --- /dev/null +++ b/cmake/nuget_helpers.cmake @@ -0,0 +1,57 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +cmake_minimum_required(VERSION 3.0) + +# Determines the version of a native nuget package from the root packages.config. +# +# id : package id +# out : name of variable to set result +function(pkg_version id out packages_config) + file(READ ${packages_config} packages_config_contents) + string(REGEX MATCH "package[ ]*id[ ]*=[ ]*\"${id}\"" found_package_id ${packages_config_contents}) + if (NOT(found_package_id)) + message(FATAL_ERROR "Could not find '${id}' in packages.config!") + endif() + + set(pattern ".*id[ ]*=[ ]*\"${id}\"[ ]+version=\"([0-9a-zA-Z\\.-]+)\"[ ]+targetFramework.*") + string(REGEX REPLACE ${pattern} "\\1" version ${packages_config_contents}) + set(${out} ${version} PARENT_SCOPE) +endfunction() + +# Downloads the nuget packages based on packages.config +function( + add_fetch_nuget_target + nuget_target # Target to be written to + target_dependency # The file in the nuget package that is needed +) + # Pull down the nuget packages + if (NOT(MSVC) OR NOT(WIN32)) + message(FATAL_ERROR "NuGet packages are only supported for MSVC on Windows.") + endif() + + # Retrieve the latest version of nuget + include(ExternalProject) + ExternalProject_Add(nuget + PREFIX nuget + URL "https://dist.nuget.org/win-x86-commandline/v5.3.0/nuget.exe" + DOWNLOAD_NO_EXTRACT 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + UPDATE_COMMAND "" + INSTALL_COMMAND "") + + set(NUGET_CONFIG ${PROJECT_SOURCE_DIR}/../NuGet.config) + set(PACKAGES_CONFIG ${PROJECT_SOURCE_DIR}/../packages.config) + get_filename_component(PACKAGES_DIR ${CMAKE_CURRENT_BINARY_DIR}/../packages ABSOLUTE) + + # Restore nuget packages + add_custom_command( + OUTPUT ${target_dependency} + DEPENDS ${PACKAGES_CONFIG} ${NUGET_CONFIG} + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/nuget/src/nuget restore ${PACKAGES_CONFIG} -PackagesDirectory ${PACKAGES_DIR} -ConfigFile ${NUGET_CONFIG} + VERBATIM) + + add_custom_target(${nuget_target} DEPENDS ${target_dependency}) + add_dependencies(${nuget_target} nuget) +endfunction() \ No newline at end of file diff --git a/cmake/winml.cmake b/cmake/winml.cmake index 82f7541f6d..7946794f31 100644 --- a/cmake/winml.cmake +++ b/cmake/winml.cmake @@ -9,6 +9,7 @@ include(precompiled_header.cmake) include(target_delayload.cmake) include(winml_sdk_helpers.cmake) include(winml_cppwinrt.cmake) +include(nuget_helpers.cmake) # get the current nuget sdk kit directory get_sdk(sdk_folder sdk_version) @@ -26,6 +27,22 @@ set(winml_lib_api_ort_dir ${REPO_ROOT}/winml/lib/api.ort) set(winml_lib_common_dir ${REPO_ROOT}/winml/lib/common) set(winml_lib_telemetry_dir ${REPO_ROOT}/winml/lib/telemetry) +# Retrieve the version of cppwinrt nuget +pkg_version( + Microsoft.Windows.CppWinRT + CppWinRT_version + ${PROJECT_SOURCE_DIR}/../packages.config +) + +# Override and use the the cppwinrt from NuGet package as opposed to the one in the SDK. +set(winml_CPPWINRT_EXE_PATH_OVERRIDE ${CMAKE_CURRENT_BINARY_DIR}/../packages/Microsoft.Windows.CppWinRT.${CppWinRT_version}/bin/cppwinrt.exe) + +# add custom target to fetch the nugets +add_fetch_nuget_target( + RESTORE_NUGET_PACKAGES # target name + winml_CPPWINRT_EXE_PATH_OVERRIDE # cppwinrt is the target package + ) + set(winml_is_inbox OFF) if (onnxruntime_WINML_NAMESPACE_OVERRIDE) set(output_name "${onnxruntime_WINML_NAMESPACE_OVERRIDE}.AI.MachineLearning") @@ -77,6 +94,7 @@ add_generate_cppwinrt_sdk_headers_target( ${CMAKE_CURRENT_BINARY_DIR}/winml/sdk/cppwinrt/include # output folder relative to CMAKE_BINARY_DIR where the generated sdk will be placed in the ${target_folder} # folder where this target will be placed ) +add_dependencies(winml_sdk_cppwinrt RESTORE_NUGET_PACKAGES) # generate winml headers from idl target_cppwinrt(winml_api @@ -89,6 +107,7 @@ target_cppwinrt(winml_api "${winml_midl_defines}" # the midl compiler defines ${winml_api_use_ns_prefix} # set ns_prefix ) +add_dependencies(winml_api RESTORE_NUGET_PACKAGES) # generate winml.experimental headers from idl target_cppwinrt(winml_api_experimental @@ -101,6 +120,7 @@ target_cppwinrt(winml_api_experimental ${winml_midl_defines} # the midl compiler defines ${winml_api_use_ns_prefix} # set ns_prefix ) +add_dependencies(winml_api_experimental RESTORE_NUGET_PACKAGES) target_midl(winml_api_native ${idl_native} # winml native idl to compile @@ -110,6 +130,7 @@ target_midl(winml_api_native ${target_folder} # the folder this target will be placed under "${winml_midl_defines}" # the midl compiler defines ) +add_dependencies(winml_api_native RESTORE_NUGET_PACKAGES) target_midl(winml_api_native_internal ${idl_native_internal} # winml internal native idl to compile @@ -119,6 +140,7 @@ target_midl(winml_api_native_internal ${target_folder} # the folder this target will be placed under "${winml_midl_defines}" # the midl compiler defines ) +add_dependencies(winml_api_native_internal RESTORE_NUGET_PACKAGES) ########################### # Add winml_lib_telemetry diff --git a/packages.config b/packages.config index cf2b71e61a..c78c556bfd 100644 --- a/packages.config +++ b/packages.config @@ -1,5 +1,6 @@  - + + diff --git a/winml/dll/module.cpp b/winml/dll/module.cpp index de6820bdca..867edd9970 100644 --- a/winml/dll/module.cpp +++ b/winml/dll/module.cpp @@ -4,7 +4,6 @@ #include "pch.h" #include #include - #include "LearningModelDevice.h" #include "OnnxruntimeProvider.h" #include "Dummy.h" @@ -92,9 +91,7 @@ STDAPI DllCanUnloadNow() { STDAPI DllGetExperimentalActivationFactory(void* classId, void** factory) noexcept { try { *factory = nullptr; - uint32_t length{}; - wchar_t const* const buffer = WINRT_WindowsGetStringRawBuffer(classId, &length); - std::wstring_view const name{buffer, length}; + std::wstring_view const name{*reinterpret_cast(&classId)}; auto requal = [](std::wstring_view const& left, std::wstring_view const& right) noexcept { return std::equal(left.rbegin(), left.rend(), right.rbegin(), right.rend()); diff --git a/winml/lib/Api.Ort/OnnxruntimeEnvironment.cpp b/winml/lib/Api.Ort/OnnxruntimeEnvironment.cpp index f4b33c995a..53d2b1d67f 100644 --- a/winml/lib/Api.Ort/OnnxruntimeEnvironment.cpp +++ b/winml/lib/Api.Ort/OnnxruntimeEnvironment.cpp @@ -6,8 +6,9 @@ #include "OnnxruntimeErrors.h" #include "core/platform/windows/TraceLoggingConfig.h" #include - #include +#include +#include using namespace _winml; @@ -190,6 +191,18 @@ static void __stdcall WinmlOrtProfileEventCallback(const OrtProfilerEventRecord* } } +static void OnSuspending(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::ApplicationModel::SuspendingEventArgs const& args) { + telemetry_helper.LogWinMLSuspended(); +} + +void OnnxruntimeEnvironment::RegisterSuspendHandler() { + try { + auto suspend_event_handler = winrt::Windows::Foundation::EventHandler(&OnSuspending); + suspend_token_ = winrt::Windows::ApplicationModel::Core::CoreApplication::Suspending(suspend_event_handler); + } catch (...) { + } //Catch in case CoreApplication cannot be found for non-UWP executions +} + OnnxruntimeEnvironment::OnnxruntimeEnvironment(const OrtApi* ort_api) : ort_env_(nullptr, nullptr) { OrtEnv* ort_env = nullptr; THROW_IF_NOT_OK_MSG(ort_api->CreateEnv(OrtLoggingLevel::ORT_LOGGING_LEVEL_VERBOSE, "Default", &ort_env), @@ -204,6 +217,15 @@ OnnxruntimeEnvironment::OnnxruntimeEnvironment(const OrtApi* ort_api) : ort_env_ ort_api); THROW_IF_NOT_OK_MSG(winml_adapter_api->OverrideSchema(), ort_api); + + // Register suspend handler for UWP applications + RegisterSuspendHandler(); +} + +OnnxruntimeEnvironment::~OnnxruntimeEnvironment() { + if (suspend_token_) { + winrt::Windows::ApplicationModel::Core::CoreApplication::Suspending(suspend_token_); + } } HRESULT OnnxruntimeEnvironment::GetOrtEnvironment(_Out_ OrtEnv** ort_env) { diff --git a/winml/lib/Api.Ort/OnnxruntimeEnvironment.h b/winml/lib/Api.Ort/OnnxruntimeEnvironment.h index 10df3aec6c..a1b9657737 100644 --- a/winml/lib/Api.Ort/OnnxruntimeEnvironment.h +++ b/winml/lib/Api.Ort/OnnxruntimeEnvironment.h @@ -11,12 +11,16 @@ namespace _winml { class OnnxruntimeEnvironment { public: OnnxruntimeEnvironment(const OrtApi* ort_api); - + ~OnnxruntimeEnvironment(); HRESULT GetOrtEnvironment(_Out_ OrtEnv** ert_env); HRESULT EnableDebugOutput(bool is_enabled); + private: + void RegisterSuspendHandler(); + private: UniqueOrtEnv ort_env_; + winrt::event_token suspend_token_; }; const OrtApi* GetVersionedOrtApi(); diff --git a/winml/lib/Common/inc/WinMLTelemetryHelper.h b/winml/lib/Common/inc/WinMLTelemetryHelper.h index 7e3d025a09..87eabaa875 100644 --- a/winml/lib/Common/inc/WinMLTelemetryHelper.h +++ b/winml/lib/Common/inc/WinMLTelemetryHelper.h @@ -83,6 +83,7 @@ class WinMLTelemetryHelper { } void LogWinMLShutDown(); + void LogWinMLSuspended(); void LogRuntimeError(HRESULT hr, std::string message, PCSTR file, PCSTR function, int line); void LogRuntimeError(HRESULT hr, PCSTR message, PCSTR file, PCSTR function, int line); void LogRegisterOperatorKernel( diff --git a/winml/lib/Telemetry/WinMLTelemetryHelper.cpp b/winml/lib/Telemetry/WinMLTelemetryHelper.cpp index 20e35fc61b..5ba7eec8b1 100644 --- a/winml/lib/Telemetry/WinMLTelemetryHelper.cpp +++ b/winml/lib/Telemetry/WinMLTelemetryHelper.cpp @@ -28,6 +28,16 @@ void WinMLTelemetryHelper::LogWinMLShutDown() { TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES)); } +void WinMLTelemetryHelper::LogWinMLSuspended() { + WinMLTraceLoggingWrite( + provider_, + "WinMLSuspended", + TraceLoggingKeyword(WINML_PROVIDER_KEYWORD_DEFAULT), + TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance), + TraceLoggingInt32(runtime_session_id_, "runtimeSessionId"), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES)); +} + void WinMLTelemetryHelper::LogRuntimeError(HRESULT hr, PCSTR message, PCSTR file, PCSTR function, int line) { if (!telemetry_enabled_) return;