Tuesday 25 August 2009

XenApp Server Scaling Script

I wrote this script to help us try and scale our Citrix XenApp Server Farm.
This is to help answer the age old How many users per server question ?

To describe it simply the script should be run on a typical server in each silo during a peak period. It will then tell you the Average and Max amount of memory being used per user.
This will allow me to make an informed scale decision based only on Memory, of course other server metrics will need to be considered but memory is the bottleneck in my environment.

Running this script over a period of time will allow us to get a good picture of how much memory an average user requires within each silo. This statistic can then be used to plan how many users can be handled per server.

We will also continue to run the script to detect if the user memory profile changes in which case the numbers can be revised.

The script simply uses tasklist to get the Working set size for each process and then tidys up the data into per user info. I will be improving the script more but this is my v1 posting. I will be getting it to get average memory figures per process as well as this will also need to be factored into the server sizing estimate.

'
' Script to sort information from a Tasklist output
'
' The script totals up the memory useage for each user
'
'
Set objShell = CreateObject("WScript.Shell")
Retrun = objShell.Run("cmd /c tasklist /nh /fo csv >input.txt",1,True)
Set objFSO = CreateObject("Scripting.fileSystemObject")
Set objInputFile = objFSO.OpenTextFile("input.txt",1)
Set ObjOutPutFile = objFSO.CreateTextFile("output.txt",True)
Set tasklist = CreateObject("Scripting.Dictionary")


Dim tasklist, StrValues, StrData, KeyItem, StrProcessList, Username, StrKeyList, Memory, MemTotal

Do While objInputFile.AtEndofStream <> True

Strdata = objInputFile.ReadLine ' Read the Line
Splitter = CHR(34)&","&CHR(34) '
Strvalues = Split(StrData,Splitter) ' Chop up via ","
StrValues(4) = Replace(StrValues(4),CHR(34),"") '
ValMemory = StrValues(4) ' Get The Memory Value
Pos = Instr(ValMemory,"K") ' Chop out the K character
Pos = Pos-1
ValMemory = Left(Valmemory,Pos) ' Get Memory Value
UserName = StrValues(2) ' Get USERNAME
ValMemory=cLng(Valmemory) ' Turn to Integer
ValMemory=ValMemory/1024 ' Convert to MB
ValMemory = Round(ValMemory,2) ' Round up to 2 Decimals

' Populate the Tasklist Dictionary with the Memory Figure

If Tasklist.Exists(UserName) Then
Ctr=0
Memtemp = Tasklist.Item(Username)
Memtotal = ValMemory + Memtemp
Tasklist.remove(UserName)
Tasklist.Add UserName, MemTotal
Else
Tasklist.Add UserName, ValMemory
If Username = "ICA-tcp#15" Then wscript.echo "NEW USER" & ValMemory
End If

Loop

Username = tasklist.Keys
Memtotal = tasklist.Items
UserCount = 0
MemBig = 0

' Calculate total Memory Useage and Largest user

For i = 0 to Tasklist.count - 1
ObjOutPutFile.Writeline "User : " & Username (i) & " Total Memory : " & Memtotal(i) & "MB"
If Memtotal(i) > MemBig and Username(i) <> "Console" Then
MemBig = Memtotal(i)
StrLargestUser = username(i)
End If

' Dont Include Console in the stats

If Username(i) <> "Console" Then
TotalMem = memtotal(i) + TotalMem
UserCount = UserCount + 1
End If

Next

' Write the output to file

ObjOutPutFile.Writeline "========================================== "
ObjOutPutFile.Writeline "Total Users : " & UserCount
ObjOutPutFile.Writeline "Total Memory : " & TotalMem & "MB"
ObjOutPutFile.Writeline "Average per user : " & Round(Totalmem/Usercount,2) & "MB"
ObjOutPutFile.Writeline "Largest User : " & StrLargestUser & " Total : " & round(MemBig,2) & "MB"

objInputFile.Close
ObjOutPutFile.Close

' Display the output file
Return = objShell.Run("%comspec% /c notepad output.txt",0,False)

No comments:

Post a Comment