详解F 详解费米悖论
创始人
2024-06-11 17:41:15
0

对于F#这个微软的新丁,很多人并不熟悉。很多开发人员知道函数式编程方面Scala可以算一个,但是不知道F#中CodeTimer妙用。本文借用作者的文章,希望能让大家对F#有更深刻的了解。

#T#

CodeTimer很好用,自从在今年三月在.NET技术大会上看到Jeffrey Richter用类似的东西之后,我就自己写了一个。不过,当时是用C#写的,现在我需要在F#里做相同的事情就不那么方便了。当然,F#与.NET本是无缝集成,因此C#写的CodeTimer也应该可以被F#使用。不过,我平时在使用CodeTimer时并不是通过程序集引用,而是使用代码复制的方式,因此如果有个F#版本那么应该使用起来更加方便。

代码如下:

  1. #light  
  2. module CodeTimer  
  3. open System  
  4. open System.Diagnostics  
  5. open System.Threading  
  6. open System.Runtime.InteropServices  
  7.  
  8. ["kernel32.dll")>]  
  9. extern int QueryThreadCycleTime(IntPtr threadHandle, uint64* cycleTime)  
  10.  
  11. ["kernel32.dll")>]  
  12. extern IntPtr GetCurrentThread();  
  13.  
  14. let private getCycleCount() =   
  15.     let mutable cycle = 0UL  
  16.     let threadHandle = GetCurrentThread()  
  17.     QueryThreadCycleTime(threadHandle, &&cycle) |> ignore  
  18.     cycle  
  19.  
  20. let time name iteration action =  
  21.  
  22.     if (String.IsNullOrEmpty(name)) then ignore 0 else 
  23.  
  24.     // keep current color  
  25.     let currentForeColor = Console.ForegroundColor  
  26.     Console.ForegroundColor <- ConsoleColor.Yellow  
  27.     printfn "%s" name  
  28.  
  29.     // keep current gc count  
  30.     GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);  
  31.     let gcCounts =  
  32.         [0 .. GC.MaxGeneration]  
  33.         |> List.map (fun i -> (i, GC.CollectionCount(i)))  
  34.         |> List.fold (fun acc i -> i :: acc) []  
  35.         |> List.rev  
  36.  
  37.     // keep cycle count and start watch  
  38.     let threadPtr = GetCurrentThread()  
  39.     let cycle = getCycleCount()  
  40.     let watch = Stopwatch.StartNew()  
  41.       
  42.     // run  
  43.     for i = 1 to iteration do action();  
  44.       
  45.     let cycleUsed = getCycleCount() - cycle  
  46.     watch.Stop()  
  47.  
  48.     // restore the color  
  49.     Console.ForegroundColor <- currentForeColor;  
  50.  
  51.     // print  
  52.     watch.ElapsedMilliseconds.ToString("N0") |> printfn "\tTime Elapsed:\t%sms" 
  53.     cycle.ToString("N0") |> printfn "\tCPU Cycles:\t%s" 
  54.     gcCounts |> List.iter (fun (i, c) ->   
  55.         printfn "\tGen%i:\t\t%i" i (GC.CollectionCount(i) - c))  
  56.  
  57.     printfn "" 
  58.  
  59. let initialize() =  
  60.     Process.GetCurrentProcess().PriorityClass <- ProcessPriorityClass.High  
  61.     Thread.CurrentThread.Priority <- ThreadPriority.Highest  
  62.     time "" 0 (fun() -> ignore 0) 

结果是:

  1. Wait  
  2.         Time Elapsed:   684ms  
  3.         CPU Cycles:     372,709,908  
  4.         Gen0:           0  
  5.         Gen1:           0  
  6.         Gen2:           0 

与C#版本的CodeTimer相比,第一版的F# CodeTimer少算了CPU使用周期的消耗——不是我不想,而是遇到了问题。我当时这样引入P/Invoke的签名:

  1. open System.Runtime.InteropServices  
  2. [("kernel32.dll")>]  
  3. extern int QueryThreadCycleTime(IntPtr threadHandle, uint32* cycleTime)  
  4. [("kernel32.dll")>]  
  5. extern IntPtr GetCurrentThread(); 

F#在P/Invoke签名中使用*来标记out参数,但是在自定义方法时使用的是byref,这点与C#不同,后者都是使用ref。这个引入看似没有问题,而且普通调用也能得到正常结果:

  1. []  
  2. let main args =  
  3.  
  4.     let mutable cycle = 0u 
  5.     let threadHandle = CodeTimer.GetCurrentThread()  
  6.     CodeTimer.QueryThreadCycleTime(threadHandle, &&cycle) |> ignore  
  7.  
  8.     Console.ReadLine() |> ignore  
  9.     0 

但是,一旦我把它加为CodeTimer的一个方法,如getCycleCount:

  1. let getCycleCount() =   
  2.     let mutable cycle = 0u  
  3.     let threadHandle = GetCurrentThread()  
  4.     QueryThreadCycleTime(threadHandle, &&cycle) |> ignore  
  5.     cycle 

这样调用的时候就会抛出异常:

抛出异常

后经alonesail同学指出,引入QueryThreadCycleTime的时候,第二个参数应该是64位而不是32位无符号整数——我将PULONG64看作PULONG了。改成uint64便没有问题了。

原文标题:F#版本的CodeTimer(已支持CPU时钟周期统计)

链接:http://www.cnblogs.com/JeffreyZhao/archive/2009/11/13/fsharp-codetimer.html

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...