Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

for expression optimization #219

Closed
wants to merge 1 commit into from

Conversation

mrange
Copy link
Contributor

@mrange mrange commented Feb 6, 2015

(Moved from codeplex)
'for i in expr do body' optimization

Previously 'for i in expr do body' only had optimization
when the type of expr was an 1D-array.

'for i in expr do body' now has optimizations for when expr
is of type 'string' and 'List`1'.

These optimizations increases the performance of the for
expression but also reduces the number of objects created.

@@ -1097,6 +1097,14 @@ namespace Microsoft.FSharp.Core
//[<CompilerMessage("This function is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>]
val inline GetString : source:string -> index:int -> char

/// <summary>A compiler intrinsic that gets character from a string</summary>
[<CompilerMessage("This function is for use by compiled F# code and should not be used directly", 1204, IsHidden=true)>]
val inline GetStringChar : source:string -> index:int -> char
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am looking for alternatives to add these methods to prim-types.fsi. The issue is that in the optimizer there is not so much support for find the correct overloads. In the type-checker it was possible to find the proper overload but migrating that code to the optimizer proved difficult.

@mrange
Copy link
Contributor Author

mrange commented Feb 6, 2015

Just wanted to get the PR started again.

@@ -594,4 +594,4 @@ namespace Microsoft.FSharp.Collections
let truncate count list = Microsoft.FSharp.Primitives.Basics.List.truncate count list

[<CompiledName("Unfold")>]
let unfold<'T,'State> (f:'State -> ('T*'State) option) (s:'State) = Microsoft.FSharp.Primitives.Basics.List.unfold f s
let unfold<'T,'State> (f:'State -> ('T*'State) option) (s:'State) = Microsoft.FSharp.Primitives.Basics.List.unfold f s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useless whitespace change. Also newline at end of file is good

@dsyme
Copy link
Contributor

dsyme commented Feb 9, 2015

I think there's a problem with this PR when using FSharp.Core 4.3.0.0 or 4.3.1.0

The F# 4.0 compiler must be able to successfully work with FSHarp.Core 4.3.0.0 and 4.3.1.0. The GetStringChar and GetStringLength intrinsics won't be available in those libraries (TryDeref on the ValRef will return None). For those cases, we need to make sure the optimization doesn't apply

@KevinRansom @latkin - This reminds me that we really need to beef up our testing for this backward-library-targeting case. I wonder if the "single file test and run" in the "fsharp" suite needs to be beefed up with a compilation against both 4.3.0.0 and 4.3.1.0, with a #define to cover the API differences between the libraries.

@latkin
Copy link
Contributor

latkin commented Feb 12, 2015

Yes, when reviewing this on Codeplex, it got to a good state for F# 4.0-only. But design causes the 4.0 compiler to error out when it encounters one of these loops and is targeting 3.1.0 or earlier. This needs to be resolved.

@dsyme yes, this back-compat stuff is on my backlog. I have some ideas, just need to find time.

@dsyme
Copy link
Contributor

dsyme commented Feb 13, 2015

@mrange - I think you just need to add mkstringchar_vref to TcGlobals and check mkstringchar_vref.CanDeref as part of the case guard here: https://github.com/Microsoft/visualfsharp/pull/219/files#diff-b6f3f390e9807a7e9d93964104d74363R7819

Likewise for any other cases using new constructs

@mrange mrange force-pushed the pr/for_optimization branch from f98994f to 9fc834a Compare March 8, 2015 23:07
@mrange
Copy link
Contributor Author

mrange commented Mar 8, 2015

Hi.

Reworked the code so that it no longer relies on new functions being added to IntrinsicFunctions.

That should make the change backwards comptatible with FSharp.Core 4.3.0.0 and 4.3.1.0.

It's getting a bit late here so hopefully I haven't lost latkins portable fixes along the way.

@mrange
Copy link
Contributor Author

mrange commented Mar 9, 2015

