Board logo

标题: [问题求助] 有没有文档可以解释PowerShell的Object[]速度比int[]还要快的原因呀? [打印本页]

作者: bylove    时间: 2023-9-14 16:59     标题: 有没有文档可以解释PowerShell的Object[]速度比int[]还要快的原因呀?

  1. $sw=[System.Diagnostics.Stopwatch]::new()
  2. do{
  3.     $sw.Start()
  4.     $max=1000000
  5.     [int[]]$arr=1..$max
  6.     $t1=$sw.Elapsed.TotalSeconds.ToString('0.00s')
  7.     $sw.Stop()
  8.     $sw.Reset()
  9.     $sw.Start()
  10.     [object[]]$arr=1..$max
  11.     $t2=$sw.Elapsed.TotalSeconds.ToString('0.00s')
  12.     $sw.Stop()
  13.     $t1,$t2
  14.     cmd /c pause
  15. }until(0)
复制代码
上面的t2简直快到没朋友了,不是一般来说Object占用内存是最大的吗,速度应该也是最慢吧?怎么会快那么多?

在我电脑上测试5组数据比较
结果如下:
0.43s
0.04s
请按任意键继续. . .
0.35s
0.02s
请按任意键继续. . .
0.40s
0.07s
请按任意键继续. . .
0.33s
0.02s
请按任意键继续. . .
0.36s
0.02s
请按任意键继续. . .

作者: bylove    时间: 2023-9-14 17:05

本帖最后由 bylove 于 2023-9-14 17:31 编辑

我在vba里的测试结果如下(换成1个亿):
  1. Sub main()
  2.     Max = 100000000
  3.     ReDim arr&(Max)
  4.     For j = 1 To 5
  5.     t = Timer
  6.         For i& = 0 To Max
  7.             arr(i) = i
  8.         Next
  9.         Debug.Print Format(Timer - t, "0.00s")
  10.     Next
  11. End Sub
复制代码
int[]
1.11s
1.12s
1.13s
1.14s
1.13s
  1. Sub main()
  2.     Max = 100000000
  3.     ReDim arr(Max)
  4.     For j = 1 To 5
  5.     t = Timer
  6.         For i& = 0 To Max
  7.             arr(i) = i
  8.         Next
  9.         Debug.Print Format(Timer - t, "0.00s")
  10.     Next
  11. End Sub
复制代码
Variant[]
1.62s
1.60s
1.56s
1.54s
1.60s


我很意外,vba速度居然完爆PowerShell
作者: bylove    时间: 2023-9-14 17:12

本帖最后由 bylove 于 2023-9-14 17:30 编辑
  1. $sw=[System.Diagnostics.Stopwatch]::new()
  2. $sw.Start()
  3. $max=100000000
  4. [object[]]$arr=1..$max
  5. $t1=$sw.Elapsed.TotalSeconds.ToString('0.00s')
  6. $sw.Stop()
  7. $t1
复制代码
22.22s
  1. $sw=[System.Diagnostics.Stopwatch]::new()
  2. $sw.Start()
  3. $max=100000000
  4. [object]$arr=1..$max
  5. $t1=$sw.Elapsed.TotalSeconds.ToString('0.00s')
  6. $sw.Stop()
  7. $t1
复制代码
17.42s

这边按照vba一样的逻辑测试时间实在是超的太多了吧?(1亿测试)
Object与Object[]的时间也是不一样的
  1. $sw=[System.Diagnostics.Stopwatch]::new()
  2. $sw.Start()
  3. $max=100000000
  4. [int[]]$arr=1..$max
  5. $t1=$sw.Elapsed.TotalSeconds.ToString('0.00s')
  6. $sw.Stop()
  7. $t1
复制代码
43.58s

不懂为什么改int[]时间直接成倍上涨,2倍多了
作者: bylove    时间: 2023-9-14 17:19

本帖最后由 bylove 于 2023-9-14 17:30 编辑
  1. $sw=[System.Diagnostics.Stopwatch]::new()
  2. $sw.Start()
  3. $max=100000000
  4. [System.Collections.Generic.List[int]]$arr=1..$max
  5. $t1=$sw.Elapsed.TotalSeconds.ToString('0.00s')
  6. $sw.Stop()
  7. $t1
复制代码
用List速度会变快我可以理解,但List[int]一样也慢.

换Object试试
  1. $sw.Start()
  2. $max=100000000
  3. [System.Collections.Generic.List[object]]$arr=1..$max
  4. $t1=$sw.Elapsed.TotalSeconds.ToString('0.00s')
  5. $sw.Stop()
  6. $t1
复制代码
10.52s

这么看来根据上面测试汇总一下:

Object与List[Object] 17.42s, 10.52s

int与int[] 43.58s, 32.73s
作者: Five66    时间: 2023-9-14 17:24

字符串数值跟二进制数值???
范围类型跟基础类型???
作者: wanghan519    时间: 2023-9-14 17:47

