PowerShell将整数转换为字符串速度较慢。

5

我正在编写一段PowerShell脚本,其中需要将许多整数转换为字符串。我使用ToString方法来完成这个操作,如下所示:

$i = 5
$i.ToString()

不幸的是,这似乎非常缓慢(我省略了执行策略警告):

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

我正在使用PowerShell 2和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

这是int_to_str.ps1的内容:
(Measure-Command {
    ForEach($i in 1..1000000){
        $i.ToString()
    }
}).TotalSeconds

这是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)

如您所见,这两个脚本都将1到1000000之间的整数转换为字符串。但是,PowerShell需要6.75秒,而Python只需要0.37秒,使得Python快18倍。在我正在编写的实际PowerShell脚本中,将所有整数转换为字符串需要大约三个小时,因此18倍的速度提高将会受到欢迎。
在PowerShell 2中有更快的将int转换为string的方法吗?

1
不是整数转字符串的速度慢,而很可能是范围操作(即Python的range()在这种情况下比PowerShell的..运算符快得多)。你究竟想要实现什么? - Mathias R. Jessen
@MathiasR.Jessen 我正在从Active Directory获取一些数据,返回的是字节数组,将每个字节转换为整数字符串表示,并将它们写入CSV文件。这些字节数组特别长。我不确定是range操作变慢了,(Measure-Command {(5).ToString()}).TotalMilliseconds仍然返回0.0472,而start=time.perf_counter()str(5)print(time.perf_counter() - start)打印1.995030623720074e-05。 - wecsam
3
如果您想让脚本运行更快,请发布您的脚本。 - Mathias R. Jessen
在我的机器上,PowerShell(2.0版)运行大约需要3.6秒。当我使用"$i"进行转换时,可以节省一秒钟的时间。我同意最好看到您实际的代码实现。在v5中只需要1.5秒。 - Matt
@thepip3r 谢谢,我之前不知道有这个下载。 - wecsam
显示剩余11条评论
2个回答

6
我已经接受了@thepip3r的答案,但我想强调一些可能来自问题评论中的其他解决方案:
  1. 您可以使用"$i"而不是$i.ToString()。它更快。
  2. 如果您使用的是PowerShell 2,则可以尝试从Microsoft下载更新版本的Windows Management Framework:https://www.microsoft.com/en-us/download/details.aspx?id=50395
如果在评论中出现更多解决方案,我将进行编辑。

6
为了回答你的问题,在使用PowerShell时,即使在.NET中,这篇文章介绍了你关心的int->string转换的最佳实践:http://cc.davelozinski.com/c-sharp/fastest-way-to-convert-an-int-to-string
至于从AD进行字节数组转换,我进行了测试并采用显式类型转换为 [string[]],几乎总是比使用".tostring()"更快。提速效果在50%到相当之间,但速度始终如一。
$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

1
这是一个好建议。我用我的1,000,000个整数尝试了一下,转换为string[]的速度快了五倍。 - wecsam
2
澄清一下,[string[]](1..1000000) 的速度大约比 ForEach($i in 1..1000000) { $i.ToString() } 快五倍。 - wecsam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接