Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb279f8d

Browse files
cartermpTIHan
authored andcommitted
Use hashes for language service cache keys (dotnet#6058)
* Use hashes for language service cache keys* Fix dumb thing I forgot* I guess this is required ayyy lmao* Override HashCode instead and do a few less computations* Remove ToString in obj expression
1 parent3176821 commitb279f8d

File tree

4 files changed

+84
-58
lines changed

4 files changed

+84
-58
lines changed

‎src/fsharp/service/service.fs‎

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,17 +2188,17 @@ module Helpers =
21882188
&& FSharpProjectOptions.UseSameProject(o1,o2)
21892189

21902190
/// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. parsing
2191-
letAreSameForParsing((fileName1:string,source1:ISourceText,options1),(fileName2,source2,options2))=
2192-
fileName1= fileName2&& options1= options2&&source1.ContentEquals(source2)
2191+
letAreSameForParsing((fileName1:string,source1Hash:int,options1),(fileName2,source2Hash,options2))=
2192+
fileName1= fileName2&& options1= options2&&source1Hash= source2Hash
21932193

21942194
letAreSimilarForParsing((fileName1,_,_),(fileName2,_,_))=
21952195
fileName1= fileName2
21962196

21972197
/// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. checking
2198-
letAreSameForChecking3((fileName1:string,source1:ISourceText,options1:FSharpProjectOptions),(fileName2,source2,options2))=
2198+
letAreSameForChecking3((fileName1:string,source1Hash:int,options1:FSharpProjectOptions),(fileName2,source2Hash,options2))=
21992199
(fileName1= fileName2)
22002200
&& FSharpProjectOptions.AreSameForChecking(options1,options2)
2201-
&&source1.ContentEquals(source2)
2201+
&&source1Hash= source2Hash
22022202

22032203
/// Determine whether two (fileName,sourceText,options) keys should be identical w.r.t. resource usage
22042204
letAreSubsumable3((fileName1:string,_,o1:FSharpProjectOptions),(fileName2:string,_,o2:FSharpProjectOptions))=
@@ -2314,7 +2314,7 @@ module CompileHelpers =
23142314
System.Console.SetError error
23152315
| None->()
23162316

2317-
2317+
typeSourceTextHash= int
23182318
typeFileName= string
23192319
typeFilePath= string
23202320
typeProjectPath= string
@@ -2460,7 +2460,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
24602460

24612461
// Also keyed on source. This can only be out of date if the antecedent is out of date
24622462
letcheckFileInProjectCache=
2463-
MruCache<ParseCacheLockToken,FileName*ISourceText* FSharpProjectOptions, FSharpParseFileResults* FSharpCheckFileResults* FileVersion* DateTime>
2463+
MruCache<ParseCacheLockToken,FileName*SourceTextHash* FSharpProjectOptions, FSharpParseFileResults* FSharpCheckFileResults* FileVersion* DateTime>
24642464
(keepStrongly=checkFileInProjectCacheSize,
24652465
areSame=AreSameForChecking3,
24662466
areSimilar=AreSubsumable3)
@@ -2511,13 +2511,14 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
25112511

25122512
memberbc.ParseFile(filename:string,sourceText:ISourceText,options:FSharpParsingOptions,userOpName:string)=
25132513
async{
2514-
match parseCacheLock.AcquireLock(fun ltok-> parseFileCache.TryGet(ltok,(filename, sourceText, options)))with
2514+
lethash= sourceText.GetHashCode()
2515+
match parseCacheLock.AcquireLock(fun ltok-> parseFileCache.TryGet(ltok,(filename, hash, options)))with
25152516
| Some res->return res
25162517
| None->
25172518
foregroundParseCount<- foregroundParseCount+1
25182519
letparseErrors,parseTreeOpt,anyErrors= Parser.parseFile(sourceText, filename, options, userOpName)
25192520
letres= FSharpParseFileResults(parseErrors, parseTreeOpt, anyErrors, options.SourceFiles)
2520-
parseCacheLock.AcquireLock(fun ltok-> parseFileCache.Set(ltok,(filename,sourceText, options), res))
2521+
parseCacheLock.AcquireLock(fun ltok-> parseFileCache.Set(ltok,(filename,hash, options), res))
25212522
return res
25222523
}
25232524

@@ -2536,9 +2537,9 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
25362537
}
25372538
)
25382539

