Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell is slow to convert integers to strings

I am writing a PowerShell script where many integers have to be converted to strings. I am using the ToString method to do this, as in:

$i = 5
$i.ToString()

Unfortunately, this seems to be very slow (I omitted the execution policy warning):

PS I:\ADCC\Scripting Performance> .\int_to_str.ps1
6.747561
PS I:\ADCC\Scripting Performance> .\int_to_str.py
0.37243021680382793

I am using PowerShell 2 and Python 3.

PS I:\ADCC\Scripting Performance> $PSVersionTable

Name                           Value
----                           -----
CLRVersion                     2.0.50727.5485
BuildVersion                   6.1.7601.17514
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.1


PS I:\ADCC\Scripting Performance> python --version
Python 3.6.1

This is the contents of int_to_str.ps1:

(Measure-Command {
    ForEach($i in 1..1000000){
        $i.ToString()
    }
}).TotalSeconds

This is the contents of int_to_str.py:

#!/usr/bin/env python3
import time
start = time.perf_counter()
for i in range(1, 1000000):
    str(i)
print(time.perf_counter() - start)

As you can see, both scripts convert integers from 1 to 1,000,000 to strings. However, while PowerShell takes 6.75 seconds, Python only takes 0.37 seconds, making Python 18 times faster. In the actual PowerShell script that I am writing, it takes about three hours to convert all of the integers to strings, so an 18-fold speed improvement would be welcome.

Is there a faster way to convert an int to a string in PowerShell 2?

like image 351
wecsam Avatar asked Jun 26 '17 19:06

wecsam


2 Answers

To answer your question, even in .NET (which is what you're using with PowerShell), here is a great article on the int->string conversion you care about: http://cc.davelozinski.com/c-sharp/fastest-way-to-convert-an-int-to-string.

As far as byte array conversions from AD, here is a test I did and with explicit casting to a [string[]], I nearly always saw gains over using .tostring(). The gains ranged from 50% to equivalent but it was consistently faster:

$s = [adsisearcher]'(&(objectCategory=user)(samaccountname=mysam))'
$r = @($s.FindAll())

(Measure-Command {
    foreach ($b in $r[0].Properties.userpassword[0]) {
        $b.tostring()
    }
}).TotalSeconds

(Measure-Command {
    [string[]]$r[0].Properties.userpassword[0]
}).TotalSeconds
like image 113
thepip3r Avatar answered Nov 14 '22 22:11

thepip3r


I have accepted @thepip3r's answer, but I want to highlight some other possible solutions from the comments on the question two things:

  1. You can use "$i" instead of $i.ToString(). It is faster.
  2. If you are on PowerShell 2, you can try downloading a newer version of the Windows Management Framework from Microsoft: https://www.microsoft.com/en-us/download/details.aspx?id=50395

I will edit this if more solutions appear in the comments.

like image 45
wecsam Avatar answered Nov 14 '22 22:11

wecsam