4

Does such feature exist? Something like Java HotSpot running in server mode, but for .Net applications.

EDIT: Little more information. I have small application (written in F#) and I have lots of small functions in it. Like this one:

let printable b =
    if b >= ' 'B && b <= '~'B
    then b else '.'B

I had realized that performance in poor, and after profiling I saw that every such function were called millions times. I made them inline and got performance boost (5+ times, may be more).

Ok, nice. Performance is good now. But why didn't the framework do it? It has enough information about my code and how often a function was called. Why didn't it inline an function that was called 1M times?

EDIT2: Sample test to measure difference of an inlined function:

    open System

    let printableByte b =
        if b >= ' 'B && b <= '~'B
        then b else '.'B

    let foo (arr : byte[]) = 
        for i in 0..arr.Length-1 do
            arr.[i] <- printableByte (arr.[i])
        arr.Length / 1000

    let main() =
        let sum = ref 0
        let arr = Array.create 1000000 0uy

        let stopWatch = System.Diagnostics.Stopwatch()
        stopWatch.Start()
        for x in 0..5000 do
            sum := !sum + (foo arr)

        stopWatch.Stop()
        printfn "%d" !sum 
        printfn "total time = %A" stopWatch.ElapsedMilliseconds
        ()

    main()

It runs 19.5 sec when printableByte is not inlined and 13.6 sec when inlined.

EDIT3: This time difference can be viewed only if compiled for x86 target and run on x64 host. There is no time difference if compiled for "anycpu" or x64.

So, there is no any issue with "small functions" and optimization.

qehgt
  • 2,972
  • 1
  • 22
  • 36
  • 2
    Yes, that's what the CLR's JIT does. – vcsjones May 04 '12 at 18:24
  • possible duplicate of [Performance differences between debug and release builds](http://stackoverflow.com/questions/4043821/performance-differences-between-debug-and-release-builds) – Hans Passant May 04 '12 at 18:26
  • 1
    @HansPassantI I added more information, the question is not related to debug/release modes. – qehgt May 04 '12 at 18:41
  • The title of the question misrepresents the actual question. A valid answer to the title would be "yes, .net does *some* optimization at run-time". This wouldn't actually answer your question. Maybe you should rephrase to "Does the Microsoft's .net CLR inline small functions at run-time?" – Joh May 04 '12 at 18:59
  • @qehgt - How, precisely, would the JIT compiler (at runtime) know that a function will be called 1M times? Yes, it could inline small methods by default, but then that could have different repercussions. The point is, the compiler can't figure out at JIT time how many times something gets called and optimize for it. Theoretically, it could do some runtime optimizations as it's running, but that's a very advanced kind of optimization. – Erik Funkenbusch May 04 '12 at 19:19
  • @MystereMan Hmm... Java HotSpot can do it, so I think it can be possible for .Net too. – qehgt May 04 '12 at 19:30
  • @qehgt - I don't believe it does. I've never heard of Hotspot being able to optimize runtime code based on how many times a method is called at runtime, and a google search doesn't immediately show any either. More than likely, hotspot just automatically inlines small functions, and not profiling the code and doing to for high use ones. – Erik Funkenbusch May 04 '12 at 19:50
  • @MystereMan, Oh, sorry, I was misled. – qehgt May 04 '12 at 20:15
  • 1
    @Mystere : The _server_ HotSpot does do adaptive runtime optimization based on "hot" code paths (hence then name), i.e. code paths or branches that are executed more frequently can be re-JIT-compiled with different or more aggressive optimizations. – ildjarn May 04 '12 at 21:03

3 Answers3

4

Yes, the CLR does some run-time optimization, as this blog shows. Note that according to this post, virtual method are not inlined.

neither of these methods was inlined:

  • Recursive method
  • Virtual method (even if the static type of the receiver variable is sealed)

How is your printable function called in your code? If the F# compiler wraps it in a closure, which it often does, even in cases where you might not expect it at first, then you'll fall into the "virtual method" case.

Joh
  • 2,380
  • 20
  • 31
  • Current version is here: https://github.com/qehgt/fsharp-netproxy/blob/7481a8807a1566d920a4f2ddd7ae47fd6bed788b/Program.fs Previous one was without `inline` keyword. – qehgt May 04 '12 at 19:24
  • `printableByte` in your code is a nested function. Those are sometimes implemented as closures. Release builds with optimization enabled should lift those nested functions that don't capture anything out of the containing function, though. I'm a bit surprised it's not doing that in your case. – Joh May 04 '12 at 19:39
  • @Jon, I'll double check it later. – qehgt May 04 '12 at 20:21
  • @Jon, I updated the topic. It looks like F# compiler does not want to inline functions without `inline` keyword. – qehgt May 04 '12 at 21:01
1

Please keep in mind that testing this code in FSI is not the same as compiling a project in Release mode.

My highly non-scientific tests show that the performance test you gave runs better in Debug if inline is added to the printableByte.

However, when inline is added in Release mode, the program actually performs worse than without it. I'm sure the F# compiler team or some disassembly could tell you why that is...

In my experience using F#, you should very rarely have to apply an inline optimization manually. Just make sure you compile in Release!

EDIT: Aha, yes! Be sure to compile in "Any CPU" mode unless you have a specific reason not to (usually my reason would be having to interoperate with x86 COM libraries from F#)

Dan Fitch
  • 2,480
  • 2
  • 23
  • 39
  • No, everything was done in Release on windows (or with `-O` on Linux).I did not use Fsi. – qehgt May 04 '12 at 21:26
  • Without inline in Release here: average 32s. With inline: average 35s. (Clearly my machine is older than yours, but I don't know what could explain the inversion.) – Dan Fitch May 04 '12 at 21:32
0

Yes, the .net framework optimizes the code for the platform it's running on. It takes many factors into account. There are some things it won't do, though.. For example, I don't believe it uses SIMD instructions if they're available. But it does do a good job of optimization in general.

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • @ildjarn - I think it still makes sense. The compiler does some run-time optimizations, the edit does not change that fact. Joh's answer has more information, so there is no reason for me to enhance mine. – Erik Funkenbusch May 04 '12 at 19:23
  • Not really -- the OP is not asking about platform-specific optimizations, he's asking about adaptive runtime optimization. – ildjarn May 04 '12 at 19:24
  • @ildjarn - The question has just be refined, it's still asking about runtime optimizations, and my answer is still valid for that. Just because he added additional questions to it doesn't mean it's invalid. – Erik Funkenbusch May 04 '12 at 19:53
  • I didn't downvote your answer, no need to get defensive. I only said something in the first place in case you weren't aware of the OP's edit and wanted to update your answer. – ildjarn May 04 '12 at 19:54