Experimental: Adds code caching for faster loading

This commit is contained in:
Lord Hepipud 2020-11-04 09:20:19 +01:00
parent 67c7d3c8e0
commit 37c0824be5
8 changed files with 153 additions and 10 deletions

View file

@ -18,6 +18,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
* [#139](https://github.com/Icinga/icinga-powershell-framework/pull/139) Add Cmdlet `Start-IcingaShellAsUser` to open an Icinga Shell as different user for testing * [#139](https://github.com/Icinga/icinga-powershell-framework/pull/139) Add Cmdlet `Start-IcingaShellAsUser` to open an Icinga Shell as different user for testing
* [#141](https://github.com/Icinga/icinga-powershell-framework/pull/141) Adds Cmdlet `Convert-IcingaPluginThresholds` as generic approach to convert Icinga Thresholds with units to the lowest unit of this type. * [#141](https://github.com/Icinga/icinga-powershell-framework/pull/141) Adds Cmdlet `Convert-IcingaPluginThresholds` as generic approach to convert Icinga Thresholds with units to the lowest unit of this type.
* [#134](https://github.com/Icinga/icinga-powershell-framework/pull/134) Adds Cmdlet `Test-IcingaWindowsInformation` to check if a WMI class exist and if we can fetch data from it. In addition we add support for binary value comparison with the new Cmdlet `Test-IcingaBinaryOperator` * [#134](https://github.com/Icinga/icinga-powershell-framework/pull/134) Adds Cmdlet `Test-IcingaWindowsInformation` to check if a WMI class exist and if we can fetch data from it. In addition we add support for binary value comparison with the new Cmdlet `Test-IcingaBinaryOperator`
* [#142](https://github.com/Icinga/icinga-powershell-framework/pull/142) **Experimental:** Adds feature to cache the Framework code into a single file to speed up the entire loading process, mitigating the impact on performance on systems with few CPU cores. You enable disables this feature by using `Enable-IcingaFrameworkCodeCache` and `Disable-IcingaFrameworkCodeCache`. Updating the cache is done with `Write-IcingaFrameworkCodeCache`
### Bugfixes ### Bugfixes

View file

@ -7,10 +7,21 @@
Copyright = '(c) 2020 Icinga GmbH | MIT' Copyright = '(c) 2020 Icinga GmbH | MIT'
Description = 'Icinga for Windows module which allows to entirely monitor the Windows Host system.' Description = 'Icinga for Windows module which allows to entirely monitor the Windows Host system.'
PowerShellVersion = '4.0' PowerShellVersion = '4.0'
NestedModules = @(
'.\lib\core\framework\Get-IcingaFrameworkCodeCache.psm1',
'.\lib\config\Get-IcingaPowerShellConfig.psm1',
'.\lib\config\Read-IcingaPowerShellConfig.psm1',
'.\lib\config\Test-IcingaPowerShellConfigItem.psm1',
'.\lib\core\logging\Write-IcingaConsoleOutput.psm1',
'.\lib\core\logging\Write-IcingaConsoleNotice.psm1',
'.\lib\core\logging\Write-IcingaConsoleWarning.psm1'
)
FunctionsToExport = @( FunctionsToExport = @(
'Use-Icinga', 'Use-Icinga',
'Invoke-IcingaCommand', 'Invoke-IcingaCommand',
'Import-IcingaLib', 'Import-IcingaLib',
'Get-IcingaFrameworkCodeCacheFile',
'Write-IcingaFrameworkCodeCache',
'Publish-IcingaModuleManifest', 'Publish-IcingaModuleManifest',
'Publish-IcingaEventlogDocumentation', 'Publish-IcingaEventlogDocumentation',
'Get-IcingaPluginDir', 'Get-IcingaPluginDir',
@ -19,9 +30,16 @@
'Get-IcingaPowerShellConfigDir', 'Get-IcingaPowerShellConfigDir',
'Get-IcingaFrameworkRootPath', 'Get-IcingaFrameworkRootPath',
'Get-IcingaPowerShellModuleFile', 'Get-IcingaPowerShellModuleFile',
'Start-IcingaShellAsUser' 'Start-IcingaShellAsUser',
'Get-IcingaPowerShellConfig',
'Get-IcingaFrameworkCodeCache',
'Read-IcingaPowerShellConfig',
'Test-IcingaPowerShellConfigItem',
'Write-IcingaConsoleOutput',
'Write-IcingaConsoleNotice',
'Write-IcingaConsoleWarning'
) )
CmdletsToExport = @() CmdletsToExport = @('*')
VariablesToExport = '*' VariablesToExport = '*'
AliasesToExport = @( 'icinga' ) AliasesToExport = @( 'icinga' )
PrivateData = @{ PrivateData = @{

View file

@ -22,6 +22,10 @@ function Use-Icinga()
Use-IcingaPlugins; Use-IcingaPlugins;
} }
if ((Test-Path (Get-IcingaFrameworkCodeCacheFile)) -eq $FALSE -And (Get-IcingaFrameworkCodeCache)) {
Write-IcingaFrameworkCodeCache;
}
# This function will allow us to load this entire module including possible # This function will allow us to load this entire module including possible
# actions, making it available within our shell environment # actions, making it available within our shell environment
# First load our custom modules # First load our custom modules
@ -78,6 +82,20 @@ function Use-Icinga()
} }
} }
function Get-IcingaFrameworkCodeCacheFile()
{
return (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'framework_cache.psm1');
}
function Write-IcingaFrameworkCodeCache()
{
if (Get-IcingaFrameworkCodeCache) {
Import-IcingaLib '\' -Init -CompileCache;
} else {
Write-IcingaConsoleNotice 'The experimental code caching feature is currently not enabled. You can enable it with "Enable-IcingaFrameworkCodeCache"';
}
}
function Import-IcingaLib() function Import-IcingaLib()
{ {
param( param(
@ -87,15 +105,27 @@ function Import-IcingaLib()
[Switch]$ForceReload, [Switch]$ForceReload,
[switch]$Init, [switch]$Init,
[switch]$Custom, [switch]$Custom,
[switch]$WriteManifests [switch]$WriteManifests,
[switch]$CompileCache
); );
# This is just to only allow a global loading of the module. Import-IcingaLib is ignored on every other # This is just to only allow a global loading of the module. Import-IcingaLib is ignored on every other
# location. It is just there to give a basic idea within commands, of which functions are used # location. It is just there to give a basic idea within commands, of which functions are used
if ($Init -eq $FALSE) { if ($Init -eq $FALSE) {
return; return;
} }
$CacheFile = Get-IcingaFrameworkCodeCacheFile;
if ($Custom -eq $FALSE -And $CompileCache -eq $FALSE -And (Test-Path $CacheFile) -And (Get-IcingaFrameworkCodeCache)) {
Import-Module $CacheFile -Global;
return;
}
[array]$ImportModules = @();
[array]$RemoveModules = @();
if ($Custom) { if ($Custom) {
[string]$directory = Join-Path -Path $PSScriptRoot -ChildPath 'custom\'; [string]$directory = Join-Path -Path $PSScriptRoot -ChildPath 'custom\';
} else { } else {
@ -116,11 +146,11 @@ function Import-IcingaLib()
if ($ListOfLoadedModules -like "*$moduleName*") { if ($ListOfLoadedModules -like "*$moduleName*") {
if ($ForceReload) { if ($ForceReload) {
Remove-Module -Name $moduleName $RemoveModules += $moduleName;
Import-Module ([string]::Format('{0}', $modulePath)) -Global;
} }
$ImportModules += $modulePath;
} else { } else {
Import-Module ([string]::Format('{0}', $modulePath)) -Global; $ImportModules += $modulePath;
if ($WriteManifests) { if ($WriteManifests) {
Publish-IcingaModuleManifest -Module $moduleName; Publish-IcingaModuleManifest -Module $moduleName;
} }
@ -132,15 +162,35 @@ function Import-IcingaLib()
if ($ForceReload) { if ($ForceReload) {
if ($ListOfLoadedModules -Like "*$moduleName*") { if ($ListOfLoadedModules -Like "*$moduleName*") {
Remove-Module -Name $moduleName; $RemoveModules += $moduleName;
} }
} }
Import-Module ([string]::Format('{0}.psm1', $module)) -Global; $ImportModules += ([string]::Format('{0}.psm1', $module));
if ($WriteManifests) { if ($WriteManifests) {
Publish-IcingaModuleManifest -Module $moduleName; Publish-IcingaModuleManifest -Module $moduleName;
} }
} }
if ($RemoveModules.Count -ne 0) {
Remove-Module $RemoveModules;
}
if ($ImportModules.Count -ne 0) {
if ($CompileCache) {
$CacheContent = '';
foreach ($module in $ImportModules) {
$Content = Get-Content $module -Raw;
$CacheContent += $Content + "`r`n";
}
$CacheContent += $Content + "Export-ModuleMember -Function @( '*' )";
Set-Content -Path $CacheFile -Value $CacheContent;
} else {
Import-Module $ImportModules -Global;
}
}
} }
function Publish-IcingaModuleManifest() function Publish-IcingaModuleManifest()
@ -279,6 +329,9 @@ function Invoke-IcingaCommand()
Write-Output ([string]::Format('** Icinga PowerShell Framework {0}', $IcingaFrameworkData.PrivateData.Version)); Write-Output ([string]::Format('** Icinga PowerShell Framework {0}', $IcingaFrameworkData.PrivateData.Version));
Write-Output ([string]::Format('** Copyright {0}', $IcingaFrameworkData.Copyright)); Write-Output ([string]::Format('** Copyright {0}', $IcingaFrameworkData.Copyright));
Write-Output ([string]::Format('** User environment {0}\{1}', $env:USERDOMAIN, $env:USERNAME)); Write-Output ([string]::Format('** User environment {0}\{1}', $env:USERDOMAIN, $env:USERNAME));
if (Get-IcingaFrameworkCodeCache) {
Write-Output ([string]::Format('** Warning: Icinga Framework Code Caching is enabled'));
}
Write-Output '******************************************************'; Write-Output '******************************************************';
} }

