Dlaczego lsof na OS X jest tak absurdalnie wolny?

36

Nie mogę zrozumieć, dlaczego lsof na moim Macu (10.8.2, MacBook Pro) jest taki wolny.

Na moim komputerze Mac lsofzajmuje więcej niż minutę:

$ touch /tmp/testfile
$ time lsof /tmp/testfile

real   1m16.483s
user   0m0.029s
sys    1m15.969s

W typowym systemie Linux z systemem Ubuntu 12.04 lsoftrwa 20 ms:

$ touch /tmp/testfile
$ time lsof /tmp/testfile

real   0m0.023s
user   0m0.008s
sys    0m0.012s

Problem nie ustępuje, jeśli uruchomię lsof -n(aby uniknąć wyszukiwania DNS). Ponadto próbowałem sprawdzić, które wywołania systemowe są wykonywane przy lsofużyciu dtruss, i stwierdziłem, że wywołuje to proc_infodziesiątki tysięcy razy:

$ sudo dtruss lsof /tmp/testfile 2> /tmp/dump
$ cat /tmp/dump | sort | uniq -c | sort -nr | head
10000 proc_info(0x2, 0x1199, 0x8) = 1272 0
 6876 proc_info(0x2, 0x45, 0x8) = 1272 0
 2360 proc_info(0x2, 0x190D, 0x8) = 1272 0
 1294 proc_info(0x2, 0xFF, 0x8) = 1272 0
 1152 proc_info(0x2, 0x474, 0x8) = 1272 0
 1079 proc_info(0x2, 0x2F, 0x8) = 1272 0
  709 proc_info(0x2, 0xFE, 0x8) = 1272 0
  693 proc_info(0x2, 0x1F, 0x8) = 1272 0
  623 proc_info(0x2, 0x11A, 0x8) = 1272 0
  528 proc_info(0x2, 0xF7, 0x8) = 1272 0

Jakieś pomysły? Uruchomiłem te testy i uzyskałem te same wyniki przy użyciu zarówno wersji lsofdołączonej do OS X (4.85), jak i najnowszej wersji z ftp://sunsite.ualberta.ca/pub/Mirror/lsof/ (4.87).

(Z ciekawości powodem, dla którego frustruje mnie ta wydajność, jest to, że kiedy przeciągam obrazy do Evernote, działa ono lsofw trakcie kopiowania pliku, powodując zawieszenie się systemu przez całą minutę za każdym razem, gdy próbuję wstawić obraz w Evernote.)

Jason
źródło
1
Jeśli masz plik wyjściowy w konsoli zamiast pliku, to czy zawiesił się w określonym momencie? Jestem również na 10.8.2. Zajęło mi to 6 sekund i zauważyłem, że wisi za każdym razem w połowie wyświetlania listy otwartych plików AirServer. Zabiłem AirServer, a czas spadł do 1,76 sekundy. Być może w twoim systemie jest coś, co zajmuje dużo czasu?
Warren Pena
Ciekawy punkt danych, @WarrenPena. Jeśli uruchomię lsofbez argumentów (aby wyświetlić wszystkie pliki), to zawiesi się na minutę, a następnie wydrukuje wszystkie pliki. Ale, jak wspomniałem, nadal się zawiesza, jeśli spróbuję wymienić, kto ma otwarty pojedynczy plik w katalogu / tmp, więc problem nie jest konkretnym otwartym plikiem. Ponadto nie uruchamiam żadnego procesu AirServer.
Jason
2
Zajmuje mi to (tylko?) Sekundę. Możesz także spróbować sudo opensnoop -n lsof.
Lri
2
Zajmuje mi to 19 lat. Nie mam pojęcia, dlaczego ...
daviewales
Dobry pomysł, @LauriRanta. Próbowałem uruchomić sudo opensnoop -n lsofi lsof /tmp/testfilena dwóch kartach, i opensnoop zgłosił tylko, że trzy pliki zostały otwarte. Problemem nie może być zbyt duża liczba otwieranych plików, ale coś związanego z nadmierną liczbą proc_infowywołań.
Jason

Odpowiedzi:

10

Z mojego doświadczenia wynika, że ​​od Mac OS X 10.7 (Lion) do 10.11.5 (EI Capitan) lsofzawsze się zawiesza.

Aby rozwiązać problem, dołącz -nopcję.

lsof -n

Zgodnie z instrukcją lsof, -nopcja:

inhibits the conversion of network numbers to host names for network files.  
Inhibiting conversion may make  lsof  run faster.  It is also useful when host 
name lookup is not working properly

EDYCJA 2018-04-25: Jeśli nadal jest wolny, możesz spróbować

-O to bypass  the  strategy it uses to avoid being blocked by some kernel operations
-P to inhibits the conversion of port numbers to port names for network files
-l to inhibits  the  conversion of user ID numbers to login names

Ostatecznym sposobem, aby dowiedzieć się, dlaczego tak wolno, jest uruchomienie narzędzia „Instruments” (w prawym górnym rogu ikony Spotlight Search), aby wykonać „System Trace” na / usr / sbin / lsof, a następnie zobaczyć wywołania wykresów i sys.

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

osexp2003
źródło
2
Łał! Dodając -nwyciąć moje lsof +Dod 5.31 realdo 0.25 real. Ta opcja jest dla ... prawdziwego
wetjosh,
2
Nadal dla mnie absurdalnie powolny ...
Noldorin
Cześć @Noldorin, jesteś w tym samym systemie operacyjnym, co ten starszy wątek? Jeśli nie, nowe szczegółowe pytanie łączące się tutaj z Twoją konkretną konfiguracją i określonym czasem może być warte nowej odpowiedzi.
bmike
3

