20170527 inside .net core on linux

40
.NET Core Linuxどのように動いているか、 またわれわれは どのようにデバッグするのか たなか (@TANAKA_733) Y8 2017 SPRING IN SHIBUYA 1

Upload: takayoshi-tanaka

Post on 28-Jan-2018

102 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: 20170527 inside .NET Core on Linux

.NET Core がLinuxでどのように動いているか、またわれわれはどのようにデバッグするのかたなか (@TANAKA_733)

Y8 2017 SPRING IN SHIBUYA

1

Page 2: 20170527 inside .NET Core on Linux

@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◦ [email protected] or twitterで

2

* VSDT: Visual Studio and Development Technologies

Page 3: 20170527 inside .NET Core on Linux

AGENDA.NET Core とは◦ (この後出てくる) coreclrとか corefxが何かを知ってもらう

CoreFX on Linux◦ネットワーク通信とかファイルIOとかどう実装してるのか

Debugging .NET Core on Linux◦ Visual Studioが使えないLinux上でどうやってデバッグするのか

3

Page 4: 20170527 inside .NET Core on Linux

…は話しません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

Page 5: 20170527 inside .NET Core on Linux

.NET Core とは?

.NET Frameworkとの違いや、coreFX, coreCLRの意味するもの

5

Page 6: 20170527 inside .NET Core on Linux

.NET Application Model

6

Page 7: 20170527 inside .NET Core on Linux

.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

Page 8: 20170527 inside .NET Core on Linux

coreFXに見るOS固有処理の実装

8

Page 9: 20170527 inside .NET Core on Linux

coreFXとは.NET Core の基本クラスライブラリ群◦コレクションとかIOとか

開発時、実行時ともライブラリとしてロードされる◦開発時と実行時では参照するものが異なる後で

NuGetとよばれるパッケージマネージャを通して提供

9

Page 10: 20170527 inside .NET Core on Linux

NuGetnodejsのnpm、Javaのmaven的なパッケージ管理エコシステム◦ mavenとは違ってビルドシステムは別(MSBuild)

デフォルトでnuget.orgでホストされるパッケージを参照する◦ 公式ライブラリも正式版はここから提供される

◦ アカウントを作成すればだれでもここにホストできる

◦ 専用ホスティングを立てることもできる(社内限定など)

NuGetパッケージの.nupkgは単なるzip圧縮◦ フォルダ階層やフォルダ名に意味がある

◦ 中身はWindowsでおなじみのdllとか◦ LinuxやmacOSでもクラスライブラリの拡張子はdll

10

Page 11: 20170527 inside .NET Core on Linux

NuGetにおける複数環境への対応.NET Core以前にも、異なる環境ごとに実装を入れ替えたい要望があった◦ SilverlightとかWindows Phoneとかありましたしね… (遠い目

◦ .NET Frameworkのバージョンごとにわけたというのもある

(歴史的な経緯で)名称は複雑だが、環境ごとにフォルダを分けて同梱できる◦ Portable Class Library (PCL)とかその辺

NuGetクライアントがいい感じに対応するバイナリを拾ってくれる

11

Page 12: 20170527 inside .NET Core on Linux

OS固有の処理をいかに記述するかNetworkやFile IOといった処理

プログラミング的なアプローチとしては…◦通常のif文◦コンパイラスイッチ

◦ プラットフォームごとにコンパイラにスイッチを渡してコンパイル対象のコードを切り替えることができる

パフォーマンス上の問題になったり、コードの見通しが悪くなったり…

13

Page 13: 20170527 inside .NET Core on Linux

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の環境を示す

Page 14: 20170527 inside .NET Core on Linux

15

せっかくHttp通信ライブラリを例に出したのでUnix(Linux+Mac)でHttp通信がどのように実装されているか見てみよう

Page 15: 20170527 inside .NET Core on Linux

HttpClient.XXX.cs

16

https://github.com/dotnet/corefx/blob/release/1.1.0/src/System.Net.Http/src/System/Net/Http/HttpClient.cs

Page 16: 20170527 inside .NET Core on Linux

17

Page 17: 20170527 inside .NET Core on Linux

HttpClientの実装はcurlだった…?.NET Frameworkにはネイティブライブラリを実行するP/Invokeという技術がありました◦ COMだったり

◦ C styleの関数だったり

.NET Coreの世界に来てもP/Invokeは健在です◦ P/Invoke on Linuxはmonoで実現できていたことです

◦ 機能追加に関してもmonoの機能が提案されています

18

Page 18: 20170527 inside .NET Core on Linux

P/Invokeのしていること

関数を格納している共有ライブラリを検索

そのライブラリをメモリに読み込み

関数のアドレスを指定+引数をスタックにプッシュ

• .NET とC++のデータ型が一致しないのでマーシャリングも

19

Page 19: 20170527 inside .NET Core on Linux

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);

}

