ClassMethodsさんの記事で、C,Go,Rust,Python,Node.jsのHello Worldプログラムをstraceで覗いていたのですが、C#も気になりませんか?私は気になるので見てみましょう。
C#のビルド成果物にはJITとAOTの2種類があり、これらの言語がVMを用いないことを考えると比較するならAOTでのstraceが適切です。ただ、せっかくなので両方を見てみましょう。
結論
記事が長いので、結論を書いておきます。
システムコール数の比較は次の通りです。C# (JIT + ICU無効)とC# (JIT + ICU指定)のシステムコール数は本記事に載せていませんがリポジトリを参照してください。
| 実装 | システムコール数 |
|---|---|
| C# (JIT) | 1159 |
| C# (JIT + ICU無効) | 940 |
| C# (JIT + ICU指定) | 985 |
| C# (AOT) | 470 |
| C# (AOT + ICU無効) | 228 |
| C# (AOT + ICU指定) | 290 |
| Go | 185 |
| Rust | 63 |
| C | 34 |
C#の起動時のシステムコールを減らすには、ICUの使用有無を指定するのが効果的です。
- InvariantCultureで問題ない:
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 - 多言語対応が必要:
DOTNET_ICU_VERSION_OVERRIDE=<バージョン>で探索を削減
環境
今回の検証はguitarrapc/linux-straceリポジトリで公開しています。元の記事のリポジトリを参考にしつつ、C#のJIT/AOT両方や結果を記載し、再現が取れるようにコンテナで動かしています。気になる方は参照してください。
| 項目 | バージョン |
|---|---|
| OS | Ubuntu 24.04 (コンテナ) |
| C (gcc) | 13.3.0 |
| Rust | 1.93.0 |
| Go | 1.24.1 |
| .NET SDK | 10.0.102 |
| strace | 6.8 |
検証
各言語でHello, Worldを書いていきます。C、Rust、Goは元記事と同じコードです。
C#
Console.WriteLine("Hello, World");
C
#include <stdio.h> int main() { printf("Hello World\n"); return 0; }
Rust
fn main() { println!("Hello World"); }
Go
package main import ( "fmt" ) func main() { fmt.Println("Hello World") }
成果物の生成
成果物を生成する流れは本題ではないので、再現したい人向けに簡単に説明します。
C#は、JITとAOTはPublishAotの有無だけで切り替わります。publish時のパラメーターで指定してもいいのですが、わかりやすくするため、フォルダを分けて2つ用意しましょう。それぞれhello_csharp (JIT)とhello_csharp_aot (AOT)を使います。
C# (JIT)
JIT設定のhello_csharp.csprojです。ランタイムを自己完結型にして、単一ファイルにまとめる設定です。
mkdir hello_csharp
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net10.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <PublishSingleFile>true</PublishSingleFile> <SelfContained>true</SelfContained> </PropertyGroup> </Project>
成果物をリリースビルドで作成します。
dotnet publish -c Release -r linux-x64 -o ./bin hello_csharp/hello_csharp.csproj
C# (AOT)
AOT設定のhello_csharp_aot.csprojです。JITとの違いは、<PublishAot>true</PublishAot>の追加だけです。
mkdir hello_csharp_aot
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net10.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <PublishSingleFile>true</PublishSingleFile> <SelfContained>true</SelfContained> <PublishAot>true</PublishAot> </PropertyGroup> </Project>
dotnet publish -c Release -r linux-x64 -o ./bin hello_csharp_aot/hello_csharp_aot.csproj
C
gcc hello_c/main.c -o ./bin/hello_c
Rust
rustc hello_rust/main.rs -o ./bin/hello_rust
Go
静的リンク版(通常)と共有ライブラリ版1の2種類を作成します。
cd hello_go && go build -o ../bin/hello_go && cd .. cd hello_go && go build -linkshared -o ../bin/hello_go_linkshared && cd ..
システムコールの統計を比較
元記事同様に、strace -cオプションでシステムコール数の統計を出します。
strace -c `./バイナリ`
使うバイナリはこちらです。各言語を見ていきましょう。
$ ls -l hello* -rwxr-xr-x 1 guitarrapc guitarrapc 15960 Feb 9 18:32 hello_c -rwxr-xr-x 1 guitarrapc guitarrapc 73522500 Feb 9 18:09 hello_csharp -rwxr-xr-x 1 guitarrapc guitarrapc 1270792 Feb 9 18:18 hello_csharp_aot -rwxr-xr-x 1 guitarrapc guitarrapc 2204715 Feb 9 18:32 hello_go -rwxr-xr-x 1 guitarrapc guitarrapc 3893728 Feb 9 18:33 hello_rust
C
$ strace -c ./hello_c Hello World % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 32.15 0.000109 13 8 mmap 10.62 0.000036 12 3 mprotect 8.55 0.000029 29 1 write 6.49 0.000022 7 3 brk 5.31 0.000018 9 2 close 5.31 0.000018 6 3 fstat 5.31 0.000018 9 2 pread64 4.42 0.000015 15 1 munmap 4.13 0.000014 7 2 openat 2.95 0.000010 10 1 read 2.65 0.000009 9 1 prlimit64 2.65 0.000009 9 1 getrandom 2.36 0.000008 8 1 arch_prctl 2.36 0.000008 8 1 set_tid_address 2.36 0.000008 8 1 set_robust_list 2.36 0.000008 8 1 rseq 0.00 0.000000 0 1 1 access 0.00 0.000000 0 1 execve ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000339 9 34 1 total
Rust
$ strace -c ./hello_rust Hello World % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ------------------ 18.45 0.000119 9 13 mmap 9.46 0.000061 12 5 mprotect 8.84 0.000057 11 5 read 7.91 0.000051 12 4 close 7.13 0.000046 9 5 rt_sigaction 7.13 0.000046 11 4 openat 6.67 0.000043 21 2 munmap 4.03 0.000026 8 3 brk 4.03 0.000026 8 3 sigaltstack 3.72 0.000024 6 4 fstat 3.26 0.000021 21 1 write 3.26 0.000021 10 2 pread64 3.26 0.000021 21 1 getrandom 2.79 0.000018 9 2 prlimit64 1.86 0.000012 12 1 poll 1.55 0.000010 10 1 sched_getaffinity 1.40 0.000009 9 1 arch_prctl 1.40 0.000009 9 1 gettid 1.40 0.000009 9 1 set_tid_address 1.24 0.000008 8 1 set_robust_list 1.24 0.000008 8 1 rseq 0.00 0.000000 0 1 1 access 0.00 0.000000 0 1 execve ------ ----------- ----------- --------- --------- ------------------ 100.00 0.000645 10 63 1 total
Go
$ strace -c ./hello_go Hello World % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ------------------ 54.59 0.001041 9 114 rt_sigaction 14.53 0.000277 15 18 rt_sigreturn 10.44 0.000199 39 5 1 futex 7.03 0.000134 67 2 clone 4.09 0.000078 13 6 fcntl 3.15 0.000060 10 6 rt_sigprocmask 1.73 0.000033 1 20 mmap 1.68 0.000032 16 2 prlimit64 1.31 0.000025 25 1 write 1.05 0.000020 10 2 sigaltstack 0.42 0.000008 8 1 gettid 0.00 0.000000 0 1 read 0.00 0.000000 0 1 close 0.00 0.000000 0 2 madvise 0.00 0.000000 0 1 execve 0.00 0.000000 0 1 arch_prctl 0.00 0.000000 0 1 sched_getaffinity 0.00 0.000000 0 1 openat ------ ----------- ----------- --------- --------- ------------------ 100.00 0.001907 10 185 1 total
C# (AOT)
$ strace -c ./hello_csharp_aot Hello, World % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ------------------ 33.24 0.001192 9 129 83 openat 14.89 0.000534 8 61 mmap 12.97 0.000465 17 27 mprotect 7.45 0.000267 12 22 munmap 6.53 0.000234 5 44 fstat 5.94 0.000213 4 45 close 4.35 0.000156 9 16 12 newfstatat 3.12 0.000112 2 38 read 2.51 0.000090 5 18 rt_sigaction 2.29 0.000082 13 6 rt_sigprocmask 1.06 0.000038 9 4 ioctl 0.98 0.000035 17 2 write 0.98 0.000035 17 2 clone3 0.70 0.000025 8 3 futex 0.56 0.000020 1 17 madvise 0.47 0.000017 17 1 pipe2 0.31 0.000011 11 1 lseek 0.28 0.000010 3 3 pread64 0.25 0.000009 2 4 brk 0.25 0.000009 3 3 sched_getaffinity 0.22 0.000008 2 3 getpid 0.22 0.000008 8 1 fcntl 0.22 0.000008 8 1 gettid 0.22 0.000008 2 4 prlimit64 0.00 0.000000 0 1 1 access 0.00 0.000000 0 1 execve 0.00 0.000000 0 1 sysinfo 0.00 0.000000 0 2 statfs 0.00 0.000000 0 1 arch_prctl 0.00 0.000000 0 2 getdents64 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 1 get_mempolicy 0.00 0.000000 0 1 set_robust_list 0.00 0.000000 0 1 getrandom 0.00 0.000000 0 2 membarrier 0.00 0.000000 0 1 rseq ------ ----------- ----------- --------- --------- ------------------ 100.00 0.003586 7 470 96 total
C# (JIT)
$ strace -c ./hello_csharp Hello, World % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ------------------ 46.49 0.002176 6 343 mprotect 18.44 0.000863 5 161 mmap 9.25 0.000433 2 163 92 openat 4.10 0.000192 5 37 munmap 3.18 0.000149 3 38 34 readlink 2.88 0.000135 6 21 pread64 2.67 0.000125 1 67 fstat 2.63 0.000123 5 22 fcntl 2.22 0.000104 6 15 rt_sigprocmask 1.60 0.000075 8 9 stat 1.30 0.000061 1 61 close 1.22 0.000057 8 7 clone3 1.03 0.000048 2 24 rt_sigaction 0.58 0.000027 0 58 read 0.43 0.000020 3 6 6 access 0.41 0.000019 1 11 brk 0.34 0.000016 8 2 pipe2 0.28 0.000013 1 9 futex 0.26 0.000012 3 4 ioctl 0.21 0.000010 2 5 getpid 0.19 0.000009 1 8 write 0.19 0.000009 0 23 madvise 0.11 0.000005 5 1 lseek 0.00 0.000000 0 1 socket 0.00 0.000000 0 1 bind 0.00 0.000000 0 1 listen 0.00 0.000000 0 1 execve 0.00 0.000000 0 1 ftruncate 0.00 0.000000 0 5 2 unlink 0.00 0.000000 0 1 fchmod 0.00 0.000000 0 2 sysinfo 0.00 0.000000 0 1 getsid 0.00 0.000000 0 2 sigaltstack 0.00 0.000000 0 2 statfs 0.00 0.000000 0 1 arch_prctl 0.00 0.000000 0 1 gettid 0.00 0.000000 0 4 sched_getaffinity 0.00 0.000000 0 2 getdents64 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 1 get_mempolicy 0.00 0.000000 0 2 mknodat 0.00 0.000000 0 16 12 newfstatat 0.00 0.000000 0 1 set_robust_list 0.00 0.000000 0 10 prlimit64 0.00 0.000000 0 1 getrandom 0.00 0.000000 0 1 memfd_create 0.00 0.000000 0 4 membarrier 0.00 0.000000 0 1 rseq ------ ----------- ----------- --------- --------- ------------------ 100.00 0.004681 4 1159 146 total
元記事に比べてGoのシステムコール数が減っています。(911 -> 185前後) straceは決定論的に結果が出るわけではないので、実行ごとに多少のばらつきがありますが、明らかに違いがあります。Goのバージョンは元記事が1.24.0、今回が1.24.1なので、このような差が生まれる要因とは考えにくく、実際記事のリポジトリにあるコンテナを用いても本記事と同様の190前後でした。おや?
本記事で追加したC# (JIT)とC# (AOT)ですが、JITは1159回、AOTは470回と大きな差があります。AOTはネイティブコードに変換されているので、JITのように実行時にコードを生成する必要がなく、その分システムコール数が減っています。これは、あとから見るwriteの数の違いでも分かります。
C#のopenatシステムコールとICU
C#はAOTにしてもまだシステムコールが大きく、特にopenatの数が多いです。openat/readlink/accessはerrorsがあるのも気になります。
straceでopenatを調べてみると、openat(…libicu*.so…)ログから、プログラムロード前にICU(国際化対応ライブラリ)のデータファイルを探しに行っていることが分かります。glibc-hwcapsバージョンごとにICUバージョンを90 > 89 > 88 ... 74と探索するため、openatが大きく増え、ICUファイルが見つからなければENOENTが出てerrorがカウントされます。最後にlibicuuc.so.74が見つかった瞬間から、libicudata.so.74やlibicui18n.so.74のロードに進んでいます。
結果、(候補バージョン数) × (探索ディレクトリ数) × (hwcaps分岐)でopenatもエラーが増えているわけです。
$ strace -f -e trace=openat,newfstatat,access -s 200 ./bin/hello_csharp_aot 2>&1
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/proc/self/mountinfo", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/self/mountinfo", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY) = 3
openat(AT_FDCWD, "/sys/fs/cgroup//cpu.max", O_RDONLY) = 3
strace: Process 160 attached
[pid 159] openat(AT_FDCWD, "/sys/fs/cgroup//memory.max", O_RDONLY) = 3
[pid 159] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index0/size", O_RDONLY) = 3
[pid 159] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index0/level", O_RDONLY) = 3
[pid 159] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index1/size", O_RDONLY) = 3
[pid 159] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index1/level", O_RDONLY) = 3
[pid 159] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index2/size", O_RDONLY) = 3
[pid 159] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index2/level", O_RDONLY) = 3
[pid 159] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index3/size", O_RDONLY) = 3
[pid 159] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index3/level", O_RDONLY) = 3
[pid 159] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index4/size", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/proc/meminfo", O_RDONLY) = 3
[pid 159] openat(AT_FDCWD, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 3
strace: Process 161 attached
[pid 159] openat(AT_FDCWD, "/root/.terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/root/.terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/share/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v4/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v4/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/lib/x86_64-linux-gnu/", {st_mode=S_IFDIR|0755, st_size=16384, ...}, 0) = 0
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v4/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v4/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/", {st_mode=S_IFDIR|0755, st_size=16384, ...}, 0) = 0
[pid 159] openat(AT_FDCWD, "/lib/glibc-hwcaps/x86-64-v4/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/lib/glibc-hwcaps/x86-64-v4/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/glibc-hwcaps/x86-64-v3/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/lib/glibc-hwcaps/x86-64-v3/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/glibc-hwcaps/x86-64-v2/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/lib/glibc-hwcaps/x86-64-v2/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/lib/", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
[pid 159] openat(AT_FDCWD, "/usr/lib/glibc-hwcaps/x86-64-v4/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/usr/lib/glibc-hwcaps/x86-64-v4/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/glibc-hwcaps/x86-64-v3/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/usr/lib/glibc-hwcaps/x86-64-v3/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/glibc-hwcaps/x86-64-v2/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/usr/lib/glibc-hwcaps/x86-64-v2/", 0x7ffc1064fc30, 0) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] newfstatat(AT_FDCWD, "/usr/lib/", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/lib/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/usr/lib/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.74", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicudata.so.74", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 159] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicui18n.so.74", O_RDONLY|O_CLOEXEC) = 6
Hello, World
[pid 161] +++ exited with 0 +++
[pid 160] +++ exited with 0 +++
+++ exited with 0 +++
ICUの読み込みを無効化する
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1を指定するとICUの読み込みを無効化できます。この状態でstraceを取ると、全体の数が470から228へ、openatの数が129 (83)から28 (7)へ減っています。
$ DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 strace -c ./bin/hello_csharp_aot Hello, World % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ------------------ 18.23 0.000144 5 28 7 openat 14.18 0.000112 6 18 rt_sigaction 14.05 0.000111 55 2 clone 8.48 0.000067 2 30 read 6.84 0.000054 13 4 ioctl 6.46 0.000051 2 22 mprotect 4.81 0.000038 6 6 rt_sigprocmask 4.68 0.000037 18 2 write 3.16 0.000025 1 20 mmap 2.78 0.000022 1 21 close 2.78 0.000022 1 17 madvise 2.53 0.000020 1 20 fstat 2.28 0.000018 18 1 pipe2 1.65 0.000013 4 3 pread64 1.39 0.000011 3 3 sched_getaffinity 1.27 0.000010 10 1 fcntl 1.14 0.000009 9 1 lseek 1.14 0.000009 3 3 getpid 1.14 0.000009 2 4 prlimit64 1.01 0.000008 8 1 gettid 0.00 0.000000 0 4 munmap 0.00 0.000000 0 3 brk 0.00 0.000000 0 1 1 access 0.00 0.000000 0 1 execve 0.00 0.000000 0 1 sysinfo 0.00 0.000000 0 2 statfs 0.00 0.000000 0 1 arch_prctl 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 1 1 get_mempolicy 0.00 0.000000 0 1 set_robust_list 0.00 0.000000 0 1 getrandom 0.00 0.000000 0 2 membarrier 0.00 0.000000 0 1 rseq 0.00 0.000000 0 1 1 clone3 ------ ----------- ----------- --------- --------- ------------------ 100.00 0.000790 3 228 10 total
openatの呼び出しログからもICU探索ブロックが丸ごと消えています。
$ DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 strace -f -e trace=openat,newfstatat,access -s 200 ./bin/hello_csharp_aot 2>&1
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/proc/self/mountinfo", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/self/mountinfo", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY) = 3
openat(AT_FDCWD, "/sys/fs/cgroup//cpu.max", O_RDONLY) = 3
strace: Process 187 attached
[pid 186] openat(AT_FDCWD, "/sys/fs/cgroup//memory.max", O_RDONLY) = 3
[pid 186] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index0/size", O_RDONLY) = 3
[pid 186] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index0/level", O_RDONLY) = 3
[pid 186] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index1/size", O_RDONLY) = 3
[pid 186] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index1/level", O_RDONLY) = 3
[pid 186] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index2/size", O_RDONLY) = 3
[pid 186] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index2/level", O_RDONLY) = 3
[pid 186] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index3/size", O_RDONLY) = 3
[pid 186] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index3/level", O_RDONLY) = 3
[pid 186] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index4/size", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 186] openat(AT_FDCWD, "/proc/meminfo", O_RDONLY) = 3
[pid 186] openat(AT_FDCWD, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 3
strace: Process 188 attached
[pid 186] openat(AT_FDCWD, "/root/.terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 186] openat(AT_FDCWD, "/root/.terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 186] openat(AT_FDCWD, "/etc/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 186] openat(AT_FDCWD, "/etc/terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 186] openat(AT_FDCWD, "/lib/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 186] openat(AT_FDCWD, "/lib/terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 186] openat(AT_FDCWD, "/usr/share/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = 6
Hello, World
[pid 188] +++ exited with 0 +++
[pid 187] +++ exited with 0 +++
+++ exited with 0 +++
ICUバージョンを指定する
ICU探索が重いからと言って、グローバリゼーションを無効にしてもいいアプリケーションばかりではありません。当然多言語対応が必要な場合もあります。この場合、ICUライブラリバージョンを指定するか、アプリに同梱する手があります。DOTNET_ICU_VERSION_OVERRIDE=74でICUバージョンを指定でき、該当バージョンのICUライブラリだけを探索するようになります。この状態でstraceを取ると、全体の数が470から290 (無効だと228)へ、openatの数が129 (83)から35(7)(無効だと28 (7))へ減っています。
ICU対応は、AOTに限らずJITでも同様に効果があります。
$ DOTNET_ICU_VERSION_OVERRIDE=74 strace -c ./bin/hello_csharp_aot Hello, World % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ------------------ 22.68 0.000414 9 45 mmap 13.86 0.000253 7 35 7 openat 11.45 0.000209 7 27 mprotect 7.07 0.000129 3 35 read 5.37 0.000098 3 28 close 5.37 0.000098 5 17 madvise 5.26 0.000096 5 18 rt_sigaction 5.15 0.000094 3 27 fstat 4.66 0.000085 14 6 rt_sigprocmask 3.67 0.000067 33 2 clone 3.34 0.000061 10 6 munmap 2.74 0.000050 12 4 ioctl 2.03 0.000037 18 2 write 1.48 0.000027 9 3 futex 1.04 0.000019 19 1 pipe2 0.77 0.000014 4 3 sched_getaffinity 0.77 0.000014 3 4 prlimit64 0.66 0.000012 4 3 pread64 0.60 0.000011 2 4 brk 0.55 0.000010 10 1 fcntl 0.49 0.000009 9 1 lseek 0.49 0.000009 3 3 getpid 0.49 0.000009 9 1 gettid 0.00 0.000000 0 1 1 access 0.00 0.000000 0 1 execve 0.00 0.000000 0 1 sysinfo 0.00 0.000000 0 2 statfs 0.00 0.000000 0 1 arch_prctl 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 1 1 get_mempolicy 0.00 0.000000 0 1 set_robust_list 0.00 0.000000 0 1 getrandom 0.00 0.000000 0 2 membarrier 0.00 0.000000 0 1 rseq 0.00 0.000000 0 1 1 clone3 ------ ----------- ----------- --------- --------- ------------------ 100.00 0.001825 6 290 10 total
straceでopenatの呼び出しログを見ると、ICU探索ブロックが期待通り1つだけ存在し、ENOENTも発生していません。
$ DOTNET_ICU_VERSION_OVERRIDE=74 strace -f -e trace=openat,newfstatat,access -s 200 ./bin/hello_csharp_aot
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/proc/self/mountinfo", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/self/mountinfo", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY) = 3
openat(AT_FDCWD, "/sys/fs/cgroup//cpu.max", O_RDONLY) = 3
strace: Process 175 attached
[pid 174] openat(AT_FDCWD, "/sys/fs/cgroup//memory.max", O_RDONLY) = 3
[pid 174] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index0/size", O_RDONLY) = 3
[pid 174] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index0/level", O_RDONLY) = 3
[pid 174] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index1/size", O_RDONLY) = 3
[pid 174] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index1/level", O_RDONLY) = 3
[pid 174] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index2/size", O_RDONLY) = 3
[pid 174] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index2/level", O_RDONLY) = 3
[pid 174] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index3/size", O_RDONLY) = 3
[pid 174] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index3/level", O_RDONLY) = 3
[pid 174] openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/cache/index4/size", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 174] openat(AT_FDCWD, "/proc/meminfo", O_RDONLY) = 3
[pid 174] openat(AT_FDCWD, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 3
strace: Process 176 attached
[pid 174] openat(AT_FDCWD, "/root/.terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 174] openat(AT_FDCWD, "/root/.terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 174] openat(AT_FDCWD, "/etc/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 174] openat(AT_FDCWD, "/etc/terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 174] openat(AT_FDCWD, "/lib/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 174] openat(AT_FDCWD, "/lib/terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 174] openat(AT_FDCWD, "/usr/share/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = 6
[pid 174] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 174] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicuuc.so.74", O_RDONLY|O_CLOEXEC) = 6
[pid 174] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicudata.so.74", O_RDONLY|O_CLOEXEC) = 6
[pid 174] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 6
[pid 174] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 6
[pid 174] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
[pid 174] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libicui18n.so.74", O_RDONLY|O_CLOEXEC) = 6
Hello, World
[pid 176] +++ exited with 0 +++
[pid 175] +++ exited with 0 +++
+++ exited with 0 +++
ICUを指定するためには、対象環境に入っているICUライブラリのバージョンを知る必要があります。ldconfig -pで確認できるので、使うと良いでしょう。
$ ldconfig -p | grep -E 'libicu(uc|i18n)\.so' | head -n 50
libicuuc.so.74 (libc6,x86-64) => /lib/x86_64-linux-gnu/libicuuc.so.74
libicui18n.so.74 (libc6,x86-64) => /lib/x86_64-linux-gnu/libicui18n.so.74
あるいはアプリケーションでICUバージョンを指定できるので、いずれかを使うと良いでしょう。
InvariantCultureを使えればいいのですが、そうでない場合はICUバージョン指定で起動時間を改善できるのはなるほどです。
C# AOTのopenatシステムコール
straceログから、ICUを除いたopenatの呼び出しは以下だけに限定されています。2
/sys/devices/system/cpu/.../proc/self/mountinfo,/proc/self/cgroup/sys/fs/cgroup/.../cpu.max,memory.max/proc/meminfo,/proc/self/maps/dev/urandomterminfo探索
他言語を見てみましょう。CとRustはlibcを通じて同様の情報を取得しているようです。Goはランタイムが独自に実装しているため、プロセスを複数生成して情報を集めています。こうやって見ると、C#は診断用にいくつかのファイルを読んだり、icu、terminfoを読んだりしているのが追加部分と分かります。
C
$ strace -f -e trace=openat,newfstatat,access -s 200 ./bin/hello_c 2>&1
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
Hello World
+++ exited with 0 +++
Rust
$ strace -f -e trace=openat,newfstatat,access -s 200 ./bin/hello_rust 2>&1
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 3
Hello World
+++ exited with 0 +++
Go
$ strace -f -e trace=openat,newfstatat,access -s 200 ./bin/hello_go 2>&1
openat(AT_FDCWD, "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", O_RDONLY) = 3
strace: Process 239 attached
strace: Process 240 attached
[pid 238] --- SIGURG {si_signo=SIGURG, si_code=SI_TKILL, si_pid=238, si_uid=0} ---
strace: Process 241 attached
strace: Process 242 attached
strace: Process 243 attached
Hello World
[pid 243] +++ exited with 0 +++
[pid 242] +++ exited with 0 +++
[pid 241] +++ exited with 0 +++
[pid 240] +++ exited with 0 +++
[pid 239] +++ exited with 0 +++
+++ exited with 0 +++
C#ランタイムが読むシステムファイルの意味
C#が/sys,/procを色々読んでいるのは、dotnetランタイムがコンテナ/CPU/メモリのチューニングに必要なためです。index4がENOENTなのは単にそのCPUにindex4が無いので、最後まで試しているだけです。環境検出(CPU/NUMA/キャッシュ)、制限検出(cgroup)、メモリ検出、乱数、Console(terminfo)の5系統しかなく、パスが固定なので、起動時決め打ちの必要な情報を取っているように見えます。
他言語より多いものの、むしろC/Rustは最低限の情報しか取っていないとも言えます。
コンテナリソース制限(cgroup)検出
これらはdotnetランタイムがコンテナ内のCPU quotaやメモリ上限を読むためのものです。実際、dotnetランタイムのGCはコンテナリソース制限を考慮して動作するため必要な情報です。
/proc/self/mountinfo/proc/self/cgroup:/sys/fs/cgroup/.../cpu.max/sys/fs/cgroup/.../memory.max
CPU情報
C/Rustより多いポイントで、CPUトポロジ/キャッシュ階層を取得しています。dotnetランタイムが、GCのセグメント/ヒープ構成やスレッドプールや初期パラメーターに必要な情報です。
/sys/devices/system/cpu/onlinecpu0/cache/index*/{size,level}
メモリ情報・自己マップ
物理メモリ等、自プロセスのマップ(保護設定、診断、アンワインド/例外、スタック関連など)でランタイム起動時に必要な情報です。
/proc/meminfo/proc/self/maps:
乱数
ハッシュのランダム化やセキュリティ機能のために乱数を取得します。
/dev/urandom
terminfo
TERM=dumbにしても1しか減らないことから、Console周りがterminfoをスキップしない、あるいはTERM=dumbでも最低限の確認をしているようです。terminfoで6回ENOENTが出ているのは嫌ですが、まぁ仕方ないでしょう。
~/.terminfo//etc/terminfo//lib/terminfo//usr/share/terminfo
C#のwriteシステムコール
ここまでopenatを見てきましたが、writeシステムコールが他言語は標準出力の1回だけなのに対して、C# AOTは2回、JITは8回呼ばれています。これは割と特徴的なのstrace -e writeでwriteシステムコールを深堀りしてみましょう。
C
$ strace -e write ./bin/hello_c > /dev/null write(1, "Hello World\n", 12) = 12 +++ exited with 0 +++
Rust
$ strace -e write ./bin/hello_rust > /dev/null write(1, "Hello World\n", 12) = 12 +++ exited with 0 +++
Go
$ strace -e write ./bin/hello_go > /dev/null
--- SIGURG {si_signo=SIGURG, si_code=SI_TKILL, si_pid=5462, si_uid=0} ---
--- SIGURG {si_signo=SIGURG, si_code=SI_TKILL, si_pid=5462, si_uid=0} ---
--- SIGURG {si_signo=SIGURG, si_code=SI_TKILL, si_pid=5462, si_uid=0} ---
write(1, "Hello World\n", 12) = 12
+++ exited with 0 +++
C# AOT
$ strace -e write ./bin/hello_csharp_aot > /dev/null write(0, "\33[?1h\33=", 7) = 7 write(3, "Hello, World\n", 13) = 13 +++ exited with 0 +++
C# JIT
$ strace -e write ./bin/hello_csharp > /dev/null write(13, "*", 1) = 1 write(14, ".NET Finalizer", 14) = 14 write(13, "*", 1) = 1 write(16, ".NET Tiered Com", 15) = 15 write(15, "*", 1) = 1 write(0, "\33[?1h\33=", 7) = 7 write(24, "Hello, World\n", 13) = 13 write(4, "\1", 1) = 1 +++ exited with 0 +++
C、Rust、Goは標準出力への1回のwriteだけですが、C# AOTでは端末制御シーケンスを書き込んでから標準出力へ書き込んでいます。JITではさらに診断情報を書き込んでいます。C# AOTとJITを詳しく見てみましょう。
C# AOTのwriteシステムコール
straceのオプションを追加して、タイムスタンプ、File descriptor(FD)のパス、バッファ内容を表示します。
$ strace -f -ttt -e trace=write,writev -s 200 -yy -xx ./bin/hello_csharp_aot strace: Process 13 attached strace: Process 14 attached [pid 12] 1770645277.828800 write(1<\x2f\x64\x65\x76\x2f\x70\x74\x73\x2f\x30<char 136:0>>, "\x1b\x5b\x3f\x31\x68\x1b\x3d", 7) = 7 [pid 12] 1770645277.830239 write(3<\x2f\x64\x65\x76\x2f\x70\x74\x73\x2f\x30<char 136:0>>, "\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x0a", 13Hello, World ) = 13 [pid 14] 1770645277.830626 +++ exited with 0 +++ [pid 13] 1770645277.830656 +++ exited with 0 +++ 1770645277.831918 +++ exited with 0 +++ $ strace -f -ttt -e trace=write,writev -s 200 -yy ./bin/hello_csharp_aot strace: Process 31 attached strace: Process 32 attached [pid 30] 1770646142.571391 write(1</dev/pts/0<char 136:0>>, "\33[?1h\33=", 7) = 7 [pid 30] 1770646142.572052 write(3</dev/pts/0<char 136:0>>, "Hello, World\n", 13Hello, World ) = 13 [pid 32] 1770646142.573542 +++ exited with 0 +++ [pid 31] 1770646142.573563 +++ exited with 0 +++ 1770646142.574448 +++ exited with 0 +++
1回目のwriteで端末のモード切り替え(ANSIエスケープ)を流し、それからFD 3へ"Hello, World\n"を書き込んでいます。FD 3はstraceの-yyオプションでパスを表示させたところ、/dev/pts/0となっており、標準出力が端末に接続されている場合に割り当てられる擬似端末デバイスです。つまり、C# AOTでは標準出力に直接書き込むのではなく、一旦擬似端末デバイスに書き込んでから端末に出力していることになります。
1回目のwrite
端末のモード切り替えは以下の処理で、DECCKM: cursor keys modeとDECKPAM(Keypad Application Modeを設定しています。
\x1b=ESC\x1b\x5b\x3f\x31\x68=ESC [ ? 1 h= DEC Private Mode Set 1 (DECCKM: cursor keys mode)\x1b\x3d=ESC= DECKPAM(Keypad Application Mode)
write(1<\x2f\x64\x65\x76\x2f\x70\x74\x73\x2f\x30<char 136:0>>, "\x1b\x5b\x3f\x31\x68\x1b\x3d", 7) = 7
あるいは、エスケープシーケンスを可読化すると以下のようになります。
write(1</dev/pts/0<char 136:0>>, "\33[?1h\33=", 7) = 7
dotnet/runtimeのどこで処理されているかというと、src/libraries/System.Console/src/System/ConsolePal.Unix.csのEnsureConsoleInitialized関数にて、Interop.Sys.SetKeypadXmit(s_terminalHandle, keypadXmit);で端末のモード切替をしています。
private static unsafe void EnsureInitializedCore() { lock (Console.Out) // ensure that writing the ANSI string and setting initialized to true are done atomically { if (!s_initialized) { // Do this even when redirected to make CancelKeyPress works. if (!Interop.Sys.InitializeTerminalAndSignalHandling()) { throw new Win32Exception(); } // InitializeTerminalAndSignalHandling will reset the terminal on a normal exit. // This also resets it for termination due to an unhandled exception. AppDomain.CurrentDomain.UnhandledException += (_, _) => { Interop.Sys.UninitializeTerminal(); }; s_terminalHandle = !Console.IsOutputRedirected ? OpenStandardOutputHandle() : !Console.IsInputRedirected ? OpenStandardInputHandle() : null; // Provide the native lib with the correct code from the terminfo to transition us into // "application mode". This will both transition it immediately, as well as allow // the native lib later to handle signals that require re-entering the mode. if (s_terminalHandle != null && TerminalFormatStringsInstance.KeypadXmit is string keypadXmit) { Interop.Sys.SetKeypadXmit(s_terminalHandle, keypadXmit); }
2回目のwriteはなぜFD3なのか
Hello, World\nを出力していますが、FD 3へ書き込んでいます。
write(3<\x2f\x64\x65\x76\x2f\x70\x74\x73\x2f\x30<char 136:0>>, "\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x0a", 13Hello, World
エスケープシーケンスを可読化すると以下のようになります。
write(3</dev/pts/0<char 136:0>>, "Hello, World\n", 13Hello, World
CやRust、Goは標準出力FD 1へ直接書き込んでいるのに対して、C# AOTは擬似端末デバイスFD 3へ書き込んでいる点は不思議ですね。
# C $ strace -f -ttt -e trace=write,writev -s 200 -yy ./bin/hello_c write(1</dev/pts/0<char 136:0>>, "Hello World\n", 12Hello World # Rust $ strace -f -ttt -e trace=write,writev -s 200 -yy ./bin/hello_rust write(1</dev/pts/0<char 136:0>>, "Hello World\n", 12Hello World # Go $ strace -f -ttt -e trace=write,writev -s 200 -yy ./bin/hello_go write(1</dev/pts/0<char 136:0>>, "Hello World\n", 12Hello World
書き込みを追ってみましょう。
$ strace -f -ttt -e trace=dup,dup2,dup3,fcntl,openat,close,write -s 200 -yy ./bin/hello_csharp_aot 1770646837.538617 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3</etc/ld.so.cache> 1770646837.538979 close(3</etc/ld.so.cache>) = 0 1770646837.539104 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3</usr/lib/x86_64-linux-gnu/libm.so.6> 1770646837.539803 close(3</usr/lib/x86_64-linux-gnu/libm.so.6>) = 0 1770646837.539917 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3</usr/lib/x86_64-linux-gnu/libc.so.6> 1770646837.540707 close(3</usr/lib/x86_64-linux-gnu/libc.so.6>) = 0 1770646837.543771 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC) = 3</sys/devices/system/cpu/online> 1770646837.544000 close(3</sys/devices/system/cpu/online>) = 0 1770646837.544644 openat(AT_FDCWD</workspace>, "/proc/self/mountinfo", O_RDONLY) = 3</proc/137/mountinfo> 1770646837.545334 close(3</proc/137/mountinfo>) = 0 1770646837.545512 openat(AT_FDCWD</workspace>, "/proc/self/cgroup", O_RDONLY) = 3</proc/137/cgroup> 1770646837.545820 close(3</proc/137/cgroup>) = 0 1770646837.546360 openat(AT_FDCWD</workspace>, "/proc/self/mountinfo", O_RDONLY) = 3</proc/137/mountinfo> 1770646837.546940 close(3</proc/137/mountinfo>) = 0 1770646837.547053 openat(AT_FDCWD</workspace>, "/proc/self/cgroup", O_RDONLY) = 3</proc/137/cgroup> 1770646837.547324 close(3</proc/137/cgroup>) = 0 1770646837.547582 openat(AT_FDCWD</workspace>, "/sys/fs/cgroup//cpu.max", O_RDONLY) = 3</sys/fs/cgroup/cpu.max> 1770646837.547895 close(3</sys/fs/cgroup/cpu.max>) = 0 strace: Process 138 attached [pid 137] 1770646837.549562 openat(AT_FDCWD</workspace>, "/sys/fs/cgroup//memory.max", O_RDONLY) = 3</sys/fs/cgroup/memory.max> [pid 137] 1770646837.549880 close(3</sys/fs/cgroup/memory.max>) = 0 [pid 137] 1770646837.550374 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index0/size", O_RDONLY) = 3</sys/devices/system/cpu/cpu0/cache/index0/size> [pid 137] 1770646837.550791 close(3</sys/devices/system/cpu/cpu0/cache/index0/size>) = 0 [pid 137] 1770646837.550911 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index0/level", O_RDONLY) = 3</sys/devices/system/cpu/cpu0/cache/index0/level> [pid 137] 1770646837.551252 close(3</sys/devices/system/cpu/cpu0/cache/index0/level>) = 0 [pid 137] 1770646837.551367 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index1/size", O_RDONLY) = 3</sys/devices/system/cpu/cpu0/cache/index1/size> [pid 137] 1770646837.551765 close(3</sys/devices/system/cpu/cpu0/cache/index1/size>) = 0 [pid 137] 1770646837.551889 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index1/level", O_RDONLY) = 3</sys/devices/system/cpu/cpu0/cache/index1/level> [pid 137] 1770646837.552238 close(3</sys/devices/system/cpu/cpu0/cache/index1/level>) = 0 [pid 137] 1770646837.552360 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index2/size", O_RDONLY) = 3</sys/devices/system/cpu/cpu0/cache/index2/size> [pid 137] 1770646837.552654 close(3</sys/devices/system/cpu/cpu0/cache/index2/size>) = 0 [pid 137] 1770646837.552790 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index2/level", O_RDONLY) = 3</sys/devices/system/cpu/cpu0/cache/index2/level> [pid 137] 1770646837.553103 close(3</sys/devices/system/cpu/cpu0/cache/index2/level>) = 0 [pid 137] 1770646837.553222 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index3/size", O_RDONLY) = 3</sys/devices/system/cpu/cpu0/cache/index3/size> [pid 137] 1770646837.553513 close(3</sys/devices/system/cpu/cpu0/cache/index3/size>) = 0 [pid 137] 1770646837.553629 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index3/level", O_RDONLY) = 3</sys/devices/system/cpu/cpu0/cache/index3/level> [pid 137] 1770646837.553912 close(3</sys/devices/system/cpu/cpu0/cache/index3/level>) = 0 [pid 137] 1770646837.554043 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index4/size", O_RDONLY) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.555098 openat(AT_FDCWD</workspace>, "/proc/meminfo", O_RDONLY) = 3</proc/meminfo> [pid 137] 1770646837.555372 close(3</proc/meminfo>) = 0 [pid 137] 1770646837.557397 openat(AT_FDCWD</workspace>, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 3</proc/137/maps> [pid 137] 1770646837.558138 close(3</proc/137/maps>) = 0 [pid 137] 1770646837.561204 fcntl(1</dev/pts/0<char 136:0>>, F_DUPFD_CLOEXEC, 0) = 3</dev/pts/0<char 136:0>> strace: Process 139 attached [pid 137] 1770646837.562720 openat(AT_FDCWD</workspace>, "/root/.terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.562981 openat(AT_FDCWD</workspace>, "/root/.terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.563093 openat(AT_FDCWD</workspace>, "/etc/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.563212 openat(AT_FDCWD</workspace>, "/etc/terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.563341 openat(AT_FDCWD</workspace>, "/lib/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.563475 openat(AT_FDCWD</workspace>, "/lib/terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.563648 openat(AT_FDCWD</workspace>, "/usr/share/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = 6</usr/share/terminfo/x/xterm> [pid 137] 1770646837.564125 close(6</usr/share/terminfo/x/xterm>) = 0 [pid 137] 1770646837.564249 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.564534 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.564700 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v4/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.564886 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.565197 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.565444 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.565722 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v4/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.565980 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.566227 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.566497 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.566767 openat(AT_FDCWD</workspace>, "/lib/glibc-hwcaps/x86-64-v4/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.567001 openat(AT_FDCWD</workspace>, "/lib/glibc-hwcaps/x86-64-v3/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.567277 openat(AT_FDCWD</workspace>, "/lib/glibc-hwcaps/x86-64-v2/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.567554 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.567779 openat(AT_FDCWD</workspace>, "/usr/lib/glibc-hwcaps/x86-64-v4/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.567974 openat(AT_FDCWD</workspace>, "/usr/lib/glibc-hwcaps/x86-64-v3/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.568192 openat(AT_FDCWD</workspace>, "/usr/lib/glibc-hwcaps/x86-64-v2/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.568404 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.568702 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.569027 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.569146 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.569274 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.569402 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.569532 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.569740 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.570007 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.570137 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.570305 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.570443 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.570583 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.570792 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.571078 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.571184 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.571303 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.571408 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.571549 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.571828 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.572099 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.572216 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.572358 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.572511 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.572662 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.572861 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.573188 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.573420 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.573612 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.573790 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.574000 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.574299 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.574644 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.574781 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.574940 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.575085 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.575207 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.575539 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.575823 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.575963 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.576089 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.576212 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.576351 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.576564 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.576850 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.576976 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.577100 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.577265 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.577408 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.577682 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.578019 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.578130 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.578248 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.578374 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.578507 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.578751 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.579075 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.579186 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.579302 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.579457 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.579541 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.579801 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.580128 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.580244 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.580403 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.580520 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.580683 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.580877 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.581203 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.581383 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.581544 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.581703 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.581872 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.582150 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.582529 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.582696 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.582857 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.583033 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.583186 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.583474 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.583801 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.583913 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.584040 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.584172 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.584351 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.584607 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.584878 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.584988 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.585114 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.585244 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.585410 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 137] 1770646837.585664 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.585977 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.586087 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.74", O_RDONLY|O_CLOEXEC) = 6</usr/lib/x86_64-linux-gnu/libicuuc.so.74.2> [pid 137] 1770646837.586809 close(6</usr/lib/x86_64-linux-gnu/libicuuc.so.74.2>) = 0 [pid 137] 1770646837.586925 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicudata.so.74", O_RDONLY|O_CLOEXEC) = 6</usr/lib/x86_64-linux-gnu/libicudata.so.74.2> [pid 137] 1770646837.587485 close(6</usr/lib/x86_64-linux-gnu/libicudata.so.74.2>) = 0 [pid 137] 1770646837.587587 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 6</usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33> [pid 137] 1770646837.588280 close(6</usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33>) = 0 [pid 137] 1770646837.588404 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 6</usr/lib/x86_64-linux-gnu/libgcc_s.so.1> [pid 137] 1770646837.588959 close(6</usr/lib/x86_64-linux-gnu/libgcc_s.so.1>) = 0 [pid 137] 1770646837.590298 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6</etc/ld.so.cache> [pid 137] 1770646837.590678 close(6</etc/ld.so.cache>) = 0 [pid 137] 1770646837.590820 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicui18n.so.74", O_RDONLY|O_CLOEXEC) = 6</usr/lib/x86_64-linux-gnu/libicui18n.so.74.2> [pid 137] 1770646837.591551 close(6</usr/lib/x86_64-linux-gnu/libicui18n.so.74.2>) = 0 [pid 137] 1770646837.592432 write(1</dev/pts/0<char 136:0>>, "\33[?1h\33=", 7) = 7 [pid 137] 1770646837.592944 write(3</dev/pts/0<char 136:0>>, "Hello, World\n", 13Hello, World ) = 13 [pid 139] 1770646837.593311 +++ exited with 0 +++ [pid 138] 1770646837.593343 +++ exited with 0 +++ 1770646837.594304 +++ exited with 0 +++
以下は、fd=3はstdout(1)の複製(CLOEXEC付き)を示しており、dotnetランタイムは起動時にstdoutのFD=1をF_DUPFD_CLOEXECでFD=3にdup(close-on-exec 付き)していることが分かります。
fcntl(1</dev/pts/0<char 136:0>>, F_DUPFD_CLOEXEC, 0) = 3</dev/pts/0<char 136:0>>
実際にdotnet/runtimeを見に行くと、src/coreclr/pal/src/file/file.cppのinit_std_handle関数にて、以下のようにF_DUPFD_CLOEXECでdupしていることが分かります。コメントに元のFILE*(= stdoutなど)をfcloseしても、元のfd(1) を閉じないためにdupして別fdを持つと書かれているので、まさにstrace結果と一致します。
static HANDLE init_std_handle(HANDLE * pStd, FILE *stream)
{
CPalThread *pThread = InternalGetCurrentThread();
PAL_ERROR palError = NO_ERROR;
IPalObject *pFileObject = NULL;
IPalObject *pRegisteredFile = NULL;
IDataLock *pDataLock = NULL;
CFileProcessLocalData *pLocalData = NULL;
CObjectAttributes oa;
HANDLE hFile = INVALID_HANDLE_VALUE;
int new_fd = -1;
/* duplicate the FILE *, so that we can fclose() in FILECloseHandle without
closing the original */
new_fd = fcntl(fileno(stream), F_DUPFD_CLOEXEC, 0); // dup, but with CLOEXEC
if(-1 == new_fd)
{
ERROR("dup() failed; errno is %d (%s)\n", errno, strerror(errno));
goto done;
}
System.Nativeでも意図的にF_DUPFD_CLOEXECでdupしており、dotnetランタイム全体でこの方法を採用していることが分かります。
intptr_t SystemNative_Dup(intptr_t oldfd) { int result; #if HAVE_F_DUPFD_CLOEXEC while ((result = fcntl(ToFileDescriptor(oldfd), F_DUPFD_CLOEXEC, 0)) < 0 && errno == EINTR); #elif HAVE_F_DUPFD while ((result = fcntl(ToFileDescriptor(oldfd), F_DUPFD, 0)) < 0 && errno == EINTR); // do CLOEXEC here too fcntl(result, F_SETFD, FD_CLOEXEC); #else // The main use cases for dup are setting up the classic Unix dance of setting up file descriptors in advance of performing a fork. Since WASI has no fork, these don't apply. // https://github.com/bytecodealliance/wasmtime/blob/b2fefe77148582a9b8013e34fe5808ada82b6efc/docs/WASI-rationale.md#why-no-dup result = oldfd; #endif return result; } int32_t SystemNative_Unlink(const char* path) { int32_t result; while ((result = unlink(path)) < 0 && errno == EINTR); return result; } #ifdef __NR_memfd_create #ifndef MFD_CLOEXEC #define MFD_CLOEXEC 0x0001U #endif #ifndef MFD_ALLOW_SEALING #define MFD_ALLOW_SEALING 0x0002U #endif #ifndef F_ADD_SEALS #define F_ADD_SEALS (1024 + 9) #endif #ifndef F_SEAL_WRITE #define F_SEAL_WRITE 0x0008 #endif #endif
C# JITのwriteシステムコール
C# JITコンパイラが動作しているときのwriteシステムコールを見てみます。以下は、dotnet runでJITコンパイルを行いながらHello Worldを出力したときのstrace結果です。制御コードがHello Worldの出力先はAOTと同様なのでおいておきましょう。
$ strace -e write ./bin/hello_csharp > /dev/null write(13, "*", 1) = 1 write(14, ".NET Finalizer", 14) = 14 write(13, "*", 1) = 1 write(16, ".NET Tiered Com", 15) = 15 write(15, "*", 1) = 1 write(0, "\33[?1h\33=", 7) = 7 write(24, "Hello, World\n", 13) = 13 write(4, "\1", 1) = 1 +++ exited with 0 +++
.NET Finalizerや.NET Tiered Comなどの文字列がwriteシステムコールで出力されているのが気になりますが、これは.NETがスレッドを作って名前を付けているのがwrite()として見えています。Linuxのスレッド名は15文字まで(終端NULを含めて16バイト制限)なので、次のような名前になります。
.NET Finalizer: 14字なのでそのまま.NET Tiered Compilation: 先頭15文字だけなので.NET Tiered Comに切り詰められる
.NET FinalizerはGCのファイナライザースレッドであり、ランタイムとしていつでもファイナライズできる状態を作るために、必ず起動します。.NET Tiered CompilationはJITコンパイラのTiered PGO最適化を担当するスレッドです。NativeAOTではJITがなく、またTiered PGO最適化は行われないため、これらスレッドは起動せず、writeシステムコールも発生しません。
この辺りはstraceでログを見ると、もう少し詳しくわかります。
$ strace -f -ttt -e trace=openat,close,fcntl,write -yy -s 200 ./bin/hello_csharp 1770651503.638424 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3</etc/ld.so.cache> 1770651503.638872 close(3</etc/ld.so.cache>) = 0 1770651503.639013 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3</usr/lib/x86_64-linux-gnu/libdl.so.2> 1770651503.639668 close(3</usr/lib/x86_64-linux-gnu/libdl.so.2>) = 0 1770651503.639779 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY|O_CLOEXEC) = 3</usr/lib/x86_64-linux-gnu/librt.so.1> 1770651503.640466 close(3</usr/lib/x86_64-linux-gnu/librt.so.1>) = 0 1770651503.640575 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3</usr/lib/x86_64-linux-gnu/libgcc_s.so.1> 1770651503.641275 close(3</usr/lib/x86_64-linux-gnu/libgcc_s.so.1>) = 0 1770651503.641383 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3</usr/lib/x86_64-linux-gnu/libpthread.so.0> 1770651503.642019 close(3</usr/lib/x86_64-linux-gnu/libpthread.so.0>) = 0 1770651503.642173 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3</usr/lib/x86_64-linux-gnu/libm.so.6> 1770651503.642672 close(3</usr/lib/x86_64-linux-gnu/libm.so.6>) = 0 1770651503.642775 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3</usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33> 1770651503.643511 close(3</usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33>) = 0 1770651503.643629 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3</usr/lib/x86_64-linux-gnu/libc.so.6> 1770651503.644728 close(3</usr/lib/x86_64-linux-gnu/libc.so.6>) = 0 1770651503.659843 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3</etc/ld.so.cache> 1770651503.660212 close(3</etc/ld.so.cache>) = 0 1770651503.660343 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v4/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.660624 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.660899 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.661116 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.661325 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v4/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.661507 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.661742 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.661973 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.662165 openat(AT_FDCWD</workspace>, "/lib/glibc-hwcaps/x86-64-v4/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.662366 openat(AT_FDCWD</workspace>, "/lib/glibc-hwcaps/x86-64-v3/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.662548 openat(AT_FDCWD</workspace>, "/lib/glibc-hwcaps/x86-64-v2/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.662759 openat(AT_FDCWD</workspace>, "/lib/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.662937 openat(AT_FDCWD</workspace>, "/usr/lib/glibc-hwcaps/x86-64-v4/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.663160 openat(AT_FDCWD</workspace>, "/usr/lib/glibc-hwcaps/x86-64-v3/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.663372 openat(AT_FDCWD</workspace>, "/usr/lib/glibc-hwcaps/x86-64-v2/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.663581 openat(AT_FDCWD</workspace>, "/usr/lib/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.663842 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3</etc/ld.so.cache> 1770651503.664154 close(3</etc/ld.so.cache>) = 0 1770651503.664265 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.664416 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.664611 openat(AT_FDCWD</workspace>, "/lib/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.664714 openat(AT_FDCWD</workspace>, "/usr/lib/liblttng-ust-tracepoint.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 1770651503.666744 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 3</workspace/bin/hello_csharp> 1770651503.667483 close(3</workspace/bin/hello_csharp>) = 0 1770651503.668334 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 3</workspace/bin/hello_csharp> 1770651503.668997 close(3</workspace/bin/hello_csharp>) = 0 1770651503.669736 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 3</workspace/bin/hello_csharp> 1770651503.670377 close(3</workspace/bin/hello_csharp>) = 0 1770651503.671028 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 3</workspace/bin/hello_csharp> 1770651503.671721 close(3</workspace/bin/hello_csharp>) = 0 1770651503.673748 openat(AT_FDCWD</workspace>, "/proc/self/mountinfo", O_RDONLY) = 3</proc/143/mountinfo> 1770651503.674430 close(3</proc/143/mountinfo>) = 0 1770651503.674546 openat(AT_FDCWD</workspace>, "/proc/self/cgroup", O_RDONLY) = 3</proc/143/cgroup> 1770651503.674831 close(3</proc/143/cgroup>) = 0 strace: Process 144 attached [pid 143] 1770651503.677794 fcntl(0</dev/pts/0<char 136:0>>, F_DUPFD_CLOEXEC, 0) = 5</dev/pts/0<char 136:0>> [pid 143] 1770651503.677926 fcntl(1</dev/pts/0<char 136:0>>, F_DUPFD_CLOEXEC, 0) = 6</dev/pts/0<char 136:0>> [pid 143] 1770651503.678068 fcntl(2</dev/pts/0<char 136:0>>, F_DUPFD_CLOEXEC, 0) = 7</dev/pts/0<char 136:0>> [pid 143] 1770651503.679079 openat(AT_FDCWD</workspace>, "/sys/fs/cgroup//cpu.max", O_RDONLY) = 8</sys/fs/cgroup/cpu.max> [pid 143] 1770651503.679363 close(8</sys/fs/cgroup/cpu.max>) = 0 [pid 143] 1770651503.683922 openat(AT_FDCWD</workspace>, "/dev/urandom", O_RDONLY|O_CLOEXEC) = 9</dev/urandom<char 1:9>> [pid 143] 1770651503.684119 openat(AT_FDCWD</workspace>, "/proc/143/stat", O_RDONLY) = 10</proc/143/stat> [pid 143] 1770651503.684495 close(10</proc/143/stat>) = 0 strace: Process 145 attached [pid 143] 1770651503.687465 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC) = 11</sys/devices/system/cpu/online> [pid 143] 1770651503.687648 close(11</sys/devices/system/cpu/online>) = 0 [pid 143] 1770651503.688005 openat(AT_FDCWD</workspace>, "/proc/self/mountinfo", O_RDONLY) = 11</proc/143/mountinfo> [pid 143] 1770651503.688585 close(11</proc/143/mountinfo>) = 0 [pid 143] 1770651503.688690 openat(AT_FDCWD</workspace>, "/proc/self/cgroup", O_RDONLY) = 11</proc/143/cgroup> [pid 143] 1770651503.688925 close(11</proc/143/cgroup>) = 0 [pid 143] 1770651503.691797 openat(AT_FDCWD</workspace>, "/proc/143/stat", O_RDONLY) = 11</proc/143/stat> [pid 143] 1770651503.692066 close(11</proc/143/stat>) = 0 [pid 143] 1770651503.692179 openat(AT_FDCWD</workspace>, "/proc/143/stat", O_RDONLY) = 11</proc/143/stat> [pid 143] 1770651503.692478 close(11</proc/143/stat>) = 0 strace: Process 146 attached [pid 146] 1770651503.694266 openat(AT_FDCWD</workspace>, "/tmp/clr-debug-pipe-143-4092879-in", O_RDONLYstrace: Process 147 attached <unfinished ...> [pid 143] 1770651503.695169 write(13<pipe:[654821]>, "*", 1) = 1 [pid 143] 1770651503.695294 openat(AT_FDCWD</workspace>, "/proc/143/stat", O_RDONLY <unfinished ...> [pid 147] 1770651503.695332 close(12<pipe:[654821]> <unfinished ...> [pid 143] 1770651503.695361 <... openat resumed>) = 14</proc/143/stat> [pid 147] 1770651503.695388 <... close resumed>) = 0 [pid 147] 1770651503.695429 close(13<pipe:[654821]>) = 0 [pid 143] 1770651503.695560 close(14</proc/143/stat>) = 0 [pid 143] 1770651503.695670 openat(AT_FDCWD</workspace>, "/dev/shm/sem.clrst0000008f00000000003e73cf", O_RDWR|O_NOFOLLOW|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.696489 openat(AT_FDCWD</workspace>, "/sys/fs/cgroup//memory.max", O_RDONLY) = 12</sys/fs/cgroup/memory.max> [pid 143] 1770651503.696794 close(12</sys/fs/cgroup/memory.max>) = 0 [pid 143] 1770651503.697425 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index0/size", O_RDONLY) = 12</sys/devices/system/cpu/cpu0/cache/index0/size> [pid 143] 1770651503.697800 close(12</sys/devices/system/cpu/cpu0/cache/index0/size>) = 0 [pid 143] 1770651503.697912 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index0/level", O_RDONLY) = 12</sys/devices/system/cpu/cpu0/cache/index0/level> [pid 143] 1770651503.698353 close(12</sys/devices/system/cpu/cpu0/cache/index0/level>) = 0 [pid 143] 1770651503.698491 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index1/size", O_RDONLY) = 12</sys/devices/system/cpu/cpu0/cache/index1/size> [pid 143] 1770651503.698789 close(12</sys/devices/system/cpu/cpu0/cache/index1/size>) = 0 [pid 143] 1770651503.698909 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index1/level", O_RDONLY) = 12</sys/devices/system/cpu/cpu0/cache/index1/level> [pid 143] 1770651503.699260 close(12</sys/devices/system/cpu/cpu0/cache/index1/level>) = 0 [pid 143] 1770651503.699371 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index2/size", O_RDONLY) = 12</sys/devices/system/cpu/cpu0/cache/index2/size> [pid 143] 1770651503.699689 close(12</sys/devices/system/cpu/cpu0/cache/index2/size>) = 0 [pid 143] 1770651503.699824 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index2/level", O_RDONLY) = 12</sys/devices/system/cpu/cpu0/cache/index2/level> [pid 143] 1770651503.700127 close(12</sys/devices/system/cpu/cpu0/cache/index2/level>) = 0 [pid 143] 1770651503.700243 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index3/size", O_RDONLY) = 12</sys/devices/system/cpu/cpu0/cache/index3/size> [pid 143] 1770651503.700559 close(12</sys/devices/system/cpu/cpu0/cache/index3/size>) = 0 [pid 143] 1770651503.700679 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index3/level", O_RDONLY) = 12</sys/devices/system/cpu/cpu0/cache/index3/level> [pid 143] 1770651503.700997 close(12</sys/devices/system/cpu/cpu0/cache/index3/level>) = 0 [pid 143] 1770651503.701105 openat(AT_FDCWD</workspace>, "/sys/devices/system/cpu/cpu0/cache/index4/size", O_RDONLY) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.702578 openat(AT_FDCWD</workspace>, "/proc/meminfo", O_RDONLY) = 12</proc/meminfo> [pid 143] 1770651503.702830 close(12</proc/meminfo>) = 0 [pid 143] 1770651503.703978 openat(AT_FDCWD</workspace>, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 12</proc/143/maps> [pid 143] 1770651503.704811 close(12</proc/143/maps>) = 0 [pid 143] 1770651503.704991 openat(AT_FDCWD</workspace>, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 12</proc/143/maps> [pid 143] 1770651503.706019 close(12</proc/143/maps>) = 0 strace: Process 148 attached [pid 143] 1770651503.707664 openat(AT_FDCWD</workspace>, "/proc/self/task/148/comm", O_RDWR) = 14</proc/143/task/148/comm> [pid 143] 1770651503.707795 write(14</proc/143/task/148/comm>, ".NET Finalizer", 14) = 14 [pid 143] 1770651503.707905 close(14</proc/143/task/148/comm>) = 0 [pid 143] 1770651503.708034 write(13<pipe:[656760]>, "*", 1) = 1 [pid 148] 1770651503.708204 close(12<pipe:[656760]>) = 0 [pid 148] 1770651503.708355 close(13<pipe:[656760]>) = 0 [pid 143] 1770651503.708851 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 12</workspace/bin/hello_csharp> [pid 143] 1770651503.709311 fcntl(12</workspace/bin/hello_csharp>, F_SETFD, FD_CLOEXEC) = 0 [pid 143] 1770651503.709529 fcntl(12</workspace/bin/hello_csharp>, F_DUPFD_CLOEXEC, 0) = 13</workspace/bin/hello_csharp> strace: Process 149 attached [pid 143] 1770651503.739900 openat(AT_FDCWD</workspace>, "/proc/self/task/149/comm", O_RDWR) = 16</proc/143/task/149/comm> [pid 143] 1770651503.740087 write(16</proc/143/task/149/comm>, ".NET Tiered Com", 15) = 15 [pid 143] 1770651503.740251 close(16</proc/143/task/149/comm>) = 0 [pid 143] 1770651503.740380 write(15<pipe:[654827]>, "*", 1) = 1 [pid 149] 1770651503.740714 close(14<pipe:[654827]>) = 0 [pid 149] 1770651503.740860 close(15<pipe:[654827]>) = 0 [pid 143] 1770651503.759910 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 14</workspace/bin/hello_csharp> [pid 143] 1770651503.760370 fcntl(14</workspace/bin/hello_csharp>, F_SETFD, FD_CLOEXEC) = 0 [pid 143] 1770651503.760596 fcntl(14</workspace/bin/hello_csharp>, F_DUPFD_CLOEXEC, 0) = 15</workspace/bin/hello_csharp> [pid 143] 1770651503.762460 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 16</workspace/bin/hello_csharp> [pid 143] 1770651503.762883 fcntl(16</workspace/bin/hello_csharp>, F_SETFD, FD_CLOEXEC) = 0 [pid 143] 1770651503.763136 fcntl(16</workspace/bin/hello_csharp>, F_DUPFD_CLOEXEC, 0) = 17</workspace/bin/hello_csharp> [pid 143] 1770651503.769514 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 18</workspace/bin/hello_csharp> [pid 143] 1770651503.770035 fcntl(18</workspace/bin/hello_csharp>, F_SETFD, FD_CLOEXEC) = 0 [pid 143] 1770651503.770286 fcntl(18</workspace/bin/hello_csharp>, F_DUPFD_CLOEXEC, 0) = 19</workspace/bin/hello_csharp> [pid 143] 1770651503.779217 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 20</workspace/bin/hello_csharp> [pid 143] 1770651503.779738 fcntl(20</workspace/bin/hello_csharp>, F_SETFD, FD_CLOEXEC) = 0 [pid 143] 1770651503.780015 fcntl(20</workspace/bin/hello_csharp>, F_DUPFD_CLOEXEC, 0) = 21</workspace/bin/hello_csharp> [pid 143] 1770651503.786433 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 22</workspace/bin/hello_csharp> [pid 143] 1770651503.786897 fcntl(22</workspace/bin/hello_csharp>, F_SETFD, FD_CLOEXEC) = 0 [pid 143] 1770651503.787267 fcntl(22</workspace/bin/hello_csharp>, F_DUPFD_CLOEXEC, 0) = 23</workspace/bin/hello_csharp> [pid 143] 1770651503.790962 fcntl(1</dev/pts/0<char 136:0>>, F_DUPFD_CLOEXEC, 0) = 24</dev/pts/0<char 136:0>> [pid 143] 1770651503.799356 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 25</workspace/bin/hello_csharp> [pid 143] 1770651503.799878 fcntl(25</workspace/bin/hello_csharp>, F_SETFD, FD_CLOEXEC) = 0 [pid 143] 1770651503.800107 fcntl(25</workspace/bin/hello_csharp>, F_DUPFD_CLOEXEC, 0) = 26</workspace/bin/hello_csharp> strace: Process 150 attached [pid 143] 1770651503.804328 openat(AT_FDCWD</workspace>, "/root/.terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.805457 openat(AT_FDCWD</workspace>, "/root/.terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.805598 openat(AT_FDCWD</workspace>, "/etc/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.805738 openat(AT_FDCWD</workspace>, "/etc/terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.805889 openat(AT_FDCWD</workspace>, "/lib/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.806050 openat(AT_FDCWD</workspace>, "/lib/terminfo/78/xterm", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.806268 openat(AT_FDCWD</workspace>, "/usr/share/terminfo/x/xterm", O_RDONLY|O_CLOEXEC) = 29</usr/share/terminfo/x/xterm> [pid 143] 1770651503.807384 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 30</workspace/bin/hello_csharp> [pid 143] 1770651503.807820 fcntl(30</workspace/bin/hello_csharp>, F_SETFD, FD_CLOEXEC) = 0 [pid 143] 1770651503.808029 fcntl(30</workspace/bin/hello_csharp>, F_DUPFD_CLOEXEC, 0) = 31</workspace/bin/hello_csharp> [pid 143] 1770651503.811379 openat(AT_FDCWD</workspace>, "/workspace/bin/hello_csharp", O_RDONLY) = 32</workspace/bin/hello_csharp> [pid 143] 1770651503.811898 fcntl(32</workspace/bin/hello_csharp>, F_SETFD, FD_CLOEXEC) = 0 [pid 143] 1770651503.812202 fcntl(32</workspace/bin/hello_csharp>, F_DUPFD_CLOEXEC, 0) = 33</workspace/bin/hello_csharp> [pid 143] 1770651503.819234 close(29</usr/share/terminfo/x/xterm>) = 0 [pid 143] 1770651503.821484 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.821744 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.821877 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.822027 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.822180 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.822296 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.90", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.822496 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.822790 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.822908 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.823061 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.823191 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.823323 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.89", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.823533 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.823862 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.823971 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.824115 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.824245 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.824350 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.88", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.824537 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.824873 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.824996 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.825210 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.825320 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.825400 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.87", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.825577 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.825921 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.826037 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.826181 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.826345 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.826517 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.86", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.826743 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.827013 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.827184 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.827308 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.827414 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.827546 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.85", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.827743 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.828080 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.828260 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.828410 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.828527 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.828655 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.84", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.828891 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.829219 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.829330 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.829457 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.829600 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.829721 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.83", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.829992 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.830294 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.830407 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.830538 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.830661 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.830761 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.82", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.830942 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.831250 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.831386 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.831513 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.831643 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.831818 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.81", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.832110 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.832416 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.832537 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.832691 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.832827 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.832943 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.80", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.833210 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.833542 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.833681 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.833836 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.833988 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.834114 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.79", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.834362 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.834618 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.834710 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.834952 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.835083 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.835207 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.78", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.835438 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.835794 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.835904 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.836046 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.836204 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.836366 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.77", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.836645 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.836936 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.837088 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.837257 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.837387 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.837559 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.76", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.837851 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.838170 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.838272 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.838409 openat(AT_FDCWD</workspace>, "/usr/lib/x86_64-linux-gnu/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.838562 openat(AT_FDCWD</workspace>, "/lib/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.838724 openat(AT_FDCWD</workspace>, "/usr/lib/libicuuc.so.75", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) [pid 143] 1770651503.838965 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.839287 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.839394 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicuuc.so.74", O_RDONLY|O_CLOEXEC) = 29</usr/lib/x86_64-linux-gnu/libicuuc.so.74.2> [pid 143] 1770651503.840074 close(29</usr/lib/x86_64-linux-gnu/libicuuc.so.74.2>) = 0 [pid 143] 1770651503.840189 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicudata.so.74", O_RDONLY|O_CLOEXEC) = 29</usr/lib/x86_64-linux-gnu/libicudata.so.74.2> [pid 143] 1770651503.840985 close(29</usr/lib/x86_64-linux-gnu/libicudata.so.74.2>) = 0 [pid 143] 1770651503.841575 openat(AT_FDCWD</workspace>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 29</etc/ld.so.cache> [pid 143] 1770651503.841994 close(29</etc/ld.so.cache>) = 0 [pid 143] 1770651503.842160 openat(AT_FDCWD</workspace>, "/lib/x86_64-linux-gnu/libicui18n.so.74", O_RDONLY|O_CLOEXEC) = 29</usr/lib/x86_64-linux-gnu/libicui18n.so.74.2> [pid 143] 1770651503.842904 close(29</usr/lib/x86_64-linux-gnu/libicui18n.so.74.2>) = 0 [pid 143] 1770651503.847992 write(1</dev/pts/0<char 136:0>>, "\33[?1h\33=", 7) = 7 [pid 143] 1770651503.848572 write(24</dev/pts/0<char 136:0>>, "Hello, World\n", 13Hello, World ) = 13 [pid 143] 1770651503.850376 write(4<pipe:[653798]>, "\1", 1) = 1 [pid 144] 1770651503.850599 close(4<pipe:[653798]>) = 0 [pid 146] 1770651503.851271 <... openat resumed>) = ? [pid 150] 1770651503.851382 +++ exited with 0 +++ [pid 149] 1770651503.851403 +++ exited with 0 +++ [pid 148] 1770651503.851425 +++ exited with 0 +++ [pid 147] 1770651503.851445 +++ exited with 0 +++ [pid 146] 1770651503.851456 +++ exited with 0 +++ [pid 145] 1770651503.851479 +++ exited with 0 +++ [pid 144] 1770651503.856690 +++ exited with 0 +++ 1770651503.856716 +++ exited with 0 +++
ログを見ているとclr-debug-pipeというパイプで診断情報をやり取りしていますが、これは診断用なのでDOTNET_EnableDiagnostics=0を指定すれば止められます。もし診断情報を止めた状態でstraceを取りたい場合は、以下のようにします。システムコール的には1つ減るだけですが、診断情報は不要なら止める判断もあるでしょう。
$ DOTNET_EnableDiagnostics=0 strace -f -ttt -e trace=openat,close,fcntl,write -yy -s 200 ./bin/hello_csharp
まとめ
C#のstraceを追いかけてみましたが、面白かったです。こうやってみていくとstraceのシステムコールが少ないからよい、とは一概には言えないと感じます。
C#のdotnetランタイム(CoreCLR)は、GC最適化やJITコンパイラのために環境情報を収集しており、これにより実行時のパフォーマンスを向上させています。仮にdotnetランタイムが/procや/sysを見に行くシステムコールをしていない場合、それはGC、JITコンパイラのTiered PGO最適化、その他ランタイム最適化のための情報を取得できないことを意味します。CやRustのように、メモリ管理や最適化を手動で行う言語と異なり、C#などのマネージドランタイムは、ランタイムがシステムの状態を把握して最適化を行うことに依存しています。したがって、必要なシステムコールはある程度存在するでしょう。
一方で、C# AOTのシステムコールは起動時のシステムコールを最小限に抑えつつ、必要な最適化情報を取得するよう設計されています。straceで追いかけていて無駄だなーと感じるポイントが少なく、だいぶん頑張っているなーという印象です。このあたりは、AOTとJITの違いがよく出ていますね。
参考
元記事
- strace で C / Go / Rust / Python / Node.js のシステムコールを覗いてみた。 | DevelopersIO
- HasutoSasaki/linux-system-playground | GitHub
本記事の再現をGitHub
他














