189 8069 5689

详解F#版本的CodeTimer方法实现

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

创新互联公司主要从事网站设计制作、成都网站制作、网页设计、企业做网站、公司建网站等业务。立足成都服务尼开远,10余年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:18980820575

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

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


标题名称:详解F#版本的CodeTimer方法实现
网页地址:http://cdxtjz.cn/article/djcpsei.html

联系我们

您好HELLO!
感谢您来到成都网站建设公司,若您有合作意向,请您为我们留言或使用以下方式联系我们, 我们将尽快给你回复,并为您提供真诚的设计服务,谢谢。
  • 电话:028- 86922220 18980695689
  • 商务合作邮箱:631063699@qq.com
  • 合作QQ: 532337155
  • 成都网站设计地址:成都市青羊区锣锅巷31号五金站写字楼6楼

小谭建站工作室

成都小谭网站建设公司拥有多年以上互联网从业经验的团队,始终保持务实的风格,以"帮助客户成功"为已任,专注于提供对客户有价值的服务。 我们已为众企业及上市公司提供专业的网站建设服务。我们不只是一家网站建设的网络公司;我们对营销、技术、管理都有自己独特见解,小谭建站采取“创意+综合+营销”一体化的方式为您提供更专业的服务!

小谭观点

相对传统的成都网站建设公司而言,小谭是互联网中的网站品牌策划,我们精于企业品牌与互联网相结合的整体战略服务。
我们始终认为,网站必须注入企业基因,真正使网站成为企业vi的一部分,让整个网站品牌策划体系变的深入而持久。