View file

@ -25,13 +25,13 @@ function Read-IcingaPowerShellConfig()
} }
if (-Not (Test-Path $ConfigFile)) { if (-Not (Test-Path $ConfigFile)) {
return (New-Object -TypeName PSOBject); return (New-Object -TypeName PSObject);
} }
[string]$Content = Get-Content -Path $ConfigFile; [string]$Content = Get-Content -Path $ConfigFile;
if ([string]::IsNullOrEmpty($Content)) { if ([string]::IsNullOrEmpty($Content)) {
return (New-Object -TypeName PSOBject); return (New-Object -TypeName PSObject);
} }
return (ConvertFrom-Json -InputObject $Content); return (ConvertFrom-Json -InputObject $Content);

View file

@ -0,0 +1,19 @@
<#
.SYNOPSIS
Disables the experimental feature to cache all functions into a single file,
allowing quicker loading times of the Icinga PowerShell Framework
.DESCRIPTION
Disables the experimental feature to cache all functions into a single file,
allowing quicker loading times of the Icinga PowerShell Framework
.FUNCTIONALITY
Experimental: Disables the Icinga for Windows code caching
.EXAMPLE
PS>Disable-IcingaFrameworkCodeCache;
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Disable-IcingaFrameworkCodeCache()
{
Set-IcingaPowerShellConfig -Path 'Framework.Experimental.CodeCaching' -Value $FALSE;
}

