标题: [技术讨论] PowerShell解决用纯BAT几秒内生成几万个字符串组的问题 [打印本页]
作者: xczxczxcz 时间: 2018-12-17 17:31 标题: PowerShell解决用纯BAT几秒内生成几万个字符串组的问题
N久以前的事了。用纯P写,总是没达到要求。[任意7位数,以大定字母开头,后6位为大小写字母和数字的任意组合]
现在用 Powershell 写。不开多任务,约3秒多点 完成10000次,7秒多点 20000次 10秒30000次,也算符合要求。
如何把开头的字符数组直接写,不用 toCharArray()分割.可以少约 1秒。- $time=get-date
- $ULetter=@('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.toCharArray())
- $DigitLetter=@('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.toCharArray())
- while ($num -lt 10000){
- [Collections.ArrayList]$random=@(get-random -input $ULetter) #大写字母开头
- $random+=get-random -input $DigitLetter -count 6 #数字和大小写字母
- $str=-join $random #用 + 的方法连接字符约少 0.2秒。
- #if($str -match '(\d+){1,}') { #至少包含一位数字
- $str
- $num++
- #}
- }
- ([datetime]::now - $time).TotalMilliSeconds
- pause
复制代码
作者: 523066680 时间: 2019-3-21 19:21
本帖最后由 523066680 于 2019-3-21 19:28 编辑
- use Time::HiRes qw/time/;
- STDOUT->autoflush(1);
- my $ta = time();
- my @upper = ('A'..'Z');
- my @eles = ('a'..'z', 'A'..'Z', '0'..'9');
- my $e_len = scalar(@eles);
- my $key;
- for my $i (1..1000000)
- {
- $key = $upper[rand(26)] . join("", map { $eles[rand($e_len)] } (1..6) ) ;
- printf "%s\n", $key;
- }
- printf STDERR "time usage %.2f", time()-$ta;
复制代码
genCode.pl >F:/temp/a.txt
输出到机械硬盘,100W个,4秒
join "", map {} () 改成末尾append形式,100W个,3秒- for my $i (1..1000000)
- {
- $key = $upper[rand(26)];
- grep { $key .= $eles[rand($e_len)] } (1..6);
- printf "%s\n", $key;
- }
复制代码
CPU 频率 4GHz
作者: xczxczxcz 时间: 2019-3-21 20:51
回复 2# 523066680
I5 多线程 1000000个,要40多秒。感觉写法不太好。再研究一下。那个[random]等还用不好。
作者: 老刘1号 时间: 2019-3-21 22:06
回复 3# xczxczxcz
这种要求用解释型语言太伤了,根本没有效率可言
作者: ivor 时间: 2019-3-21 22:34
本帖最后由 ivor 于 2019-3-22 07:52 编辑
效率比楼主的初始化字符数组稍高一些- $start=[System.DateTime]::Now
- $num=0
- $array=(65..90) + (97..122) + (48..57)
- while ($num -lt 10000){
- [char[]](Get-Random -Count 7 -InputObject $array) -join ""
- $num+=1
- }
- ([System.DateTime]::Now - $start).TotalSeconds
- pause
复制代码
输出结果到控制台,最占时间,面向对象资源开销也比较大,所以面向过程的c语言最有优势。
作者: 523066680 时间: 2019-3-22 09:26
回复 3# xczxczxcz
我们的代码实质是差不多的,是解释器的优化不同。
回复 4# 老刘1号
如果解释器有对这类操作优化,内部实现对应的功能模型,执行速度就会接近编译型语言。
举个例子,CLGO 绘图,
基于CLGO的COOL解释器
对于图形程序,如果大部分指令调用都在解释层挨个执行,不要说GPU,CPU也是无法充分利用的。
OpenGL是怎么实现快速渲染的呢?DrawArrayElemensts 函数,我告诉GPU,我要三角形,把包含数十万个三角形坐标的数组指针传递过去,
然后把转换平移等通用的操作通过矩阵数组传递,GPU就会并行处理这些三角形的光栅化操作(空间变换、投影、深度测试、像素化、抗锯齿等),每秒是数十甚至上百帧。
如果每一个三角形都调用一次而不是传指针,CPU是吃不消的。所以那个帖子我记得有个作品的动图,画的圈并不多(不过万),但却是卡顿的。
如果要对这些批次的三角形做特殊效果,水墨描边、素描风格等,可以使用着色语言(Shader Language),一套直接和GPU核打交道的指令。
这也是行业发展的结果,硬件厂商知道你会大量执行这些操作,所以直接提供更合适的接口。
当时我也没什么建议,这里面解释器的学问太多了,我不懂。另外全套操作下来会感觉,还是用现成的吧,连硬件厂家都帮你考虑好了。
说完掏出硬件属性看了一下,看来还得学,不然挂着这个显卡太浪费
作者: bailong360 时间: 2019-3-22 18:47
100W, 输出到文件. 1.9s (包括 1.3s 的启动及编译时间- #!/usr/bin/pwsh -nop
- $Source = @"
- using System.IO;
- using System.Linq;
- using System;
-
- namespace Foo
- {
- public static class Bar
- {
- private static Random random = new Random();
-
- public static void RandomString()
- {
- const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- using (var file = new StreamWriter("test.txt")) {
- for (int i = 0; i <= 1000000; i++) {
- file.WriteLine(new string(Enumerable.Range(1, 7).Select(n => chars[random.Next(n == 1 ? 26 : chars.Length)]).ToArray()));
- }
- }
- }
- }
- }
- "@
-
- Add-Type -TypeDefinition $Source -Language CSharp
-
- [Foo.Bar]::RandomString();
复制代码
应该也算 PowerShell 吧 (笑
作者: xczxczxcz 时间: 2019-3-22 19:40
回复 7# bailong360
不会你的电脑比偶的还差吧。偶测试只有 0.716秒。
作者: 523066680 时间: 2019-3-22 19:54
一个段子,
用Java的人都戴墨镜。
因为……
They can't see sharp.
作者: yhcfsr 时间: 2019-3-22 21:26
回复 8# xczxczxcz
看来还是我的最好,我居然只用了563MS
作者: bailong360 时间: 2019-3-22 22:02
回复 8# xczxczxcz
Linux 上 pwsh 比较慢
直接用 mono 编译运行的话, 就只要 0.56s 左右
作者: bailong360 时间: 2019-3-22 22:05
本帖最后由 bailong360 于 2019-3-22 22:14 编辑
回复 7# bailong360
这段 C# 好像太快了点...
我用 Rust 实现了一下, 然而也花了 3s. 目前正在向 Rust 大佬们寻求优化方案......- use rand::{seq::SliceRandom, FromEntropy};
- use rand_xorshift::XorShiftRng;
- use std::fs::File;
- use std::io::Write;
-
- fn main() {
- let chars = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- let mut rng = XorShiftRng::from_entropy();
-
- let mut file = File::create("test.txt").unwrap();
- for _ in 0..1000000 {
- let v = (0..7)
- .map(|n| {
- if n == 0 {
- *chars.choose(&mut rng).unwrap()
- } else {
- **(&chars[0..26].choose(&mut rng).unwrap())
- }
- })
- .collect::<Vec<_>>();
- file.write_all(&v).unwrap();
- file.write_all(&[b'\n']).unwrap();
- }
- }
复制代码
=== 更新 ===
艹, 应该用 BufWriter wrap 一下, 这样就 0.16s 左右了...- let file = File::create("test.txt").unwrap();
- let mut file = BufWriter::new(file);
复制代码
作者: WHY 时间: 2019-3-23 22:15
本帖最后由 WHY 于 2019-3-25 23:05 编辑
如果非常在意几秒的差异,这样也许会比 get-Random 快那么一点。- $t=get-date
- $chr = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890';
- $swr = New-Object IO.StreamWriter('E:\1.Log', $false, [Text.Encoding]::ASCII);
- $rnd = New-Object System.Random;
- $arr = [Array]::CreateInstance('char', 7);
-
- for ($i = 0; $i -lt 1000000; $i++) {
- $arr[0] = $chr[$rnd.Next(26)];
- for ($j = 1; $j -le 6; $j++) {
- $arr[$j] = $chr[$rnd.Next(62)];
- }
- $swr.WriteLine($arr);
- }
- $swr.Close();
- ((get-Date) - $t).TotalSeconds
复制代码
Microsoft Windows [版本 10.0.17763.379]
(c) 2018 Microsoft Corporation。保留所有权利。
C:\Users\WHY>PowerShell -exec ByPass "&'E:\Test\Test.PS1'"
1.8277292
C:\Users\WHY>
作者: 老刘1号 时间: 2019-3-23 22:26
回复 7# bailong360
内嵌C#,秒啊
作者: 老刘1号 时间: 2019-3-23 23:08
来水一发,汇编- Include masm32rt.inc
- .const
- Table DB 'ACBDFEGHIKJLMOPQNRSTUVWXYZadcbefhigjklnmpoqsrtuvwzyx6578902314'
- .data?
- Input db 5 dup (?)
- Num dd ?
- Align 10h
- Buffer db 9*10000+1 dup (?)
- .code
- Start:
- Invoke ArgClC,1,Offset Input
- Sub esp,4
- Invoke atodw_ex,Offset Input
- Mov Num,Eax
- Add Esp,4
-
- Lea Esi,Table
- Mov Ecx,Eax
-
- .Repeat
- Push Ecx
- Lea Edi,Buffer
- Mov Ecx,10000
- Align 10h
- .Repeat
- Push Ecx
- Invoke nrandom,26
- Lea Eax,[Eax+65]
- StoSB
- Mov Ecx,6
- Align 4h
- .Repeat
- Push Ecx
- Invoke nrandom,SizeOf Table
- Mov Al,[Eax+Esi]
- StoSB
- Pop Ecx
- .UntilCxZ
- Mov Ax,0A0DH
- Mov Word Ptr [Edi],Ax
- Inc Edi
- Inc Edi
- Pop Ecx
- .UntilCxZ
- Xor Eax,Eax
- StoSB
- Invoke StdOut,Offset Buffer
- Pop Ecx
- .UntilCxZ
-
-
- Invoke ExitProcess,NULL
- End Start
复制代码
I3 CPU+机械
100w个,输出到控制台,40s(真感人)
输出到txt,220ms
直接>nul,180ms
test 要生成的数目/1w
生成100w:test 100
代码将指令、数据对齐到内存4整数倍地址,提高速度
随机数生成使用masmlib中的函数,不涉及api调用,浮点计算
由于懒得调api得时间做种子,目前种子固定。
作者: happy886rr 时间: 2019-3-23 23:16
速度取决于random的实现方式,一切都是伪随机,比的就是谁更虚伪。
作者: codegay 时间: 2019-3-28 07:59
nim语言版
结果很令我尴尬。
老笔记本 i5 2430M 耗时 60-68秒- import os, random, times
-
- var t = epochTime()
- randomize()
-
- let chars = {'A'..'Z', 'a'..'z', '0'..'9'}
- let upper = {'A'..'Z'}
- var f = open(getAppDir() / "result.txt", fmAppend)
-
-
- for i in 1..1000000:
- var str = ""
- str.add(upper.sample)
- for n in 1..6:
- str.add(sample(chars))
- str.add("\r\n")
- f.write(str)
- f.close()
-
- echo epochTime() - t
复制代码
作者: codegay 时间: 2019-3-28 11:31
本帖最后由 codegay 于 2019-3-28 11:33 编辑
配置还是i5 2430M, 固态硬盘
字符表改成array
默认编译参数 nim c -r ,并且不关电脑上的浏览器,播放器之类的软件,大约是7-9秒
编译命令nim c -d:release,关掉了其它软件的情况下达到复制代码
开了浏览器,播放器之类的软件的情况下1.1秒- import os, random, times
-
- var t = epochTime()
- randomize()
-
- let chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
- 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
- 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c',
- 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
- 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
-
- let upper = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
- 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
- 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
-
- var f = open(getAppDir() / "result.txt", fmAppend)
-
-
- for i in 1..1000000:
- var str = ""
- str.add(upper.sample)
- for n in 1..6:
- str.add(sample(chars))
- str.add("\r\n")
- f.write(str)
- f.close()
-
- echo epochTime() - t
复制代码
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |