20170527 inside .net core on linux
Post on 28-Jan-2018
105 Views
Preview:
TRANSCRIPT
.NET Core がLinuxでどのように動いているか、またわれわれはどのようにデバッグするのかたなか (@TANAKA_733)
Y8 2017 SPRING IN SHIBUYA
1
@tanaka_733Red Hat K. K.◦ .NET Core on RHEL, Red Hat on Azure, OpenShift
◦ SQL Server on RHELも調べたり
Microsoft MVP for VSDT*◦ .NET, C#, Azure系の勉強会によく出現します
◦ Build Insiderでよく執筆しています (C#文法, C# 7.0や .NET Core)
◦ (需要があれば)ほかの勉強会にもお邪魔したいです
Contact◦ contact@tanaka733.net or twitterで
2
* VSDT: Visual Studio and Development Technologies
AGENDA.NET Core とは◦ (この後出てくる) coreclrとか corefxが何かを知ってもらう
CoreFX on Linux◦ネットワーク通信とかファイルIOとかどう実装してるのか
Debugging .NET Core on Linux◦ Visual Studioが使えないLinux上でどうやってデバッグするのか
3
…は話しませんGetting Started with .NET Core◦ .NET Coreでのアプリ開発について
◦ 近々Build Insiderで連載が始まるので読んでね!ダイレクトマーケティング
Xamarin◦ Xamarinの出自のmonoは関連が深いけれど、.NET Coreではないです
.NET Core 2.0/.NET Standard 2.0◦ 2.0はpreview、現在の正式最新版が1.x◦今日の話は.NET Core 1.xベース◦概念としては2.0でも変わらない(予定)
◦ 利用可能なツールのバージョンとかオプションとかは変わるかも
4
.NET Core とは?
.NET Frameworkとの違いや、coreFX, coreCLRの意味するもの
5
.NET Application Model
6
.NET Core Inside
7
.NET Core App (C#/VB)
IL Assembly (exe, dll)
Roslyn CoreFX(.NET Core
Class Library)
ManagedUnmanaged
OS
Native ABI etc
(F#)
compiler
CoreCLR(.NET Core Runtime)
.NET Core SDK To
ols
coreFXに見るOS固有処理の実装
8
coreFXとは.NET Core の基本クラスライブラリ群◦コレクションとかIOとか
開発時、実行時ともライブラリとしてロードされる◦開発時と実行時では参照するものが異なる後で
NuGetとよばれるパッケージマネージャを通して提供
9
NuGetnodejsのnpm、Javaのmaven的なパッケージ管理エコシステム◦ mavenとは違ってビルドシステムは別(MSBuild)
デフォルトでnuget.orgでホストされるパッケージを参照する◦ 公式ライブラリも正式版はここから提供される
◦ アカウントを作成すればだれでもここにホストできる
◦ 専用ホスティングを立てることもできる(社内限定など)
NuGetパッケージの.nupkgは単なるzip圧縮◦ フォルダ階層やフォルダ名に意味がある
◦ 中身はWindowsでおなじみのdllとか◦ LinuxやmacOSでもクラスライブラリの拡張子はdll
10
NuGetにおける複数環境への対応.NET Core以前にも、異なる環境ごとに実装を入れ替えたい要望があった◦ SilverlightとかWindows Phoneとかありましたしね… (遠い目
◦ .NET Frameworkのバージョンごとにわけたというのもある
(歴史的な経緯で)名称は複雑だが、環境ごとにフォルダを分けて同梱できる◦ Portable Class Library (PCL)とかその辺
NuGetクライアントがいい感じに対応するバイナリを拾ってくれる
11
OS固有の処理をいかに記述するかNetworkやFile IOといった処理
プログラミング的なアプローチとしては…◦通常のif文◦コンパイラスイッチ
◦ プラットフォームごとにコンパイラにスイッチを渡してコンパイル対象のコードを切り替えることができる
パフォーマンス上の問題になったり、コードの見通しが悪くなったり…
13
OSごとに参照するdllを差し替える
14
System.Net.Http/4.1.0
┗ref
┗ netstandard1.3
┗System.Net.Http.dll
┗lib
┗ win/lib/ netstandard1.3
┗System.Net.Http.dll
┗ unix/lib/ netstandard1.6
┗System.Net.Http.dll
開発時に参照するライブラリ
Windows上で実行するときに参照
Unix (Linux+Mac)上で実行するときに参照
対応している.NETの環境を示す
15
せっかくHttp通信ライブラリを例に出したのでUnix(Linux+Mac)でHttp通信がどのように実装されているか見てみよう
HttpClient.XXX.cs
16
https://github.com/dotnet/corefx/blob/release/1.1.0/src/System.Net.Http/src/System/Net/Http/HttpClient.cs
17
HttpClientの実装はcurlだった…?.NET Frameworkにはネイティブライブラリを実行するP/Invokeという技術がありました◦ COMだったり
◦ C styleの関数だったり
.NET Coreの世界に来てもP/Invokeは健在です◦ P/Invoke on Linuxはmonoで実現できていたことです
◦ 機能追加に関してもmonoの機能が提案されています
18
P/Invokeのしていること
関数を格納している共有ライブラリを検索
そのライブラリをメモリに読み込み
関数のアドレスを指定+引数をスタックにプッシュ
• .NET とC++のデータ型が一致しないのでマーシャリングも
19
P/Invokeを使えばLinuxでもGUIが!?.NET CoreはGUIはサポートしていない(monoはサポートしている)
が、ネイティブのGUIライブラリをP/Invoke経由で実行することは可能
20
public static void Main(string[] args){var argc = 0;var argv = IntPtr.Zero;gtk_init(ref argc, ref argv);var diag = gtk_message_dialog_new(IntPtr.Zero,DialogFlags.Modal, MessageType.Error, ButtonsType.Ok,“Hello from .NET Core on Red Hat!”, IntPtr.Zero);var res = gtk_dialog_run(diag);gtk_widget_destroy(diag);Console.WriteLine(res);
}
P/Invokeが故におきる事案https://github.com/dotnet/coreclr/issues/5612
ロケールがen-usでない環境だと、次のシンプルなコードが、LinuxだとWindowsの10倍以上遅くなる問題
libicuのロード時間の問題 (未解決)
21
"abcfeg".EndsWith("123");
async on LinuxC# (5.0以降)では非同期処理の記述にasync/await構文が使えます
.NET ではasync/await構文の実装は単純なスレッドプールではないです
WindowsではIO完了ポートが使われています。では、Linuxは?
24
public async Task<string> GetExample(){var client = new HttpClient();var res = await client.GetAsync("http://example.com");return await res.Content.ReadAsStringAsync();
}
epoll for async in Linux
25
https://github.com/dotnet/corefx/blob/release/1.1.0/src/Native/Unix/System.Native/pal_networking.cpp
Linux では epollが、macOSではkqueueが使われています
Debugging .NET Coreon LinuxLinuxの上でも .NET Coreをデバッグしたい
26
WindowsとLinuxでの違い
27
windbg
sos
procmon
perfview
LLDB/GDB
libsosplugin.so
strace
perfcollect
LLDBを使ったデバッグ起動中のプロセスにアタッチする場合
1. sospluginのパスを探しておく例: /opt/dotnet/shared/Microsoft.NETCore.App/1.1.1/libsosplugin.so
2. アタッチ対象のPIDを取得
3. lldb起動
4. lldbコンソールでアタッチ(lldb) process attach -p <PID>
5. プラグインロード(lldb) plugin load/opt/dotnet/shared/Microsoft.NETCore.App/1.1.1/libsosplugin.so(lldb) setclrpath /opt/dotnet/shared/Microsoft.NETCore.App/1.1.1(lldb) clrstack
LLDBを使ったデバッグ出力されたcoreファイルにattachする場合
1. sospluginのパスを探しておく例: /opt/dotnet/shared/Microsoft.NETCore.App/1.1.1/libsosplugin.so
2. gcore <PID> でcoreをはかせる
3. lldb起動$ sudo lldb /opt/dotnet/dotnet --core <corefile>
4. プラグインロード(lldb) plugin load/opt/dotnet/shared/Microsoft.NETCore.App/1.1.1/libsosplugin.so(lldb) setclrpath /opt/dotnet/shared/Microsoft.NETCore.App/1.1.1(lldb) clrstack
30
31
perf ツール1. 対象のPIDを取得
2. PERFを出力して表示する$ sudo perf record -F 99 -p <PID> -a -g -- sleep 10$ sudo perf report --stdio
32
33
Tracing Runtime Eventインストールhttps://lttng.org/docs/v2.8/#doc-fedoraCentOS向けhttp://frederic-wou.net/lttng/
https://raw.githubusercontent.com/dotnet/corefx-tools/master/src/performance/perfcollect/perfcollect
$ wget https://raw.githubusercontent.com/dotnet/corefx-tools/master/src/performance/perfcollect/perfcollect $ sudo ./perfcollect collect samplePerfTrace$ sudo ./perfcollect view samplePerfTrace.trace.zip
34
35
High Level Debugging .NET Core
36
GDB/LLDB
MICore
MIDE/Engine.Impl
MIDE(*)/AD7.Impl
VSCode Debugger
AD7 Interface
*MIDE: MIDebugEngine*vsdbgはVS製品以外での利用禁止かつ再頒布禁止なライセンス
MIText
VS Debugger
VS Debugger Engine
vsdbg(クローズドライセンス*)
windbg
統合可能
リモートデバッキングリモートデバッキングはデバッガーのクライアントと対象のプロセス間で信頼できる通信ができさえすればよい
◦ 多くの場合SSHを利用
◦ Windows同士だったら、昔から対象のマシンにデバッガーツールを入れて通信できていた
◦ クライアントはデバッガーのライセンス上、Visual Studio Family限定になるのが現状
◦ 技術的にはクライアントも任意。ライセンス的にはソースからビルドすればよさそう?
37
Visual Studio Codeからのリモートデバッグ接続.vscode/launch.jsonを編集する
◦ 通信コマンドを記述するので、sshコマンドのほかにdocker rshなども指定可能
38
{"name": ".NET Core Docker Remote Attach","type": "coreclr","request": "attach",“processId”: “86”, //アタッチするPIDを指定
"pipeTransport": {"pipeProgram": “ssh",“pipeArgs”: [ “-T”, “tanaka733@centos.example.com”], //接続先の指定“quoteArgs”:false, //接続プログラムによりfalseがいいときとtrueがいいときがある“debuggerPath”: “/opt/app-root/src/vsdbg/vsdbg”, //接続先のvsdbgパス
"pipeCwd": "${workspaceRoot}"},"sourceFileMap": {
"/opt/app-root/src": "${workspaceRoot}“}
}
Visual Studio on Windowsからのリモートデバッグ接続リモート接続画面でSSHを選択する
◦ 設定が隠れているので、docker rshなどは現状指定できない
◦ docker for WindowsやAzure上のdockerコンテナへはVSの機能により接続可能◦ つまり、Visual Studio拡張とかを書けば技術的にはいけるはず調査中です…
あと今日見たら、プロトコルにWebSocketが追加されてたので夢は広がる?
39
まとめ.NET CoreのクラスライブラリでOS固有の処理ではP/Invokeが大活躍
◦ P/Invokeを利用するが故の問題も起きている
Linux上の.NET Coreプロセスは通常のプロセス◦ lldbやperfといったデバッグ・プロファイルコマンドが利用可能
GUIからのデバッグにはVisual Studio Codeが便利◦ 原理的には別のエディタでもできるが、ライセンス的にVS Familyのみ
デバッグインターフェースに互換性があるので、WindowsとLinux間で相互にリモートデバッグできる
◦ 明示的に記述がないけど、VS on WindowsからLinuxへ、VS Code on LinuxからWindowsへ
40
参考資料GitHub repo
「NuGetでプラットフォーム毎にアセンブリを展開する方法」と「良い感じにコードを共有してプラットフォーム別のアセンブリを作る方法」
P/Invokeを使って.NET Core on LinuxでGUIを作る記事 (英語)◦ https://developers.redhat.com/blog/2016/09/14/pinvoke-in-net-core-rhel/
HttpClient◦ https://github.com/dotnet/corefx/blob/release/1.1.0/src/System.Net.Http/src/System/Net/Http/HttpClient.cs
Staring.StartsWithの呼び出し階層 (StringクラスなどRuntime側でも必要なクラスはcorefxではなくcoreclrで定義されている)
◦ https://github.com/dotnet/coreclr/issues/5612 (Issue本体)
◦ https://github.com/dotnet/coreclr/blob/release/1.1.0/src/mscorlib/src/System/String.Comparison.cs#L1104-L1114
◦ https://github.com/dotnet/coreclr/blob/release/1.1.0/src/mscorlib/src/System/Globalization/CompareInfo.cs#L582-L591
◦ https://github.com/dotnet/coreclr/blob/release/1.1.0/src/mscorlib/src/System/Globalization/CompareInfo.cs#L1346-L1351
◦ ※.NET Core 2.0で割と大掛かりに内部実装変わってます
41
参考資料(2)Async/Await
◦ http://forums.dotnetfoundation.org/t/socket-async-on-linux-vs-windows/2498
◦ https://github.com/dotnet/corefx/blob/release/1.1.0/src/Native/Unix/System.Native/pal_networking.cpp#L2501
◦ https://news.ycombinator.com/item?id=12341909
◦ Async訪ねて3000里 (6) : I/O完了ポートによるワーカースレッドの運用◦ .NET Frameworkでの話。ぜひ(1)から…
◦ https://msdn.microsoft.com/ja-jp/library/cc429203.aspx
◦ http://southworks.com/blog/2013/10/29/asynchronous-io-in-c-io-completion-ports/
Performance Tracing◦ https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/linux-performance-
tracing.md
42
参考資料(3)LLDB
◦ http://blogs.microsoft.co.il/sasha/2017/02/26/analyzing-a-net-core-core-dump-on-linux/
Tracing Runtime Event◦ https://lttng.org/docs/v2.8/#doc-fedora
◦ CentOS向け◦ http://frederic-wou.net/lttng/
◦ スクリプト◦ https://raw.githubusercontent.com/dotnet/corefx-tools/master/src/performance/perfcollect/perfcollect
vsdbg◦ https://github.com/OmniSharp/omnisharp-vscode/wiki/Attaching-to-remote-processes
◦ clrdbgは vsdbgにリプレースされました
◦ OpenShift上のプロセスで説明していますが、docker rshでも同様に実行可能◦ Remote Debugging s2i dotnetcore from Visual Studio Code
43
top related