From 1465c4a8bd60520a83c783e27fa8407454d49d32 Mon Sep 17 00:00:00 2001 From: Vasily Date: Mon, 2 Dec 2019 20:30:59 +0100 Subject: [PATCH] Convert `getSettingsController()` to global static object After looking at the assembly output it became apparent that the Windows compiler did not compile out the `getSettingsController()` function call. This led to an unnecessary function call in order to get the SettingsController. Turning it into a static object in the compilation unit scope removes this function call and turns getSettings call into a single instruction (not counting zeroing the register for comparison and the jump instruction afterwards). ---- Adding the following code to the `main` function: ```cpp f ( settings::getSetting( settings::BoolSetting::UTILITY_vrcDebug ) ) { LOG( INFO ) << "Enabled"; } else { LOG( INFO ) << "Disabled"; } ``` Leads to this with the `getSettingsController` function: ```assembly [...] 47 if ( settings::getSetting( settings::BoolSetting::UTILITY_vrcDebug ) ) 0x7ff6c96819a0 <+ 1024> call AdvancedSettings!settings::getSettingsController (00007ff6`c96cd280) 0x7ff6c96819a5 <+ 1029> xorps xmm0,xmm0 0x7ff6c96819a8 <+ 1032> cmp byte ptr [rax+5FCh],0 0x7ff6c96819af <+ 1039> je AdvancedSettings!main+0x4fd (00007ff6`c9681a9d) 49 LOG( INFO ) << "Enabled"; 0x7ff6c96819b5 <+ 1045> mov qword ptr [rsp+288h],r15 0x7ff6c96819bd <+ 1053> mov qword ptr [rsp+290h],rsi [...] ``` And this without the function: ```assembly [...] 47 if ( settings::getSetting( settings::BoolSetting::UTILITY_vrcDebug ) ) 0x7ff7d97a19bb <+ 1019> xorps xmm0,xmm0 0x7ff7d97a19be <+ 1022> cmp byte ptr [AdvancedSettings!settings::settingController+0x5fc (00007ff7`d9854d4c)],0 0x7ff7d97a19c5 <+ 1029> je AdvancedSettings!main+0x4f3 (00007ff7`d97a1ab3) 49 LOG( INFO ) << "Enabled"; 0x7ff7d97a19cb <+ 1035> mov qword ptr [rsp+288h],r15 0x7ff7d97a19d3 <+ 1043> mov qword ptr [rsp+290h],rsi [...] ``` Notice the missing `call AdvancedSettings![...]` without the function and that the settings call literally cannot be made any faster. --- docs/specs/Settings-API.md | 2 +- src/settings/settings.cpp | 29 ++++++++++++----------------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/docs/specs/Settings-API.md b/docs/specs/Settings-API.md index c189f30..875b165 100644 --- a/docs/specs/Settings-API.md +++ b/docs/specs/Settings-API.md @@ -124,7 +124,7 @@ The function is used as a means of controlling when the API will be initialized, ## Implementation The public imperative API is an abstraction for the implementation, which is contained in a `SettingsController`. -The `SettingsController` object is a `static` object inside the `getSettingsController()` function. +The `SettingsController` object is a `static` object inside the `settings.cpp` compilation unit. This is done to remove the limitations that an object oriented design would bring, namely lifetime and scope management. Since the API is supposed to be globally available throughout the lifetime of the program, creating it as an object in the `OverlayController` and passing it to subcontrollers would only introduce unnecessary parameter passing. diff --git a/src/settings/settings.cpp b/src/settings/settings.cpp index 7deeed7..55ba636 100644 --- a/src/settings/settings.cpp +++ b/src/settings/settings.cpp @@ -6,63 +6,58 @@ namespace settings { -SettingsController& getSettingsController() -{ - static SettingsController s{}; - - return s; -} +static SettingsController settingController{}; void saveChangedSettings() { - getSettingsController().saveChangedSettings(); + settingController.saveChangedSettings(); } void saveAllSettings() { LOG( INFO ) << "Saving all settings."; - getSettingsController().saveAllSettings(); + settingController.saveAllSettings(); LOG( INFO ) << "All settings saved."; } [[nodiscard]] bool getSetting( const BoolSetting setting ) { - return getSettingsController().getSetting( setting ); + return settingController.getSetting( setting ); } void setSetting( const BoolSetting setting, const bool value ) { - getSettingsController().setSetting( setting, value ); + settingController.setSetting( setting, value ); } [[nodiscard]] double getSetting( const DoubleSetting setting ) { - return getSettingsController().getSetting( setting ); + return settingController.getSetting( setting ); } void setSetting( const DoubleSetting setting, const double value ) { - getSettingsController().setSetting( setting, value ); + settingController.setSetting( setting, value ); } [[nodiscard]] int getSetting( const IntSetting setting ) { - return getSettingsController().getSetting( setting ); + return settingController.getSetting( setting ); } void setSetting( const IntSetting setting, const int value ) { - getSettingsController().setSetting( setting, value ); + settingController.setSetting( setting, value ); } [[nodiscard]] std::string getSetting( const StringSetting setting ) { - return getSettingsController().getSetting( setting ); + return settingController.getSetting( setting ); } void setSetting( const StringSetting setting, const std::string value ) { - getSettingsController().setSetting( setting, value ); + settingController.setSetting( setting, value ); } std::string initializeAndGetSettingsPath() @@ -70,7 +65,7 @@ std::string initializeAndGetSettingsPath() // The static object is initialized the first time the function is called. // Having a dedicated function for this allows more control over when this // happens. - return getSettingsController().getSettingsFileName(); + return settingController.getSettingsFileName(); } } // namespace settings