umount -R
バインドマウントされたサブツリーをアンマウントするのに0.2秒かかるのはなぜですか?サブツリーのマウントには0.02秒、電波フラグの変更には0.00秒しかかかりません。
(現在のインストールセットをサブディレクトリに複製して変更し、スイッチを使用してそのディレクトリに切り替えようとしていますpivot_mount
が、私が観察した待ち時間は実際にはこの目的には許容できません。)
この演習では、/
サブマウントが共有マウントであると仮定します。 Linuxはデフォルトではこれを行いませんが、システムする。
# mkdir /mnt/a
# mount --bind /mnt/a /mnt/a --make-private
# time mount --rbind / /mnt/a
0.00user 0.00system 0:00.02elapsed 9%CPU (0avgtext+0avgdata 3020maxresident)k
0inputs+0outputs (0major+135minor)pagefaults 0swaps
# time mount --make-rprivate /mnt/a
0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 3184maxresident)k
0inputs+0outputs (0major+136minor)pagefaults 0swaps
# time umount -R /mnt/a
0.00user 0.00system 0:00.19elapsed 9%CPU (0avgtext+0avgdata 3392maxresident)k
0inputs+0outputs (0major+194minor)pagefaults 0swaps
追加テスト
strace -cw
ショーで実行
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
90.44 0.180113 5297 34 umount2
...
umount2()
したがって、最後のタスクには34個の個別の呼び出しが必要でしたが、他のタスクはMS_REC(再帰)フラグを使用するペアへの1回の呼び出しだけで構成されていることを指摘する以外はmount()
それほど理解するのが難しいです。ヘッダーデータと同様に、time
今は壁時計の時間です。 strace -c
システム時間(つまり、カーネルが費やしたCPU時間)を表示すると、合計0.009秒です。
それでもいくつかの興味深い点を指摘しています。代わりに使用すると、umount -l /mnt/a
合計時間が0.02秒に短縮されます。これは単一のumount2()
呼び出しを使用してサブツリーを分離し、バック/mnt/a
グラウンドでクリーンアップを実行します。
単一の呼び出しを見ると、単一のstrace -ttt -T -e trace=umount2 umount -R /mnt/a
呼び出し数は0.002秒から0.012秒の間で比較的均等に分布していますが、明確なパターンはなく、繰り返しはパターンが一貫していないようです。
umount -R
実行後perf record -a
、およびに複数のホットスポットperf report
が表示されます。そのプロセスはまったく出てこない。これは、カーネルまたはユーザースペースで費やされたCPU時間が無視できる理由を説明できます。gsd-housekeeping
gvfs-udisks2-volume-monitor
systemd
umount
time
umount
(テスト中に各プロセスのCPU使用率を集計するより包括的な方法がある人がいる場合は非常に興味深いでしょう。)
他のプロセスは、各インストールイベントに応じていくつかの処理を実行できます。
たとえば、0.4秒かかった実行では、systemdは私の4つのCPUのうちの1つを使用して0.13秒を担当しているようです。
# systemctl set-property init.scope CPUAccounting=yes
# systemctl show --property CPUUsageNSec init.scope; time umount -R /mnt/a ; systemctl show --property CPUUsageNSec init.scope
CPUUsageNSec=2403124481
real 0m0.408s
user 0m0.015s
sys 0m0.020s
CPUUsageNSec=2534058385
# echo $(( 2534058385 - 2403124481 ))
130933904
ただし、これはプライベートマウントネームスペースで実行すると同じ遅延が発生するため、正しい説明ではないようです。この場合、perf record -a
他のプロセスは表示されず、umount
プロセス(およびパフォーマンス自体)のみが表示されます。
# unshare -m
# time mount --rbind / /mnt/a
real 0m0.005s
user 0m0.003s
sys 0m0.002s
# time mount --make-rprivate /mnt/a
real 0m0.005s
user 0m0.003s
sys 0m0.002s
# systemctl show --property CPUUsageNSec init.scope; time umount -R /mnt/a ; systemctl show --property CPUUsageNSec init.scope
CPUUsageNSec=3637792026
real 0m0.381s
user 0m0.026s
sys 0m0.018s
CPUUsageNSec=3645973005
# echo $((3645973005-3637792026))
8180979
この場合、CPUは関連性がないようです。 2.3Ghzで実行できるCPUコアは4つですが、perf stat -a
全体的にCPU使用率は5%未満です。 (「CPUの使用は無視してください。-a
使用すると常にプール値を表示していると思います)。
# time perf stat -a umount -R /mnt/a
Performance counter stats for 'system wide':
2079.333650 cpu-clock (msec) # 3.998 CPUs utilized
635 context-switches # 0.305 K/sec
23 cpu-migrations # 0.011 K/sec
333 page-faults # 0.160 K/sec
198,278,822 cycles # 0.095 GHz
138,734,277 instructions # 0.70 insn per cycle
31,401,067 branches # 15.102 M/sec
934,327 branch-misses # 2.98% of all branches
0.520083596 seconds time elapsed
real 0m0.543s
user 0m0.038s
sys 0m0.043s
ただし、一部のプロセスはまだこのイベントに応答します。 umountはまだシステムログに78行のメッセージをトリガーします。
Feb 07 10:34:26 alan-laptop systemd[1]: proc-sys-fs-binfmt_misc.automount: Got automount request for /proc/sys/fs/binfmt_misc, triggered by 6040 (umount)
Feb 07 10:34:26 alan-laptop systemd[1]: proc-sys-fs-binfmt_misc.automount: Automount point already active?
Feb 07 10:34:26 alan-laptop systemd[1]: proc-sys-fs-binfmt_misc.automount: Got automount request for /proc/sys/fs/binfmt_misc, triggered by 6040 (umount)
Feb 07 10:34:26 alan-laptop systemd[1]: proc-sys-fs-binfmt_misc.automount: Automount point already active?
findmnt
たとえば、次回これを実行すると、ひどい再帰などの電波が発生するのを防ぎます--make-rprivate
。
findmnt -o TARGET,PROPAGATION
TARGET PROPAGATION
/ shared
├─/sys shared
│ ├─/sys/kernel/security shared
│ ├─/sys/fs/cgroup shared
│ │ ├─/sys/fs/cgroup/unified shared
│ │ ├─/sys/fs/cgroup/systemd shared
│ │ ├─/sys/fs/cgroup/net_cls,net_prio shared
│ │ ├─/sys/fs/cgroup/cpu,cpuacct shared
│ │ ├─/sys/fs/cgroup/devices shared
│ │ ├─/sys/fs/cgroup/freezer shared
│ │ ├─/sys/fs/cgroup/perf_event shared
│ │ ├─/sys/fs/cgroup/hugetlb shared
│ │ ├─/sys/fs/cgroup/memory shared
│ │ ├─/sys/fs/cgroup/blkio shared
│ │ ├─/sys/fs/cgroup/cpuset shared
│ │ └─/sys/fs/cgroup/pids shared
│ ├─/sys/fs/pstore shared
│ ├─/sys/fs/selinux shared
│ ├─/sys/kernel/debug shared
│ └─/sys/kernel/config shared
├─/proc shared
│ └─/proc/sys/fs/binfmt_misc shared
├─/dev shared
│ ├─/dev/shm shared
│ ├─/dev/pts shared
│ ├─/dev/mqueue shared
│ └─/dev/hugepages shared
├─/run shared
│ ├─/run/user/1000 shared
│ └─/run/user/42 shared
├─/usr shared
├─/tmp shared
├─/boot shared
└─/mnt/a private
└─/mnt/a private
├─/mnt/a/usr private
├─/mnt/a/sys private
│ ├─/mnt/a/sys/kernel/security private
│ ├─/mnt/a/sys/fs/cgroup private
│ │ ├─/mnt/a/sys/fs/cgroup/unified private
│ │ ├─/mnt/a/sys/fs/cgroup/systemd private
│ │ ├─/mnt/a/sys/fs/cgroup/net_cls,net_prio private
│ │ ├─/mnt/a/sys/fs/cgroup/cpu,cpuacct private
│ │ ├─/mnt/a/sys/fs/cgroup/devices private
│ │ ├─/mnt/a/sys/fs/cgroup/freezer private
│ │ ├─/mnt/a/sys/fs/cgroup/perf_event private
│ │ ├─/mnt/a/sys/fs/cgroup/hugetlb private
│ │ ├─/mnt/a/sys/fs/cgroup/memory private
│ │ ├─/mnt/a/sys/fs/cgroup/blkio private
│ │ ├─/mnt/a/sys/fs/cgroup/cpuset private
│ │ └─/mnt/a/sys/fs/cgroup/pids private
│ ├─/mnt/a/sys/fs/pstore private
│ ├─/mnt/a/sys/kernel/config private
│ ├─/mnt/a/sys/fs/selinux private
│ └─/mnt/a/sys/kernel/debug private
├─/mnt/a/dev private
│ ├─/mnt/a/dev/shm private
│ ├─/mnt/a/dev/pts private
│ ├─/mnt/a/dev/mqueue private
│ └─/mnt/a/dev/hugepages private
├─/mnt/a/run private
│ ├─/mnt/a/run/user/1000 private
│ └─/mnt/a/run/user/42 private
├─/mnt/a/proc private
│ └─/mnt/a/proc/sys/fs/binfmt_misc private
├─/mnt/a/tmp private
├─/mnt/a/boot private
└─/mnt/a/mnt/a private
ベストアンサー1
したがって、何かを待つのに時間を費やしていると思いますumount
(CPU時間が非常に少なくなったり出たりするためですuser
)sys
。なぜ待っているのか見てみましょう...
# perf trace -g -e sched:* umount2 -R /mnt/a
perf record
いくつかのスケジューラ追跡ポイントが表示され、最も目立つものですsched:sched_switch
。
Samples: 21 of event 'sched:sched_switch', Event count (approx.): 21
Children Self Trace output ▒
- 100.00% 100.00% umount:1888 [120] D ==> swapper/3:0 [120] ▒
0 ▒
__umount2 ▒
entry_SYSCALL_64_fastpath ▒
sys_umount ▒
do_umount ▒
namespace_unlock ▒
synchronize_sched ▒
__wait_rcu_gp ▒
wait_for_completion ▒
schedule_timeout ▒
schedule ▒
__schedule ▒
__schedule
__wait_rcu_gp()
RCU猶予期間を示します。 namespace_unlock()
inは、fs/namespace.c
以下を含む一種のグローバル同期ですsynchronize_rcu()
。みんな「現在実行中のRCUリード側の重要な部分が完了しました。」 「RCU猶予期間が数ミリ秒延長されました...この状況は、経験的に読取り指向の状況でRCUを使用する主な理由です」名前空間をマウントすることは「デフォルトの読み取り」と見なされます。
この「数ミリ秒」は、34の呼び出しごとに5ミリ秒の平均待ち時間を占めるようですumount2()
。