View file

@ -0,0 +1,21 @@
<#
.SYNOPSIS
Enables the experimental feature to cache all functions into a single file,
allowing quicker loading times of the Icinga PowerShell Framework
.DESCRIPTION
Enables the experimental feature to cache all functions into a single file,
allowing quicker loading times of the Icinga PowerShell Framework
.FUNCTIONALITY
Experimental: Enables the Icinga for Windows code caching
.EXAMPLE
PS>Enable-IcingaFrameworkCodeCache;
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Enable-IcingaFrameworkCodeCache()
{
Set-IcingaPowerShellConfig -Path 'Framework.Experimental.CodeCaching' -Value $TRUE;
Write-IcingaConsoleWarning 'This is an experimental feature and might cause some side effects during usage. Please use this function with caution. Please run "Write-IcingaFrameworkCodeCache" in addition to ensure your cache is updated. This should be done after each update of the Framework in case the feature was disabled during the update run.';
}

View file

@ -0,0 +1,28 @@
<#
.SYNOPSIS
Fetches the current enable/disable state of the experimental feature
for caching the Icinga PowerShell Framework code
.DESCRIPTION
Fetches the current enable/disable state of the experimental feature
for caching the Icinga PowerShell Framework code
.FUNCTIONALITY
Experimental: Get the current code caching configuration of the
Icinga PowerShell Framework
.EXAMPLE
PS>Get-IcingaFrameworkCodeCache;
.LINK
https://github.com/Icinga/icinga-powershell-framework
.OUTPUTS
System.Boolean
#>
function Get-IcingaFrameworkCodeCache()
{
$CodeCaching = Get-IcingaPowerShellConfig -Path 'Framework.Experimental.CodeCaching';
if ($null -eq $CodeCaching) {
return $FALSE;
}
return $CodeCaching;
}

View file

@ -91,6 +91,9 @@ function Install-IcingaFrameworkUpdate()
Start-Sleep -Seconds 1; Start-Sleep -Seconds 1;
Remove-ItemSecure -Path $Archive.Directory -Recurse -Force | Out-Null; Remove-ItemSecure -Path $Archive.Directory -Recurse -Force | Out-Null;
Write-IcingaConsoleNotice 'Updating Framework cache file';
Write-IcingaFrameworkCodeCache;
Write-IcingaConsoleNotice 'Framework update has been completed. Please start a new PowerShell instance now to complete the update'; Write-IcingaConsoleNotice 'Framework update has been completed. Please start a new PowerShell instance now to complete the update';
Test-IcingaAgent; Test-IcingaAgent;