Page 20: 20170527 inside .NET Core on Linux

P/Invokeが故におきる事案https://github.com/dotnet/coreclr/issues/5612

ロケールがen-usでない環境だと、次のシンプルなコードが、LinuxだとWindowsの10倍以上遅くなる問題

libicuのロード時間の問題 (未解決)

21

"abcfeg".EndsWith("123");

Page 21: 20170527 inside .NET Core on Linux

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();

}

Page 22: 20170527 inside .NET Core on Linux

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が使われています

Page 23: 20170527 inside .NET Core on Linux

Debugging .NET Coreon LinuxLinuxの上でも .NET Coreをデバッグしたい

26

Page 24: 20170527 inside .NET Core on Linux

WindowsとLinuxでの違い

27

windbg

sos

procmon

perfview

LLDB/GDB

libsosplugin.so

strace

perfcollect

Page 25: 20170527 inside .NET Core on Linux

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

Page 26: 20170527 inside .NET Core on Linux

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

Page 27: 20170527 inside .NET Core on Linux

30

Page 28: 20170527 inside .NET Core on Linux

31

Page 29: 20170527 inside .NET Core on Linux

perf ツール1. 対象のPIDを取得

2. PERFを出力して表示する$ sudo perf record -F 99 -p <PID> -a -g -- sleep 10$ sudo perf report --stdio

32

Page 30: 20170527 inside .NET Core on Linux

33

Page 31: 20170527 inside .NET Core on Linux

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

Page 32: 20170527 inside .NET Core on Linux

35

Page 33: 20170527 inside .NET Core on Linux

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

統合可能

Page 34: 20170527 inside .NET Core on Linux

リモートデバッキングリモートデバッキングはデバッガーのクライアントと対象のプロセス間で信頼できる通信ができさえすればよい

◦ 多くの場合SSHを利用

◦ Windows同士だったら、昔から対象のマシンにデバッガーツールを入れて通信できていた

◦ クライアントはデバッガーのライセンス上、Visual Studio Family限定になるのが現状

◦ 技術的にはクライアントも任意。ライセンス的にはソースからビルドすればよさそう?

37

Page 35: 20170527 inside .NET Core on Linux

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”, “[email protected]”], //接続先の指定“quoteArgs”:false, //接続プログラムによりfalseがいいときとtrueがいいときがある“debuggerPath”: “/opt/app-root/src/vsdbg/vsdbg”, //接続先のvsdbgパス

"pipeCwd": "${workspaceRoot}"},"sourceFileMap": {

"/opt/app-root/src": "${workspaceRoot}“}

}

Page 36: 20170527 inside .NET Core on Linux

Visual Studio on Windowsからのリモートデバッグ接続リモート接続画面でSSHを選択する

◦ 設定が隠れているので、docker rshなどは現状指定できない

◦ docker for WindowsやAzure上のdockerコンテナへはVSの機能により接続可能◦ つまり、Visual Studio拡張とかを書けば技術的にはいけるはず調査中です…

あと今日見たら、プロトコルにWebSocketが追加されてたので夢は広がる?

39

Page 37: 20170527 inside .NET Core on Linux

まとめ.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

Page 38: 20170527 inside .NET Core on Linux

参考資料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

Page 39: 20170527 inside .NET Core on Linux

参考資料(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

Page 40: 20170527 inside .NET Core on Linux

参考資料(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