回复 2# bylove


    vba里的字典,keys10万和100万的耗时相差非常多,而且key用字符串比用数字快很多,请问大概是什么原因,多谢
作者: bylove    时间: 2023-9-14 18:00

本帖最后由 bylove 于 2023-9-14 18:07 编辑

VB.net
  1.     Sub Main()
  2.         Dim t# = 0, max = 100000000, arr%()
  3.         ReDim arr%(max)
  4.         For j% = 1 To 5
  5.             t = Environment.TickCount
  6.             For i% = 0 To max - 1
  7.                 arr(i) = i
  8.             Next
  9.             Console.WriteLine(((Environment.TickCount - t) / 1000).ToString("0.00s"))
  10.         Next
  11.         Console.ReadKey(1)
  12.     End Sub
复制代码

0.52s
0.41s
0.31s
0.30s
0.33s


C#
  1.         static void Main(string[] args)
  2.         {
  3.             int max = 100000000;
  4.             int[] arr = new int[max];
  5.             for (int j = 0; j < 5; j++)
  6.             {
  7.                 double t = Environment.TickCount;
  8.                 for (int i = 0; i < max; i++)
  9.                 {
  10.                     arr[i] = i;
  11.                 }
  12.                 Console.WriteLine(((Environment.TickCount - t) / 1000).ToString("0.00s"));
  13.             }
  14.             Console.ReadKey(true);
  15.         }
复制代码
0.44s
0.31s
0.34s
0.36s
0.27s

PowerShell和c#从时间上来看差异也不大啊都是net上的方法

只能解释可能是由于PowerShell是解释型语言所以速度比vba还要慢了吧?

但是慢的也太多了吧?

这个就不谈了,怎么解释Object速度比int快呢?不应该是反过来吗?
作者: wanghan519    时间: 2023-9-14 18:14

回复 7# bylove


    试了一下(1..10)的类型是Object[],可能是int[]需要转换类型吧
还有就是上面的问题,vba里的字典,10万个key1秒,100万个key需要70秒,还有字符串key比longkey快很多,真的懵b。。。
作者: bylove    时间: 2023-9-14 18:17

回复 6# wanghan519


    vba的字典和net的字典好像根本比不了,如果处理数据量非常大的话,速度可能还没PowerShell脚本快(应该)
    net的字典查询添加速度都比vba快,原因我就不清楚了

    整数好像是要比字符串慢的,可能是字符串的字数少?
作者: wanghan519    时间: 2023-9-14 18:17

回复 7# bylove


    还有就是powershell调用函数好慢,同样的递归c#里0.2秒,powershell里100秒...
作者: bylove    时间: 2023-9-14 18:21

本帖最后由 bylove 于 2023-9-14 18:24 编辑

回复 10# wanghan519


    我觉得会不会是因为你类型声明不对啊?试试优化一下,这个问题我也解释不了,感觉原先vba里的概念带入到PowerShell里就感觉PowerShell慢的跟蜗牛一样.而且经过测试vba的速度和c#比还算正常 甚至速度比c#还快上一点点.
当然这只是逻辑很简单的测试,我相信逻辑复杂的测试vba速度肯定不如c#

另外有的时候又觉得vba速度不如PowerShell,感觉用工具的时候就很混乱,不知道应该用哪一个

唯一能解释PowerShell速度能比vba快的原因是PowerShell调用了net的方法,如果用PowerShell自带的函数可能也会快,但手动撸的自定义函数如果优化的不好,很可能没vba的快
作者: bylove    时间: 2023-9-14 18:26

回复 8# wanghan519


    还有添加字典速度本来就很慢啊,添加字典尽量用add 不要用obj(xx)=xx 这种效率极其的慢,如果你都这么做了还慢那就不好说了,我也不清楚,哈哈
作者: bylove    时间: 2023-9-14 18:47

回复 10# wanghan519


    我刚用c#测试了一下int[]和Object[] 换成Object[]后时间感觉已经超过10秒以上了,我直接停止调试了,但是int[]测试还是0.5s  测试循环是1亿

所以我没有怀疑错,Object类型就是会比int慢的

但是不懂为什么PowerShell里是反过来的.晕了我
作者: wanghan519    时间: 2023-9-14 18:54

回复 13# bylove


    因为c#里是直接用int数据往里填,powershell里你的写法是1..100,但这东西是object[]类型的。。。
作者: bylove    时间: 2023-9-14 19:20

本帖最后由 bylove 于 2023-9-14 19:26 编辑

回复 14# wanghan519


    可是PowerShell里你写1..100速度就是比for($i=0;$i -lt 100;$i++) 快啊,怎么解释?

想变快貌似只能用Linq了:
  1. $t=[System.Environment]::TickCount
  2. [object]$x=[System.Linq.Enumerable]::Range(1,100000000)
  3. (([System.Environment]::TickCount-$t)/1000).ToString('0.00s')
复制代码





欢迎光临 批处理之家 (http://bathome.net./) Powered by Discuz! 7.2