Myślę, że największą częścią problemu jest to, że macOS staje się coraz bardziej absurdalny z powodu wzdęć i niepotrzebnych warstw na warstwach marnotrawnych ram. Oznaczało to, że setki dodatkowych procesów i tysiące dodatkowych plików pozostały otwarte, zwiększając ilość pracy lsofdo wykonania o co najmniej rząd wielkości, a być może bardziej o dwa zamówienia.

lsof przeszedł z rozsądnej prędkości do okropnie wolnego między 10,6 a 10,13.

Tutaj, w obecnym systemie 10.13.4, widzę następujące z zaledwie 7 aplikacjami otwartymi i uruchomionymi (Terminal, Chrome, Kalendarz, Finder, Adium, IPGadget i Stickies). (Chrome ma 7 okien, z których każda może 10 kart).

# ps ax | wc -l
     401
# time lsof -lnP | wc -l
   10976

real    0m49.684s
user    0m0.250s
sys 0m40.172s

Podczas pracy oba procesory mają ponad 50% czasu systemowego

Dodawanie -Oczasami pomaga, szczególnie jeśli lsofostatnio nie było uruchomione, ale najlepsze, co widziałem, to około 10% oszczędności. Zwykle jest to niewielka ilość i prawdopodobnie nie jest warta ryzyka opisanego na stronie podręcznika:

# time lsof -lnPO | wc -l
   10994

real    0m47.482s
user    0m0.249s
sys 0m40.472s

dtrusstwierdzi, że proc_info()przy moim bieżącym obciążeniu procesu jest ponad 89 000 wywołań , a są one wysyłane do jądra, a jak timedonosi, ogromna większość czasu spędzana jest w jądrze. Nie wiem, dlaczego na otwarty plik przypada około 8 połączeń.

Niestety macOS / Darwin nie zawiera coraz bardziej przydatnego i wydajnego fstatpolecenia BSD .

Greg A. Woods
źródło
1

Nie mam doskonałej odpowiedzi na pytanie, dlaczego twój system zajmuje minutę dłużej niż mój najwolniejszy komputer Mac, aby zadzwonić proc_info30 tysięcy razy, ale twoje wyczucie czasu pokazuje, że zarówno Linux, jak i OS X znajdują się w zakresie 10 ms, aby użytkownik mógł uruchomić lsof. Czy potrafisz odtworzyć to wolne uruchamianie w trybie awaryjnym, aby wykluczyć inne obciążenia procesora?

Wypróbowałem trzy komputery Mac, a te z systemem 10.7.5 są o około sekundę szybsze niż mój Mac 10.8.2. Starsze systemy operacyjne są wolniejszymi procesorami Core 2 Duo i sądzę, że Mac i7 z nowszym systemem operacyjnym byłby tak szybki lub szybszy niż starszy system operacyjny i procesor, ale myliłbym się.

Wszystkie maszyny wykonują mniej więcej taką samą liczbę wywołań proc_info, a wszystkie maszyny mają ograniczony czas użytkownika na komendę - ale możesz mieć wolniejszy ogólny czas (i nie mam pojęcia, dlaczego twój jest tak wolniejszy niż mój Mountain Lion Prochowiec).

11-calowy Air (i7) 2011 z systemem Mountain Lion - SSD:

$ system_profiler SPSoftwareDataType
      System Version: OS X 10.8.2 (or something)
      Kernel Version: Darwin 12.3.0
      Secure Virtual Memory: Enabled
$ time lsof /tmp/testfile 

real    0m1.179s
user    0m0.012s
sys     0m1.158s
$ sudo dtruss lsof /tmp/testfile 2> /tmp/dump
$ cat /tmp/dump | sort | uniq -c | sort -nr | head
9310 proc_info(0x2, 0x68, 0x8)           = 1272 0
1220 proc_info(0x2, 0xCEB6, 0x8)                 = 1272 0
$ cat /tmp/dump | cut -c -9 | sort | uniq -c | sort -nr | head
30884 proc_info
 116 write(0x4
  87 read(0x5,
  60 sigaction
  60 setitimer
  35 stat64("/
  30 sigprocma
  30 sigaltsta
  21 close(0x3
  18 close(0x6 

15-calowy MacBook Pro z systemem Lion Server - HDD:

$ system_profiler SPSoftwareDataType
      System Version: Mac OS X Server 10.7.5 (11G63)
      Kernel Version: Darwin 11.4.2
$ time lsof /tmp/testfile

real    0m0.329s
user    0m0.005s
sys     0m0.324s

27-calowy iMac z systemem Lion - HDD:

$ system_profiler SPSoftwareDataType
      System Version: Mac OS X 10.7.5 (11G63b)
      Kernel Version: Darwin 11.4.2
$ time lsof /tmp/testfile

real    0m0.066s
user    0m0.002s
sys     0m0.065s
$ sudo dtruss lsof /tmp/testfile 2> /tmp/dump
$ cat /tmp/dump | cut -c -9 | sort | uniq -c | sort -nr | head
23034 proc_info
 188 write(0x4
 141 read(0x5,
  96 sigaction
  96 setitimer
  48 sigprocma
  48 sigaltsta
  31 stat64("/
  21 close(0x3
  18 close(0x6
bmike
źródło
1
+1. Korzystam z wersji 10.8.2 na MBP z końca 2010 roku (i7 + 8 GB), a podczas uruchamiania wielu aplikacji otrzymuję ~ 1,8 s.
Harv