polaris-arch 反馈 Tailscale inotify 监听开销的验证

polaris-arch 在 Debian 13 amd64 上记录 Tailscale v1.104.2 的 inotify 监听数量、事件组成和一次性 watcher 修复验证,并明确其他管理轮询也被优化,不能把 CPU 差异全部归因于该 patch。

作者原文

Additional confirmation on v1.104.2, on a Debian 13 amd64 router host running Tailscale as a systemd service. This was observed under ordinary management/status polling, rather than a tight synthetic read loop.

The mechanism matches the report here:

  • The stock daemon had 378 inotify directory watches, with kernel mask 0xfff (IN_ALL_EVENTS).
  • A five-second tracing window decoded 6,156 events: 1,590 OPEN, 2,975 ACCESS, and 1,591 CLOSE_NOWRITE. There were no write-class events in that captured window. /etc/systemd/system accounted for 2,680 events; reads of /etc/ld.so.cache and Fail2ban configuration also contributed.
  • A separate 20-second Go CPU profile showed directory-event handling, path processing and GC work. During that profile window the Tailscale interface had no observed traffic. This does not establish that all daemon CPU came from the watcher.
  • The v1.104.2 source calls gonotify.NewDirWatcher(ctx, events, dir) in feature/linuxdnsfight/linuxdnsfight.go, with gonotify v3.0.2. The kernel subscription remains broad despite the requested change-only mask.

We independently applied the same general fix as #21744: gonotify.NewInotify(ctx) plus one non-recursive AddWatch(dir, events), consuming Read() batches and filtering the target pathname. The deployed process now has one watch, mask 0x3ce, without IN_OPEN, IN_ACCESS, or IN_CLOSE_NOWRITE.

Regression checks cover:

  • exactly one directory watch and no read-only event bits;
  • target-file reads and unrelated files remaining quiet;
  • in-place writes, rename-over replacement, deletion and recreation still invoking the callback;
  • context cancellation stopping the watcher;
  • go test -race ./feature/linuxdnsfight ./net/dns passing.

For context only: two separate 40-second, untraced natural-traffic samples showed the tailscaled.service cgroup moving from about 1.86% to 0.051% of one logical CPU. Other management polling was optimized between these samples too, so this is not a controlled A/B measurement of the Tailscale patch and should not be interpreted as its isolated performance gain. The watch-count/mask and event-delivery observations are the direct evidence.

This confirms the issue is relevant to v1.104.2 on a Debian host outside the original RouterOS environment. The latest main source checked for this report still uses NewDirWatcher. Thanks for tracking the fix in #21744.