About Me

My photo
Kozyatağı, İstanbul, Türkiye

Wednesday, December 11, 2013

An Algorithm for Restricting CPU Usage of CPU Bound Programs


For a CPU bound program which requires multi thread execution, we sometimes need certain number of processor cores to be used by our program and other cores to be left unassigned so that, other processes may utilize them.

Let's make the idea more clear:
I develop an exe application which performs long running calculations, such as running heuristic algorithms. During the calculations, I want to reserve some CPU resource for other processes so that my program will not "eat up" all the CPU resource.


Processor assignment can be achieved by setting processor affinity to threads:



C# Code:
        [DllImport("kernel32")]
        static extern int GetCurrentThreadId();

        static int unusedProcessorCount = 1;

        static void SetProcessorAffinity(int threadOrder)
        {
            int curThreadId = GetCurrentThreadId();
            int processorOrder = threadOrder % (Environment.ProcessorCount - unusedProcessorCount);
            int processorAddress = 1 << processorOrder;
            foreach (ProcessThread th in Process.GetCurrentProcess().Threads)
            {
                if (th.Id == curThreadId)
                {
                    th.ProcessorAffinity = (IntPtr)processorAddress;
                }
            }
        }



We can specify the number of cores that we want to be unassigned by setting the variable "unusedProcessorCount".

In the code above, the function that fetches current thread id needs to be imported from kernel32.dll. 

As soon as the function that thread executes is called, this function needs to call SetProcessorAffinity by passing its thread order so that the thread is assigned to the processor which comes up next.

Sunday, December 1, 2013

Retrieving All System Details by Windows PowerShell

Have you ever heard about Windows PowerShell? PowerShell is a great scripting tool for administrative tasks on computer.

So why is it "power"? Because it extends standard shell scripting with the power of .NET Framework. While accessing standard "command let"s of PowerShell, you can use any .NET Framework class. In addition to this, standard cmdlet library of PowerShell is quite enough for basic tasks that a system administrator may need.

Common Scenario: I want to display, all essential details of any computer on network. I want something quite more "advanced" than typing systeminfo on Windows command prompt.
The details I need are:             

n  Computer Name
n  Operating System,
n  Model
n  Manufacturer
n  Last Bootup Time
n  IP Address
n  Physical Memory Details: Capacity of each RAM on slots
n  Processor Details: For each  physical processor; number of cores, number of logical processors
n  Logical Disk Details: For each disk, free and total size
n  Process Details: Process name, Id, Memory Usage, Percent Load

We can achieve all, for any computer on network, by specifying computer name only.

Here is the script:
(You can run this script on Windows PowerShell ISE)


$computername = Read-Host 'Please Enter Computer Name'

$Name = Get-WmiObject win32_OperatingSystem -computer $computername | Select csName
$OperatingSystem = Get-WmiObject win32_OperatingSystem -computer $computername | Select Caption
$Model = get-wmiObject Win32_ComputerSystem  -computer $computername | select Model
$Manufacturer = get-wmiObject Win32_ComputerSystem  -computer $computername | select Manufacturer
$LastBootTime = Get-WmiObject Win32_OperatingSystem -computer $computername | select csname, @{LABEL='LastBootUpTime'; EXPRESSION={$_.ConverttoDateTime($_.LastBootupTime)}}
$PhysicalMemoryList = Get-WmiObject Win32_PhysicalMemory -computer $computername | select DeviceLocator, @{Name='Capacity_MB'; Expression={$_.Capacity / 1024 / 1024}}
$FreeMemoryMB = get-WmiObject Win32_PerfRawData_PerfOS_Memory -computer $computername | select AvailableMBytes 
$DiskList = Get-WmiObject Win32_LogicalDisk -computer $computername | select Caption, Description, @{Name="Total_Size_GB"; Expression={$_.Size/1024/1024/1024}}, @{Name="Free_Size_GB"; Expression={$_.FreeSpace/1024/1024/1024}}
$ProcessorList = Get-WmiObject Win32_Processor -computer $computername  | select Name, NumberOfCores, LoadPercentage, NumberOfLogicalProcessors
$allIpList = [System.Net.Dns]::GetHostEntry($computername) | select AddressList
$IP = ''
foreach ($item in $allIpList.AddressList)
{
 if ($item -notlike '*:*')
 {
  $IP = $item
 }
}

$ResObject = @{
ComputerName = $Name.csName
OperatingSystem = $OperatingSystem.Caption
Model = $Model.Model
Manufacturer = $Manufacturer.Manufacturer
LastBootUpTime = $LastBootTime.LastBootUpTime
FreeMemoryMB = $FreeMemoryMB.AvailableMBytes
IPAddress = $IP.IpAddressToString
#PhysicalMemoryList = $PhysicalMemoryList | Format-Table
#DiskList = $DiskList | Format-Table
#ProcessorList = $ProcessorList | Format-Table
}

$ResObject | Format-List

Write-Host 'Physical Memory Details: '
$PhysicalMemoryList | Format-Table

Write-Host 'Disk Details: '
$DiskList | Format-Table

Write-Host 'Processor Details: '
$ProcessorList | Format-Table

$answer = Read-Host "Do you want to get process details? Yes[Y]; No[N]"
if ($answer.ToUpper() -ne 'Y')
{
 Read-Host 'Script Ended'
 Exit
}

$procListDef = Get-WmiObject win32_process -computer $computername | select Name, ProcessId, @{Name='Owner'; Expression={$_.getowner() | select Domain, User}  }
$procListResource = get-WmiObject Win32_PerfFormattedData_PerfProc_Process -computer $computername | select Name, IDProcess, PercentProcessorTime, Timestamp_Sys100NS, WorkingSet

foreach ($proc in $procListDef )
{
 $ownerFullName = $proc.Owner.Domain + '\' + $proc.Owner.User;
 $res = $procListResource | Where-Object {$_.IDProcess -eq $proc.ProcessId}
 $percent = $res.PercentProcessorTime / [Environment]::ProcessorCount;
 $ws = $res.WorkingSet / 1024 / 1024
 
 $proc | Add-Member -type NoteProperty -name OwnerName -value $ownerFullName 
 $proc | Add-Member -type NoteProperty -name MemoryInMb -value $ws
 $proc | Add-Member -type NoteProperty -name PercentProcessorTime -value $percent
}

$procListDef | select Name, ProcessId, OwnerName, MemoryInMb, PercentProcessorTime | sort PercentProcessorTime -Descending | Format-Table
Read-Host 'Script Ended'