Viva la HashTable

On a toujours essayé d’optimiser au maximum les scripts et applications que l’on développait, car dès le moment que l’infrastructure est relativement importante, le gain est loin d’être négligeable (on l’a vu précédemment avec les optimisations sur le vCheck).

En se creusant la tête pour diminuer le temps d’exécution d’un script (ou plutôt d’un OneLiner), on a trouvé une nouvelle piste pour l’optimisation de vos scripts, un peu dans le même esprit que le NoSQL, à savoir se baser sur une association clé-valeur plutôt qu’un schéma relationnel complexe.

Pour cela, on va utiliser des hashtables que l’on va peupler au début du script et utiliser par la suite. La structure HashTable est très utile lors des recherches, car son cout en accès est très faible, en moyenne O(1) en notation BigO (aka ça envoie) :

Pour l’exemple, on avait un OneLiner relativement simple qui consistait à lister les machines virtuelles et leur cluster qui n’étaient pas dans un ressource pool (donc qui avaient comme parent le ressource pool ‘Resources’, un peu plus d’explication à la page 43 du document de gestion de ressource de VMware) :

get-view -ViewType virtualmachine -Property ResourcePool, Name | ?{(Get-View $_.ResourcePool -Property Name).Name -eq "Resources"} | Select @{n="Cluster";e={(get-view (Get-View $_.ResourcePool -Property Parent).Parent -Property Name).Name}}, Name

Ce OneLiner filtre déjà tous les appels Get-View pour minimiser le temps d’exécution mais prenait quand même pas mal de temps…

On a donc essayé de voir ce qu’on pouvait faire avec les hashtables. On a donc créé plusieurs hashtables afin de ne plus avoir aucun appel Get-View à part bien sûr le premier récupérant les machines virtuelles).

$htabResourcePool = @{}
$htabResourcePoolParent = @{}
$htabCluster = @{}

Une fois déclarées, on a peuplé ces hashtables avec les valeurs dont on avait besoin (en utilisant le MoRef pour la clé) :

get-view -viewtype resourcepool -property name -Filter @{"name"="Resources"} | %{$htabResourcePool.Add($_.MoRef,$_.Name)}
get-view -viewtype resourcepool -property parent -Filter @{"name"="Resources"} | %{$htabResourcePoolParent.Add($_.MoRef,$_.Parent)}
get-view -viewtype clustercomputeresource -property name | %{$htabCluster.Add($_.MoRef,$_.Name)}

On pourra ensuite les utiliser directement dans le OneLiner en remplaçant les appels Get-View par des opérations de recherches dans les hashtables :

get-view -ViewType virtualmachine -Property ResourcePool, Name | ?{$htabResourcePool[$_.ResourcePool] -eq "Resources"} | Select @{n="Cluster";e={$htabCluster[$htabResourcePoolParent[$_.ResourcePool]]}}, Name

Pour l’instant, on est au même niveau de résultats que la méthode sans les hashtables, mais il faut se poser la question du temps d’exécution :p

Pour cela, on a créé un script qui va exécuter les 2 traitements :

  1. la première méthode en récupérant via des appels Get-View
  2. la deuxième méthode en peuplant des hashtables et en les utilisant par la suite (le remplissage des hashtables faisant intégralement parti du test pour être réellement dans le même périmètre).

Le script affichera le nombre de résultat des 2 méthodes (afin de s’assurer que le contenu retourné est bien identique) et le temps pris. Dans notre exemple, nous avions un peu moins de 2200 VMs sur la plateforme interrogée et les résultats parlent d’eux-mêmes :

Pour ne pas se mettre à dos hypervisor.fr qu’on entend crier d’ici « Toucher pas à mon OneLiner! », l’exemple choisi est effectivement très parlant car il y a des imbrications d’appels Get-View donc le passage à des hashtables sera d’autant plus efficace :p

Il se peut donc que suivant le script, le gain de l’utilisation des hashtables ne soient pas aussi flagrant. Cependant, on vous invite à faire le test et comparer les temps d’exécution afin de vous faire un avis.

Voici le script utilisé pour effectuer les tests avec les 2 méthodes :

Write-Host -ForegroundColor Yellow "Benchmarking starting..."

Write-Host "`nMethod 1 (with regular filtered Get-View)"
$startMethod1 = Get-Date
$resultMethod1 = get-view -ViewType virtualmachine -Property ResourcePool, Name | ?{(Get-View $_.ResourcePool -Property Name).Name -eq "Resources"} | Select @{n="Cluster";e={(get-view (Get-View $_.ResourcePool -Property Parent).Parent -Property Name).Name}}, Name
$endMethod1 = Get-Date

Write-Host -ForegroundColor Green "Found"(($resultMethod1 | Measure-Object).Count)"records in"(($endMethod1 - $startMethod1).TotalSeconds)"seconds"

Write-Host "`nMethod 2 (with hashtable)"
$startMethod2 = Get-Date
$htabResourcePool = @{}
$htabResourcePoolParent = @{}
$htabCluster = @{}

get-view -viewtype resourcepool -property name -Filter @{"name"="Resources"} | %{$htabResourcePool.Add($_.MoRef,$_.Name)}
get-view -viewtype resourcepool -property parent -Filter @{"name"="Resources"} | %{$htabResourcePoolParent.Add($_.MoRef,$_.Parent)}
get-view -viewtype clustercomputeresource -property name | %{$htabCluster.Add($_.MoRef,$_.Name)}

$resultMethod2 = get-view -ViewType virtualmachine -Property ResourcePool, Name | ?{$htabResourcePool[$_.ResourcePool] -eq "Resources"} | Select @{n="Cluster";e={$htabCluster[$htabResourcePoolParent[$_.ResourcePool]]}}, Name
$endMethod2 = Get-Date

Write-Host -ForegroundColor Green "Found"(($resultMethod2 | Measure-Object).Count)"records in"(($endMethod2 - $startMethod2).TotalSeconds)"seconds"

6 comments

  1. Très bonne idée … D’ailleurs Zozor n’est t’il pas vert que l’idée n’ait pas été de lui ? 😉

  2. Pingback: Friday Shorts – VMworld content, #vBrownBag TechTalks and of course Sh!t I Starred! | mwpreston.net

Laisser un commentaire

Required fields are marked *.