AppVeyor seemed to break with:
Setting up Visual Studio for debugging extensions. This one-time operation may take a minute or more.
1575 C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe /RootSuffix FSharp /ResetSettings General.vssettings /Embedding /Command File.Exit
1576log4net : error XmlHierarchyConfigurator: Could not create Appender [RollingFileAppender] of type [log4net.Appender.RollingFileAppender]. Reported error follows. [C:\projects\visualfsharp-radou\vsintegration\src\deployment\EnableOpenSource\EnableOpenSource.csproj]
1577 System.IO.FileNotFoundException: Could not load file or assembly 'AWSToolkit.Util' or one of its dependencies. The system cannot find the file specified.
1578 File name: 'AWSToolkit.Util'

Previously 'for i in expr do body' only had optimization
when the type of expr was an 1D-array.

'for i in expr do body' now has optimizations for when expr
is of type 'string' and 'List`1'.

These optimizations increases the performance of the for
expression but also reduces the number of objects created.

latkin provided the following fixes:
1. Adapting tests to work with core\portable and core\netcore
2. Loop item over strings sometimes uses object, not char
3. Adjustments to debug ranges so that debug stepping behavior is consistent/unchanged
4. Updating codegen tests to represent corrected debug ranges
@mrange mrange force-pushed the pr/for_optimization branch from 1f87057 to 73509e9 Compare March 10, 2015 17:41
@mrange
Copy link
Contributor Author

mrange commented Mar 10, 2015

Tried a quick smoke test on 4.3.0.0 and 4.3.1.0 and it seems to work now.

@mrange
Copy link
Contributor Author

mrange commented Mar 10, 2015

Btw, I don't expect this to be merged until after 4.0 is released as I realize this is somewhat risky addition. Yet I want to get it to a mergable state.

Some(spForLoop,elemVar,startExpr,step,finishExpr,bodyExpr,m)
| _ ->
None
let DetectAndOptimizeForExpression g option expr =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exciting stuff

@latkin
Copy link
Contributor

latkin commented Aug 6, 2015

working on validating/merging this guy now

latkin pushed a commit that referenced this pull request Aug 6, 2015
Previously 'for i in expr do body' only had optimization
when the type of expr was an 1D-array.

'for i in expr do body' now has optimizations for when expr
is of type 'string' and 'List`1'.

These optimizations increases the performance of the for
expression but also reduces the number of objects created.

closes #219

commit e3935d95ce12a28f87e2d77c537b6f18e6d54d98
Author: latkin <latkin@microsoft.com>
Date:   Thu Aug 6 12:53:35 2015 -0700

    Add cross-version test cases

commit 1427f418ab1a2fb2b06684fafff809932714cf0a
Merge: 01dc508 73509e9
Author: latkin <latkin@microsoft.com>
Date:   Thu Aug 6 10:42:54 2015 -0700

    Merge branch 'pr/for_optimization' of https://github.com/mrange/visualfsharp into mrange-pr/for_optimization

    Conflicts:
    	src/fsharp/TcGlobals.fs
    	tests/fsharpqa/Source/Optimizations/ForLoop/env.lst

commit 73509e9
Author: mrange <marten_range@hotmail.com>
Date:   Mon Mar 9 00:04:11 2015 +0100

    'for i in expr do body' optimization..

    Previously 'for i in expr do body' only had optimization
    when the type of expr was an 1D-array.

    'for i in expr do body' now has optimizations for when expr
    is of type 'string' and 'List`1'.

    These optimizations increases the performance of the for
    expression but also reduces the number of objects created.

    latkin provided the following fixes:
    1. Adapting tests to work with core\portable and core\netcore
    2. Loop item over strings sometimes uses object, not char
    3. Adjustments to debug ranges so that debug stepping behavior is consistent/unchanged
    4. Updating codegen tests to represent corrected debug ranges
@latkin latkin added the fixed label Aug 7, 2015
@latkin
Copy link
Contributor

latkin commented Aug 7, 2015

Applied to the OOB branch. Thanks for being patient on this one, it's great to finally have this merged! I added cross-version tests and verified things are good in that regard.

@latkin latkin closed this Aug 7, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants