【C#】C# Dev Kitが生成する.lscacheファイルについて
VSCodeで久々に.NETプロジェクトを作成したところ、見慣れない*.lscacheファイルがプロジェクトフォルダ内に作成されていました。気になって調べてみたので、分かったことを記事にまとめておきます。
参考となるissueはこちら。この記事の内容は概ねこのissueのF&Qに基づいています。
.lscacheとは?
.lscacheはC# Dev Kitなどのツールが.csprojと同じフォルダに作成する軽量なキャッシュです。その実態はTOML-likeな構造のテキストファイルで、実際のファイルの中身はこんな感じ。
.lscacheの中身 (長いので折りたたみ)
version=1
# This file caches language service data to improve the performance of C# Dev Kit.
# It is not intended for manual editing. It can safely be deleted and will be
# regenerated automatically. For more information, see https://aka.ms/lscache
#
# To control where cache files are stored, use the following VS Code setting:
# "dotnet.projectsystem.cacheInProjectFolder": true
[project]
language=C#
primary
lastDtbSucceeded
[properties]
AssemblyName=Example
CommandLineArgsForDesignTimeEvaluation=-langversion:14.0 -define:TRACE
CompilerGeneratedFilesOutputPath=
MaxSupportedLangVersion=14.0
ProjectAssetsFile=<PATH>obj/project.assets.json
RootNamespace=Example
RunAnalyzers=
RunAnalyzersDuringLiveAnalysis=
SolutionPath=<PATH>../../Example.slnx
TargetFrameworkIdentifier=.NETCoreApp
TargetPath=<PATH>bin/Debug/net10.0/Example.dll
TargetRefPath=<PATH>obj/Debug/net10.0/ref/Example.dll
TemporaryDependencyNodeTargetIdentifier=net10.0
[commandLineArguments]
/noconfig
/unsafe-
/checked-
/nowarn:1701,1702,1701,1702
/fullpaths
/nostdlib+
/errorreport:prompt
/warn:10
/define:TRACE;DEBUG;NET;NET10_0;NETCOREAPP;NET5_0_OR_GREATER;NET6_0_OR_GREATER;NET7_0_OR_GREATER;NET8_0_OR_GREATER;NET9_0_OR_GREATER;NET10_0_OR_GREATER;NETCOREAPP1_0_OR_GREATER;NETCOREAPP1_1_OR_GREATER;NETCOREAPP2_0_OR_GREATER;NETCOREAPP2_1_OR_GREATER;NETCOREAPP2_2_OR_GREATER;NETCOREAPP3_0_OR_GREATER;NETCOREAPP3_1_OR_GREATER
/highentropyva+
/nullable:enable
/features:"InterceptorsNamespaces=;Microsoft.Extensions.Validation.Generated"
/debug+
/debug:portable
/filealign:512
/optimize-
/out:obj/Debug/net10.0/Example.dll
/refout:obj/Debug/net10.0/refint/Example.dll
/target:library
/warnaserror-
/utf8output
/deterministic+
/langversion:14.0
/warnaserror+:NU1605,SYSLIB0011
[sourceFiles]
obj/Debug/net10.0/
.NETCoreApp,Version=v10.0.AssemblyAttributes.cs
Example.AssemblyInfo.cs
Example.GlobalUsings.g.cs
[metadataReferences]
../../../../../../../../usr/local/share/dotnet/packs/Microsoft.NETCore.App.Ref/10.0.2/ref/net10.0/
Microsoft.CSharp.dll
Microsoft.VisualBasic.Core.dll
Microsoft.VisualBasic.dll
Microsoft.Win32.Primitives.dll
Microsoft.Win32.Registry.dll
mscorlib.dll
netstandard.dll
System.AppContext.dll
System.Buffers.dll
System.Collections.Concurrent.dll
System.Collections.dll
System.Collections.Immutable.dll
System.Collections.NonGeneric.dll
System.Collections.Specialized.dll
System.ComponentModel.Annotations.dll
System.ComponentModel.DataAnnotations.dll
System.ComponentModel.dll
System.ComponentModel.EventBasedAsync.dll
System.ComponentModel.Primitives.dll
System.ComponentModel.TypeConverter.dll
System.Configuration.dll
System.Console.dll
System.Core.dll
System.Data.Common.dll
System.Data.DataSetExtensions.dll
System.Data.dll
System.Diagnostics.Contracts.dll
System.Diagnostics.Debug.dll
System.Diagnostics.DiagnosticSource.dll
System.Diagnostics.FileVersionInfo.dll
System.Diagnostics.Process.dll
System.Diagnostics.StackTrace.dll
System.Diagnostics.TextWriterTraceListener.dll
System.Diagnostics.Tools.dll
System.Diagnostics.TraceSource.dll
System.Diagnostics.Tracing.dll
System.dll
System.Drawing.dll
System.Drawing.Primitives.dll
System.Dynamic.Runtime.dll
System.Formats.Asn1.dll
System.Formats.Tar.dll
System.Globalization.Calendars.dll
System.Globalization.dll
System.Globalization.Extensions.dll
System.IO.Compression.Brotli.dll
System.IO.Compression.dll
System.IO.Compression.FileSystem.dll
System.IO.Compression.ZipFile.dll
System.IO.dll
System.IO.FileSystem.AccessControl.dll
System.IO.FileSystem.dll
System.IO.FileSystem.DriveInfo.dll
System.IO.FileSystem.Primitives.dll
System.IO.FileSystem.Watcher.dll
System.IO.IsolatedStorage.dll
System.IO.MemoryMappedFiles.dll
System.IO.Pipelines.dll
System.IO.Pipes.AccessControl.dll
System.IO.Pipes.dll
System.IO.UnmanagedMemoryStream.dll
System.Linq.AsyncEnumerable.dll
System.Linq.dll
System.Linq.Expressions.dll
System.Linq.Parallel.dll
System.Linq.Queryable.dll
System.Memory.dll
System.Net.dll
System.Net.Http.dll
System.Net.Http.Json.dll
System.Net.HttpListener.dll
System.Net.Mail.dll
System.Net.NameResolution.dll
System.Net.NetworkInformation.dll
System.Net.Ping.dll
System.Net.Primitives.dll
System.Net.Quic.dll
System.Net.Requests.dll
System.Net.Security.dll
System.Net.ServerSentEvents.dll
System.Net.ServicePoint.dll
System.Net.Sockets.dll
System.Net.WebClient.dll
System.Net.WebHeaderCollection.dll
System.Net.WebProxy.dll
System.Net.WebSockets.Client.dll
System.Net.WebSockets.dll
System.Numerics.dll
System.Numerics.Vectors.dll
System.ObjectModel.dll
System.Reflection.DispatchProxy.dll
System.Reflection.dll
System.Reflection.Emit.dll
System.Reflection.Emit.ILGeneration.dll
System.Reflection.Emit.Lightweight.dll
System.Reflection.Extensions.dll
System.Reflection.Metadata.dll
System.Reflection.Primitives.dll
System.Reflection.TypeExtensions.dll
System.Resources.Reader.dll
System.Resources.ResourceManager.dll
System.Resources.Writer.dll
System.Runtime.CompilerServices.Unsafe.dll
System.Runtime.CompilerServices.VisualC.dll
System.Runtime.dll
System.Runtime.Extensions.dll
System.Runtime.Handles.dll
System.Runtime.InteropServices.dll
System.Runtime.InteropServices.JavaScript.dll
System.Runtime.InteropServices.RuntimeInformation.dll
System.Runtime.Intrinsics.dll
System.Runtime.Loader.dll
System.Runtime.Numerics.dll
System.Runtime.Serialization.dll
System.Runtime.Serialization.Formatters.dll
System.Runtime.Serialization.Json.dll
System.Runtime.Serialization.Primitives.dll
System.Runtime.Serialization.Xml.dll
System.Security.AccessControl.dll
System.Security.Claims.dll
System.Security.Cryptography.Algorithms.dll
System.Security.Cryptography.Cng.dll
System.Security.Cryptography.Csp.dll
System.Security.Cryptography.dll
System.Security.Cryptography.Encoding.dll
System.Security.Cryptography.OpenSsl.dll
System.Security.Cryptography.Primitives.dll
System.Security.Cryptography.X509Certificates.dll
System.Security.dll
System.Security.Principal.dll
System.Security.Principal.Windows.dll
System.Security.SecureString.dll
System.ServiceModel.Web.dll
System.ServiceProcess.dll
System.Text.Encoding.CodePages.dll
System.Text.Encoding.dll
System.Text.Encoding.Extensions.dll
System.Text.Encodings.Web.dll
System.Text.Json.dll
System.Text.RegularExpressions.dll
System.Threading.AccessControl.dll
System.Threading.Channels.dll
System.Threading.dll
System.Threading.Overlapped.dll
System.Threading.Tasks.Dataflow.dll
System.Threading.Tasks.dll
System.Threading.Tasks.Extensions.dll
System.Threading.Tasks.Parallel.dll
System.Threading.Thread.dll
System.Threading.ThreadPool.dll
System.Threading.Timer.dll
System.Transactions.dll
System.Transactions.Local.dll
System.ValueTuple.dll
System.Web.dll
System.Web.HttpUtility.dll
System.Windows.dll
System.Xml.dll
System.Xml.Linq.dll
System.Xml.ReaderWriter.dll
System.Xml.Serialization.dll
System.Xml.XDocument.dll
System.Xml.XmlDocument.dll
System.Xml.XmlSerializer.dll
System.Xml.XPath.dll
System.Xml.XPath.XDocument.dll
WindowsBase.dll
[analyzerReferences]
../../../../../../../../usr/local/share/dotnet/packs/Microsoft.NETCore.App.Ref/10.0.2/analyzers/dotnet/cs/
Microsoft.Interop.ComInterfaceGenerator.dll
Microsoft.Interop.JavaScript.JSImportGenerator.dll
Microsoft.Interop.LibraryImportGenerator.dll
Microsoft.Interop.SourceGeneration.dll
System.Text.Json.SourceGeneration.dll
System.Text.RegularExpressions.Generator.dll
../../../../../../../../usr/local/share/dotnet/sdk/10.0.102/Sdks/Microsoft.NET.Sdk/analyzers/
Microsoft.CodeAnalysis.CSharp.NetAnalyzers.dll
Microsoft.CodeAnalysis.NetAnalyzers.dll
[analyzerConfigFiles]
../../../../../../../../usr/local/share/dotnet/sdk/10.0.102/Sdks/Microsoft.NET.Sdk/analyzers/build/config/analysislevel_10_default.globalconfig
obj/Debug/net10.0/Example.GeneratedMSBuildEditorConfig.editorconfig
見てのとおり、プロジェクトの参照や構造など、様々な情報が含まれています。F&Qでも触れられていますが、環境変数などのプロジェクトの機密情報などは含まれません。
この.lscacheはC# Dev Kitなどの起動を高速化することを目的に作成され、C# Dev Kitの起動時間をなんと70%も削減することが可能になるそうです。現状は分かりませんが、.lscacheを用いることでメモリ使用量に関しても大幅に削減される見込みとなっています。
gitの追跡対象から除外すべき?
キャッシュファイルであれば.gitignoreに加えてgitの追跡対象から除外したいところですが、開発者サイドとしてはバージョン管理に含めて欲しいようです。というのもこのファイルは異なるマシンの間で共有可能であり、またブランチ切り替え時の処理を削減するためにも残しておいてほしい...という気持ちみたいですね。
とはいえかなり邪魔だし、更新されるたびにコミットするのも面倒...というのはそうなので、気になるようであれば .gitignoreしても問題ない ようです。また、VSCodeのsettings.jsonからdotnet.projectsystem.cacheInProjectFolderをfalseにすることで、.lscacheを一時フォルダに保存させるように変更することが可能です。
{
"dotnet.projectsystem.cacheInProjectFolder": false
}
やはりデフォルトはignoreでいいんじゃないか、という意見は強く、デフォルトのgitignoreに*.lscacheを追加するPRも立てられています。
なんでプロジェクトフォルダに直置きなの?別のところでも良くない?
これはissueでも議論に上がっている不満で、実際かなり気になる点でもあります。C#のプロジェクトはただでさえ.csproj、bin/、obj/が散らばっていて気になるのに、これ以上プロジェクト内に置くファイルを増やさないでくれ...というのが個人的な気持ちです。
これの理由としては、キャッシュをリポジトリ内に配置してコミットさせたい、という面が大きいようです。obj/ファイル以下だとデフォルトでignoreされるほか、ターゲットによって構成が変わる可能性があるため、キャッシュの場所を特定するのにコストが生じてしまいます。.csprojと同じ階層に置くことで探索のコストを省き、確実にキャッシュを利用できるようにするという狙いみたいですね。でもやっぱり邪魔だと思う
まとめ
一応.lscacheの仕様はプレビューで、正式に採用されるまでに変更される可能性はあります。正直かなり邪魔なので、場所に関してはもうちょっと別のところに変わるんじゃないかなーと思ってたり。言語に関係ないツール周りの細かい話題ですが、今後の動きに注目したいところです。
Discussion