2539-
memberbc.GetCachedCheckFileResult(builder:IncrementalBuilder,filename,sourceText,options)=
2540+
memberbc.GetCachedCheckFileResult(builder:IncrementalBuilder,filename,sourceText:ISourceText,options)=
25402541
// Check the cache. We can only use cached results when there is no work to do to bring the background builder up-to-date
2541-
letcachedResults= parseCacheLock.AcquireLock(fun ltok-> checkFileInProjectCache.TryGet(ltok,(filename,sourceText,options)))
2542+
letcachedResults= parseCacheLock.AcquireLock(fun ltok-> checkFileInProjectCache.TryGet(ltok,(filename,sourceText.GetHashCode(),options)))
25422543

25432544
match cachedResultswith
25442545
// | Some (parseResults, checkResults, _, _) when builder.AreCheckResultsBeforeFileInProjectReady(filename) ->
@@ -2598,7 +2599,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
25982599
tcPrior.TcState, loadClosure, tcPrior.TcErrors, reactorOps,(fun()-> builder.IsAlive), textSnapshotInfo, userOpName)
25992600
letparsingOptions= FSharpParsingOptions.FromTcConfig(tcPrior.TcConfig, Array.ofList builder.SourceFiles, options.UseScriptResolutionRules)
26002601
letcheckAnswer= MakeCheckFileAnswer(fileName, tcFileResult, options, builder, Array.ofList tcPrior.TcDependencyFiles, creationErrors, parseResults.Errors, tcErrors)
2601-
bc.RecordTypeCheckFileInProjectResults(fileName, options, parsingOptions, parseResults, fileVersion, tcPrior.TimeStamp, Some checkAnswer, sourceText)
2602+
bc.RecordTypeCheckFileInProjectResults(fileName, options, parsingOptions, parseResults, fileVersion, tcPrior.TimeStamp, Some checkAnswer, sourceText.GetHashCode())
26022603
return checkAnswer
26032604
finally
26042605
letdummy= ref()
@@ -2614,7 +2615,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
26142615
}
26152616

26162617
/// Type-check the result obtained by parsing, but only if the antecedent type checking context is available.
2617-
memberbc.CheckFileInProjectAllowingStaleCachedResults(parseResults:FSharpParseFileResults,filename,fileVersion,sourceText,options,textSnapshotInfo:obj option,userOpName)=
2618+
memberbc.CheckFileInProjectAllowingStaleCachedResults(parseResults:FSharpParseFileResults,filename,fileVersion,sourceText:ISourceText,options,textSnapshotInfo:obj option,userOpName)=
26182619
letexecWithReactorAsync action= reactor.EnqueueAndAwaitOpAsync(userOpName,"CheckFileInProjectAllowingStaleCachedResults", filename, action)
26192620
async{
26202621
try
@@ -2657,7 +2658,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
26572658
}
26582659

26592660
/// Type-check the result obtained by parsing. Force the evaluation of the antecedent type checking context if needed.
2660-
memberbc.CheckFileInProject(parseResults:FSharpParseFileResults,filename,fileVersion,sourceText,options,textSnapshotInfo,userOpName)=
2661+
memberbc.CheckFileInProject(parseResults:FSharpParseFileResults,filename,fileVersion,sourceText:ISourceText,options,textSnapshotInfo,userOpName)=
26612662
letexecWithReactorAsync action= reactor.EnqueueAndAwaitOpAsync(userOpName,"CheckFileInProject", filename, action)
26622663
async{
26632664
try
@@ -2685,7 +2686,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
26852686
}
26862687

