diff --git a/.gitignore b/.gitignore
index 95851a4bc83..3cfeb6c1cb3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -125,3 +125,4 @@ nCrunchTemp_*
/test.fsx
tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.actual
+*.vsp
diff --git a/VisualFSharp.sln b/VisualFSharp.sln
index 4f4947d3491..343c976316e 100644
--- a/VisualFSharp.sln
+++ b/VisualFSharp.sln
@@ -184,7 +184,7 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "fsiAnyCpu", "src\fsi\fsiAny
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "fsiArm64", "src\fsi\fsiArm64Project\fsiArm64.fsproj", "{EB015235-1E07-4CDA-9CC6-3FBCC27910D1}"
EndProject
-Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "HistoricalBenchmark", "tests\benchmarks\FCSBenchmarks\BenchmarkComparison\HistoricalBenchmark.fsproj", "{583182E1-3484-4A8F-AC06-7C0D232C0CA4}"
+Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "HistoricalBenchmark", "tests\benchmarks\FCSBenchmarks\BenchmarkComparison\HistoricalBenchmark.fsproj", "{583182E1-3484-4A8F-AC06-7C0D232C0CA4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FCSBenchmarks", "FCSBenchmarks", "{39CDF34B-FB23-49AE-AB27-0975DA379BB5}"
ProjectSection(SolutionItems) = preProject
@@ -193,6 +193,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FCSBenchmarks", "FCSBenchma
tests\benchmarks\FCSBenchmarks\SmokeTestAllBenchmarks.ps1 = tests\benchmarks\FCSBenchmarks\SmokeTestAllBenchmarks.ps1
EndProjectSection
EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Fsharp.ProfilingStartpointProject", "tests\benchmarks\Fsharp.ProfilingStartpointProject\Fsharp.ProfilingStartpointProject.fsproj", "{FE23BB65-276A-4E41-8CC7-F7752241DEBA}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1019,6 +1021,18 @@ Global
{583182E1-3484-4A8F-AC06-7C0D232C0CA4}.Release|Any CPU.Build.0 = Release|Any CPU
{583182E1-3484-4A8F-AC06-7C0D232C0CA4}.Release|x86.ActiveCfg = Release|Any CPU
{583182E1-3484-4A8F-AC06-7C0D232C0CA4}.Release|x86.Build.0 = Release|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Debug|x86.Build.0 = Debug|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Proto|Any CPU.Build.0 = Debug|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Proto|x86.ActiveCfg = Debug|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Proto|x86.Build.0 = Debug|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Release|x86.ActiveCfg = Release|Any CPU
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1089,6 +1103,7 @@ Global
{B5A9BBD9-2F45-4722-A6CA-BAE3C64CD4E2} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77}
{14F3D3D6-5C8E-43C2-98A2-17EA704D4DEA} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449}
{A422D673-8E3B-4924-821B-DD3174173426} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D}
+ {564E7DC5-11CB-4FCF-ABDD-23AD93AF3A61} = {39CDF34B-FB23-49AE-AB27-0975DA379BB5}
{B1E30F2C-894F-47A9-9C8A-3324831E7D26} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D}
{597D9896-4B90-4E9E-9C99-445C2CB9FF60} = {B8DDA694-7939-42E3-95E5-265C2217C142}
{0973C362-585C-4838-9459-D7E45C6B784B} = {B8DDA694-7939-42E3-95E5-265C2217C142}
@@ -1096,9 +1111,9 @@ Global
{511C95D9-3BA6-451F-B6F8-F033F40878A5} = {B8DDA694-7939-42E3-95E5-265C2217C142}
{37EB3E54-ABC6-4CF5-8273-7CE4B61A42C1} = {B8DDA694-7939-42E3-95E5-265C2217C142}
{EB015235-1E07-4CDA-9CC6-3FBCC27910D1} = {B8DDA694-7939-42E3-95E5-265C2217C142}
- {39CDF34B-FB23-49AE-AB27-0975DA379BB5} = {DFB6ADD7-3149-43D9-AFA0-FC4A818B472B}
- {564E7DC5-11CB-4FCF-ABDD-23AD93AF3A61} = {39CDF34B-FB23-49AE-AB27-0975DA379BB5}
{583182E1-3484-4A8F-AC06-7C0D232C0CA4} = {39CDF34B-FB23-49AE-AB27-0975DA379BB5}
+ {39CDF34B-FB23-49AE-AB27-0975DA379BB5} = {DFB6ADD7-3149-43D9-AFA0-FC4A818B472B}
+ {FE23BB65-276A-4E41-8CC7-F7752241DEBA} = {39CDF34B-FB23-49AE-AB27-0975DA379BB5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {48EDBBBE-C8EE-4E3C-8B19-97184A487B37}
diff --git a/buildtools/AssemblyCheck/SkipVerifyEmbeddedPdb.txt b/buildtools/AssemblyCheck/SkipVerifyEmbeddedPdb.txt
index f823017f4a1..9ea06757477 100644
--- a/buildtools/AssemblyCheck/SkipVerifyEmbeddedPdb.txt
+++ b/buildtools/AssemblyCheck/SkipVerifyEmbeddedPdb.txt
@@ -1,5 +1,6 @@
FSharp.Build.UnitTests.dll
FSharp.Compiler.Benchmarks.dll
+Fsharp.ProfilingStartpointProject.dll
FSharp.Compiler.ComponentTests.dll
FSharp.Test.Utilities.dll
FSharp.Compiler.Private.Scripting.UnitTests.dll
diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FSharp.Compiler.Benchmarks.fsproj b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FSharp.Compiler.Benchmarks.fsproj
index d1187649935..0d5fe5df518 100644
--- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FSharp.Compiler.Benchmarks.fsproj
+++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FSharp.Compiler.Benchmarks.fsproj
@@ -11,6 +11,7 @@
Microsoft.NETCore.App.Host.win-x64 [6.0.2], Microsoft.NETCore.App.Host.win-x64 [6.0.2], Microsoft.NETCore.App.Host.win-x64 [6.0.2], Microsoft.NETCore.App.Host.win-x64 [6.0.2].
-->
$(NoWarn);NU1505
+ false
diff --git a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FileCascadeBenchmarks.fs b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FileCascadeBenchmarks.fs
index 746f81065b7..accffc76c12 100644
--- a/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FileCascadeBenchmarks.fs
+++ b/tests/benchmarks/FCSBenchmarks/CompilerServiceBenchmarks/FileCascadeBenchmarks.fs
@@ -37,52 +37,114 @@ module private CascadeProjectHelpers =
$"""
module Benchmark0
let returnValue = 5
-let myFunc0 () = 5"""
+let myFunc0 () = returnValue
+type MyType0 = MyType0 of string
+type MyOtherType0 = MyOtherType0 of int"""
+
+ let baselineFsi =
+ """
+module Benchmark0
+
+val returnValue: int
+
+val myFunc0: unit -> int
+
+type MyType0 = | MyType0 of string
+
+type MyOtherType0 = | MyOtherType0 of int"""
let generateSourceCode number =
$"""
module Benchmark%i{number}
open Benchmark%i{number-1}
let myFunc%i{number} () = myFunc%i{number-1}()
+type MyType{number} = MyType{number} of string
+type MyOtherType{number} = MyOtherType{number} of int
+type MyFunctionType{number} = MyType{number} -> MyOtherType{number}
+
+let processFunc{number} (x) (func:MyFunctionType{number}) =
+ async {{
+ return func(x)
+ }}
//$COMMENTAREA$"""
+/// Code create using FSharpCheckFileResults.GenerateSignature()
+ let generateFsi number =
+ $"""
+module Benchmark{number}
+
+val myFunc{number}: unit -> int
+
+type MyType{number} = | MyType{number} of string
+
+type MyOtherType{number} = | MyOtherType{number} of int
+
+type MyFunctionType{number} = MyType{number} -> MyOtherType{number}
+
+val processFunc{number}: x: MyType{number} -> func: MyFunctionType{number} -> Async"""
+
[]
-[]
+[]
[]
[]
type FileCascadeBenchmarks() =
- let mutable project : FSharpProjectOptions option = None
-
- let getProject() = project.Value
-
- let checker = FSharpChecker.Create(projectCacheSize = 5, enableParallelCheckingWithSignatureFiles = true, parallelReferenceResolution = true)
- let filesToCreate = 64
-
- let mutable finalFileContents = SourceText.ofString ""
+ let mutable project : FSharpProjectOptions option = None
+ let filesToCreate = 128
+ member val FinalFileContents = SourceText.ofString "" with get,set
+
+ []
+ member val PartialCheck = true with get,set
+ []
+ member val ParaChecking = true with get,set
+ []
+ member val GenerateFSI = true with get,set
+
+ member val Checker = Unchecked.defaultof with get, set
+ member this.GetProject() = project.Value
[]
- member _.Setup() =
+ member this.Setup() =
+ printfn $"Running Setup(). Partial = {this.PartialCheck}, Para = {this.ParaChecking}, FSIGen = {this.GenerateFSI}"
+ this.Checker <- FSharpChecker.Create(
+ projectCacheSize = 5,
+ enablePartialTypeChecking = this.PartialCheck,
+ enableParallelCheckingWithSignatureFiles = this.ParaChecking)
+
+
let projectFolder = Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(),"CascadeBenchmarkProject"))
if(projectFolder.Exists) then
do projectFolder.Delete(recursive=true)
do Directory.CreateDirectory(projectFolder.FullName) |> ignore
let inProjectFolder fileName = Path.Combine(projectFolder.FullName,fileName)
-
+
+ if this.GenerateFSI then
+ File.WriteAllText(inProjectFolder "Benchmark0.fsi",baselineFsi)
File.WriteAllText(inProjectFolder "Benchmark0.fs",baselineModule)
- for i = 1 to filesToCreate do
+
+ for i = 1 to filesToCreate do
+ if this.GenerateFSI then
+ File.WriteAllText(inProjectFolder $"Benchmark%i{i}.fsi", generateFsi i)
File.WriteAllText(inProjectFolder $"Benchmark%i{i}.fs", generateSourceCode i)
let dllFileName = inProjectFolder "CascadingBenchMark.dll"
- let allSourceCodeFiles = [| for i in 0 .. filesToCreate -> inProjectFolder $"Benchmark%i{i}.fs"|]
+ let allSourceCodeFiles =
+ [| for i in 0 .. filesToCreate do
+ if this.GenerateFSI then
+ yield (inProjectFolder $"Benchmark%i{i}.fsi")
+ yield (inProjectFolder $"Benchmark%i{i}.fs")
+ |]
let x = createProject allSourceCodeFiles dllFileName
project <- Some x
- finalFileContents <- generateSourceCode filesToCreate |> SourceText.ofString
+ this.FinalFileContents <- generateSourceCode filesToCreate |> SourceText.ofString
+
+ ()
member x.ChangeFile(fileIndex:int, action) =
- let project = getProject()
- let fileName = project.SourceFiles.[fileIndex]
+ let project = x.GetProject()
+ let fileIndexAdapted = if x.GenerateFSI then fileIndex * 2 else fileIndex
+ let fileName = project.SourceFiles.[fileIndexAdapted]
let fullOriginalSource = File.ReadAllText(fileName)
try
File.WriteAllText(fileName, fullOriginalSource.Replace("$COMMENTAREA$","$FILEMODIFIED"))
@@ -90,29 +152,33 @@ type FileCascadeBenchmarks() =
finally
File.WriteAllText(fileName,fullOriginalSource)
- member x.CheckFinalFile () =
- let project = getProject()
+ member x.ParseAndCheckLastFileInTheProject () =
+ let project = x.GetProject()
let lastFile = project.SourceFiles |> Array.last
- checker.ParseAndCheckFileInProject(lastFile,999,finalFileContents,project)
+ let pr,cr = x.Checker.ParseAndCheckFileInProject(lastFile,999,x.FinalFileContents,project) |> Async.RunSynchronously
+ printfn $"ParseError = {pr.ParseHadErrors}; Check = {match cr with | FSharpCheckFileAnswer.Succeeded _ -> '+' | _ -> '-' }"
+ for e in pr.Diagnostics do
+ printfn "Error:= %s" (e.ToString())
[]
- member x.ParseProjectAsIs() =
- x.CheckFinalFile()
+ member x.ParseAndCheckLastFileProjectAsIs() =
+ x.ParseAndCheckLastFileInTheProject()
[]
member x.ParseProjectWithFullCacheClear() =
- checker.ClearCache([getProject()])
- checker.InvalidateConfiguration(getProject())
- x.CheckFinalFile()
+ x.Checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients()
+ x.Checker.ClearCache([x.GetProject()])
+ x.Checker.InvalidateConfiguration(x.GetProject())
+ x.ParseAndCheckLastFileInTheProject()
[]
member x.ParseProjectWithChangingFirstFile() =
- x.ChangeFile(fileIndex=0, action= fun () -> x.CheckFinalFile())
+ x.ChangeFile(fileIndex=0, action= fun () -> x.ParseAndCheckLastFileInTheProject())
[]
- member x.ParseProjectWithChanging25thPercentileFile() =
- x.ChangeFile(fileIndex=filesToCreate/4, action= fun () -> x.CheckFinalFile())
+ member x.ParseProjectWithChangingMiddleFile() =
+ x.ChangeFile(fileIndex=filesToCreate/2, action= fun () -> x.ParseAndCheckLastFileInTheProject())
[]
- member x.ParseProjectWithChangingMiddleFile() =
- x.ChangeFile(fileIndex=filesToCreate/2, action= fun () -> x.CheckFinalFile())
\ No newline at end of file
+ member x.ParseProjectWithChangingPenultimateFile() =
+ x.ChangeFile(fileIndex=(filesToCreate-2), action= fun () -> x.ParseAndCheckLastFileInTheProject())
\ No newline at end of file
diff --git a/tests/benchmarks/Fsharp.ProfilingStartpointProject/Fsharp.ProfilingStartpointProject.fsproj b/tests/benchmarks/Fsharp.ProfilingStartpointProject/Fsharp.ProfilingStartpointProject.fsproj
new file mode 100644
index 00000000000..7ed3d17abc9
--- /dev/null
+++ b/tests/benchmarks/Fsharp.ProfilingStartpointProject/Fsharp.ProfilingStartpointProject.fsproj
@@ -0,0 +1,16 @@
+
+
+
+ Exe
+ net7.0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/benchmarks/Fsharp.ProfilingStartpointProject/Program.fs b/tests/benchmarks/Fsharp.ProfilingStartpointProject/Program.fs
new file mode 100644
index 00000000000..5d851e60865
--- /dev/null
+++ b/tests/benchmarks/Fsharp.ProfilingStartpointProject/Program.fs
@@ -0,0 +1,47 @@
+open FSharp.Compiler.Benchmarks
+
+open System
+open System.IO
+open System.Text
+open FSharp.Compiler.CodeAnalysis
+open FSharp.Compiler.Diagnostics
+open FSharp.Compiler.EditorServices
+open FSharp.Compiler.Text
+open FSharp.Compiler.AbstractIL.IL
+open FSharp.Compiler.AbstractIL.ILBinaryReader
+open BenchmarkDotNet.Attributes
+open FSharp.Compiler.Benchmarks
+open Microsoft.CodeAnalysis.Text
+open BenchmarkDotNet.Order
+open BenchmarkDotNet.Mathematics
+
+let bench = new FileCascadeBenchmarks()
+bench.GenerateFSI <- true
+do bench.Setup()
+
+(*
+This project was created as an easy entry point for low-level profiling of FCS operations.
+The only purpose is the easy of setup (simply set as startup project and launch) so that a profiler can be connected.
+There is definitely no harm in deleting it if it starts bothering anyone.
+*)
+
+
+[]
+let main args =
+
+ match args |> Array.toList with
+ | ["no-change"] ->
+ for i=1 to 256 do
+ printfn "***************************"
+ printfn "ITERATION %i" i
+ printfn "***************************"
+ bench.ParseAndCheckLastFileProjectAsIs() |> ignore
+ | ["mid-change"] ->
+ for i=1 to 16 do
+ printfn "***************************"
+ printfn "ITERATION %i" i
+ printfn "***************************"
+ bench.ParseProjectWithChangingMiddleFile() |> ignore
+ | _ -> failwith "Invalid args. Use cache-clear or mid-change"
+ |> ignore
+ 0