26872688
/// Parses and checks the source file and returns untyped AST and check results.
2688-
memberbc.ParseAndCheckFileInProject(filename:string,fileVersion,sourceText,options:FSharpProjectOptions,textSnapshotInfo,userOpName)=
2689+
memberbc.ParseAndCheckFileInProject(filename:string,fileVersion,sourceText:ISourceText,options:FSharpProjectOptions,textSnapshotInfo,userOpName)=
26892690
letexecWithReactorAsync action= reactor.EnqueueAndAwaitOpAsync(userOpName,"ParseAndCheckFileInProject", filename, action)
26902691
async{
26912692
try
@@ -2772,7 +2773,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC
27722773
match sourceTextwith
27732774
| Some sourceText->
27742775
parseCacheLock.AcquireLock(fun ltok->
2775-
match checkFileInProjectCache.TryGet(ltok,(filename,sourceText,options))with
2776+
match checkFileInProjectCache.TryGet(ltok,(filename,sourceText.GetHashCode(),options))with
27762777
| Some(a,b,c,_)-> Some(a,b,c)
27772778
| None-> parseCacheLock.AcquireLock(fun ltok-> checkFileInProjectCachePossiblyStale.TryGet(ltok,(filename,options))))
27782779
| None-> parseCacheLock.AcquireLock(fun ltok-> checkFileInProjectCachePossiblyStale.TryGet(ltok,(filename,options)))
@@ -3008,14 +3009,15 @@ type FSharpChecker(legacyReferenceResolver, projectCacheSize, keepAssemblyConten
30083009

30093010
memberic.ReferenceResolver= legacyReferenceResolver
30103011

3011-
memberic.MatchBraces(filename,sourceText,options:FSharpParsingOptions,?userOpName:string)=
3012+
memberic.MatchBraces(filename,sourceText:ISourceText,options:FSharpParsingOptions,?userOpName:string)=
30123013
letuserOpName= defaultArg userOpName"Unknown"
3014+
lethash= sourceText.GetHashCode()
30133015
async{
3014-
match braceMatchCache.TryGet(AssumeAnyCallerThreadWithoutEvidence(),(filename,sourceText, options))with
3016+
match braceMatchCache.TryGet(AssumeAnyCallerThreadWithoutEvidence(),(filename,hash, options))with
30153017
| Some res->return res
30163018
| None->
30173019
letres= Parser.matchBraces(sourceText, filename, options, userOpName)
3018-
braceMatchCache.Set(AssumeAnyCallerThreadWithoutEvidence(),(filename,sourceText, options), res)
3020+
braceMatchCache.Set(AssumeAnyCallerThreadWithoutEvidence(),(filename,hash, options), res)
30193021
return res
30203022
}
30213023

‎src/utils/prim-lexing.fs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ type ISourceText =
2525

2626
abstractContentEquals : sourceText:ISourceText->bool
2727

28-
abstractCopyTo : sourceIndex:int* destination:char[]* destinationIndex:int* count:int->unit
28+
abstractCopyTo : sourceIndex:int* destination:char[]* destinationIndex:int* count:int->unit
2929

3030
[<Sealed>]
3131
typeStringText(str: string)=
@@ -50,6 +50,9 @@ type StringText(str: string) =
5050
lazy getLines str
5151

5252
member__.String= str
53+
54+
override__.GetHashCode()= str.GetHashCode()
55+
override__.Equals(obj:obj)= str.Equals(obj)
5356

5457
interface ISourceTextwith
5558

‎src/utils/prim-lexing.fsi‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type ISourceText =
2323

2424
abstractContentEquals : sourceText:ISourceText->bool
2525

26-
abstractCopyTo : sourceIndex:int* destination:char[]* destinationIndex:int* count:int->unit
26+
abstractCopyTo : sourceIndex:int* destination:char[]* destinationIndex:int* count:int->unit
2727

2828
moduleSourceText=
2929

‎vsintegration/src/FSharp.Editor/Common/Extensions.fs‎

Lines changed: 59 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -46,61 +46,82 @@ module private SourceText =
4646

4747
openSystem.Runtime.CompilerServices
4848

49+
/// Ported from Roslyn.Utilities
50+
[<RequireQualifiedAccess>]
51+
moduleHash=
52+
/// (From Roslyn) This is how VB Anonymous Types combine hash values for fields.
53+
letcombine(newKey:int)(currentKey:int)=(currentKey*(int0xA5555529))+ newKey
54+
55+
letcombineValues(values:seq<'T>)=
56+
(0, values)||> Seq.fold(fun hash value-> combine(value.GetHashCode()) hash)
57+
4958
letweakTable= ConditionalWeakTable<SourceText, ISourceText>()
5059

5160
letcreate(sourceText:SourceText)=
5261
letsourceText=
53-
{new ISourceTextwith
62+
{
63+
new Object()with
64+
override__.GetHashCode()=
65+
letchecksum= sourceText.GetChecksum()
66+
letcontentsHash=ifnot checksum.IsDefaultthen Hash.combineValues checksumelse0
67+
letencodingHash=ifnot(isNull sourceText.Encoding)then sourceText.Encoding.GetHashCode()else0
68+
69+
sourceText.ChecksumAlgorithm.GetHashCode()
70+
|> Hash.combine encodingHash
71+
|> Hash.combine contentsHash
72+
|> Hash.combine sourceText.Length
73+
74+
interface ISourceTextwith
5475

55-
member__.Itemwith get index= sourceText.[index]
76+
member__.Itemwith get index= sourceText.[index]
5677

57-
member__.GetLineString(lineIndex)=
58-
sourceText.Lines.[lineIndex].ToString()
78+
member__.GetLineString(lineIndex)=
79+
sourceText.Lines.[lineIndex].ToString()
5980

60-
member__.GetLineCount()=
61-
sourceText.Lines.Count
81+
member__.GetLineCount()=
82+
sourceText.Lines.Count
6283

63-
member__.GetLastCharacterPosition()=
64-
if sourceText.Lines.Count>0then
65-
(sourceText.Lines.Count, sourceText.Lines.[sourceText.Lines.Count-1].Span.Length)
66-
else
67-
(0,0)
84+
member__.GetLastCharacterPosition()=
85+
if sourceText.Lines.Count>0then
86+
(sourceText.Lines.Count, sourceText.Lines.[sourceText.Lines.Count-1].Span.Length)
87+
else
88+
(0,0)
6889

69-
member__.GetSubTextString(start,length)=
70-
sourceText.GetSubText(TextSpan(start, length)).ToString()
90+
member__.GetSubTextString(start,length)=
91+
sourceText.GetSubText(TextSpan(start, length)).ToString()
7192

72-
member__.SubTextEquals(target,startIndex)=
73-
if startIndex<0|| startIndex>= sourceText.Lengththen
74-
invalidArg"startIndex""Out of range."
93+
member__.SubTextEquals(target,startIndex)=
94+
if startIndex<0|| startIndex>= sourceText.Lengththen
95+
invalidArg"startIndex""Out of range."
7596

76-
if String.IsNullOrEmpty(target)then
77-
invalidArg"target""Is null or empty."
97+
if String.IsNullOrEmpty(target)then
98+
invalidArg"target""Is null or empty."
7899

79-
letlastIndex= startIndex+ target.Length
80-
if lastIndex<= startIndex|| lastIndex>= sourceText.Lengththen
81-
invalidArg"target""Too big."
100+
letlastIndex= startIndex+ target.Length
101+
if lastIndex<= startIndex|| lastIndex>= sourceText.Lengththen
102+
invalidArg"target""Too big."
82103

83-
let mutablefinished=false
84-
let mutabledidEqual=true
85-
let mutablei=0
86-
whilenot finished&& i< target.Lengthdo
87-
if target.[i]<> sourceText.[startIndex+ i]then
88-
didEqual<-false
89-
finished<-true// bail out early
90-
else
91-
i<- i+1
104+
let mutablefinished=false
105+
let mutabledidEqual=true
106+
let mutablei=0
107+
whilenot finished&& i< target.Lengthdo
108+
if target.[i]<> sourceText.[startIndex+ i]then
109+
didEqual<-false
110+
finished<-true// bail out early
111+
else
112+
i<- i+1
92113

93-
didEqual
114+
didEqual
94115

95-
member__.ContentEquals(sourceText)=
96-
match sourceTextwith
97-
|:? SourceText as sourceText-> sourceText.ContentEquals(sourceText)
98-
|_->false
116+
member__.ContentEquals(sourceText)=
117+
match sourceTextwith
118+
|:? SourceText as sourceText-> sourceText.ContentEquals(sourceText)
119+
|_->false
99120

100-
member__.Length= sourceText.Length
121+
member__.Length= sourceText.Length
101122

102-
member__.CopyTo(sourceIndex,destination,destinationIndex,count)=
103-
sourceText.CopyTo(sourceIndex, destination, destinationIndex, count)
123+
member__.CopyTo(sourceIndex,destination,destinationIndex,count)=
124+
sourceText.CopyTo(sourceIndex, destination, destinationIndex, count)
104125
}
105126

106127
sourceText

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp