Harmonogram terminów

Harmonogram terminów to harmonogram we/wy dla jądra Linuksa , który został napisany w 2002 roku przez Jensa Axboe .

Przegląd

Głównym celem Harmonogramu terminów jest zagwarantowanie czasu rozpoczęcia obsługi zgłoszenia. Czyni to poprzez nałożenie ostatecznego terminu na wszystkie operacje we/wy, aby zapobiec głodzeniu żądań. Utrzymuje również dwie kolejki terminów , oprócz kolejek posortowanych (zarówno do odczytu, jak i do zapisu). Kolejki terminów są zasadniczo sortowane według ich terminu (czasu wygaśnięcia), podczas gdy posortowane kolejki są sortowane według numeru sektora.

Przed obsłużeniem kolejnego żądania terminarz decyduje, której kolejki użyć. Kolejki odczytu mają wyższy priorytet, ponieważ procesy zwykle blokują operacje odczytu. Następnie terminarz sprawdza, czy pierwsze żądanie w kolejce terminów wygasło. W przeciwnym razie program planujący obsługuje partię żądań z posortowanej kolejki. W obu przypadkach program planujący obsługuje również partię żądań następujących po wybranym żądaniu w posortowanej kolejce.

Domyślnie żądania odczytu mają czas wygaśnięcia 500 ms, żądania zapisu wygasają po 5 sekundach.

Wczesna wersja harmonogramu została opublikowana przez Jensa Axboe w styczniu 2002 roku.

Pomiary wykazały, że terminarz we/wy terminów przewyższa harmonogram we/wy CFQ w przypadku niektórych obciążeń wielowątkowych.

ustawienia sysfs

fifo_batch (liczba całkowita)

Deadline wykonuje operacje I/O (IOP) poprzez koncepcję „partii”, czyli zestawów operacji uporządkowanych według rosnącej liczby sektorów. To dostrojenie określa, jak duża musi być partia, zanim żądania zostaną umieszczone w kolejce na dysku (z wyjątkiem wygaśnięcia aktualnie tworzonej partii). Mniejsze partie mogą zmniejszyć opóźnienia , zapewniając szybsze wykonanie nowych żądań (zamiast ewentualnie czekać na nadejście większej liczby żądań), ale mogą obniżyć ogólną przepustowość, zwiększając ogólny ruch głowic dysków (ponieważ sekwencjonowanie odbywa się w ramach partii, a nie między nimi) . Dodatkowo, jeśli liczba IOP jest wystarczająco wysoka, partie i tak będą wykonywane w odpowiednim czasie.

odczyt_wygaśnięcia (liczba całkowita)

Czas „read_expire” to maksymalny czas w milisekundach, po którym odczyt jest uznawany za „wygasły”. Pomyśl o tym bardziej jak o dacie ważności na kartonie mleka. Mleko najlepiej spożyć przed upływem terminu ważności. To samo z harmonogramem terminów. NIE będzie próbował upewnić się, że wszystkie IO zostały wydane przed datą wygaśnięcia. Jeśli jednak zamówienie we/wy wygasło, wówczas ma wyższy priorytet…. z zastrzeżeniami.

Kolejka wygaśnięcia odczytu jest sprawdzana TYLKO wtedy, gdy harmonogram terminów ponownie ocenia kolejkę odczytu. W przypadku odczytów oznacza to za każdym razem, gdy wysyłany jest posortowany odczyt Z WYJĄTKIEM przypadku przesyłania strumieniowego io. Gdy program planujący przesyła strumieniowo dane we/wy z kolejki odczytu, odczyt, który utracił ważność, nie jest oceniany. Podczas ponownej oceny kolejki odczytu logika jest taka

sprawdź wygasłe odczyty (spójrz na początek kolejki FIFO [uporządkowany czas]) sprawdź, czy buforowany wskaźnik odczytu jest prawidłowy (więc nawet jeśli nie jest przesyłany strumieniowo, buforowany wskaźnik nadal ma pierwszeństwo, więc posortowana kolejka jest przeglądana od początku do końca w przemiataniu) pobierz pierwszy odczyt z posortowanej kolejki (zacznij ponownie od końcówki, aby wykonać kolejny cykl) Jeśli istnieją odczyty, których ważność wygasła, pierwszy jest pobierany z FIFO. Zauważ, że ten wygasły odczyt jest wtedy nowym ogniwem do uporządkowania sortowania odczytu. Przechowywany w pamięci podręcznej następny wskaźnik zostanie ustawiony tak, aby wskazywał następne we/wy z kolejki sortowania po tym, które wygasło…. Należy zauważyć, że algorytm nie tylko wykonuje WSZYSTKIE wygasłe io po przekroczeniu daty ważności. Pozwala to na utrzymanie rozsądnej wydajności poprzez grupowanie razem posortowanych odczytów „write_starved” przed ponownym sprawdzeniem wygasłej kolejki odczytu.

Tak więc maksymalna liczba operacji we/wy, które można wykonać między wygasłymi operacjami odczytu, wynosi 2 * „fifo_batch” * „writes_starved”. Jeden zestaw strumieniowania „fifo_batch” odczytuje po pierwszym wygasłym odczytie we/wy i jeśli ten strumień spowodował stan braku zapisu, prawdopodobnie inny zapis strumieniowy „fifo_batch”. Jest to gorszy przypadek, po którym przedawniona kolejka odczytu zostałaby ponownie oceniona. W najlepszym razie wygasła kolejka odczytu zostanie oceniona „write_starved” razy z rzędu, zanim zostanie pominięta, ponieważ kolejka zapisu byłaby używana.

write_expire (liczba całkowita)

Identyczne z read_expire, ale dla operacji zapisu (pogrupowanych w oddzielne partie od odczytów).

writes_starved (liczba całkowita)

Jak wspomniano wcześniej, ostateczny termin woli odczyty niż zapisy. W konsekwencji może to prowadzić do sytuacji, w których wykonywane operacje są niemal w całości odczytywane. Staje się to bardziej ważne, gdy parametr write_expire jest wydłużony lub ogólna przepustowość zbliża się do nasycenia. Zmniejszenie tego daje większą przepustowość do zapisu (względnie mówiąc) kosztem operacji odczytu. Jeśli jednak aplikacja jest obciążona dużymi odczytami (na przykład większość serwerów HTTP lub katalogowych) z sporadycznym zapisem, można zmniejszyć opóźnienie przeciętnych IOP, zwiększając to (tak, że trzeba wykonać więcej odczytów, zanim partia zapisu znajdzie się w kolejce na dysk).

front_merges (bool integer)

„Front merge” to operacja, w której program planujący wejścia/wyjścia, dążąc do skondensowania (lub „scalenia”) mniejszych żądań w mniejszą liczbę (większych) operacji, podejmie nową operację, a następnie zbada aktywną partię i spróbuje zlokalizować operacje, w których sektor początkowy jest taki sam lub bezpośrednio po sektorze początkowym innej operacji. „Scalanie wsteczne” jest odwrotne, gdy sektory końcowe w aktywnej partii są przeszukiwane w poszukiwaniu sektorów, które są albo takie same, albo bezpośrednio po sektorach początkowych bieżącej operacji. Scalanie przekierowuje operacje z bieżącej partii do aktywnej, zmniejszając „sprawiedliwość” w celu zwiększenia przepustowości.

Ze względu na sposób, w jaki pliki są zwykle układane, scalanie wsteczne jest znacznie bardziej powszechne niż scalanie przednie. W przypadku niektórych obciążeń możesz nawet wiedzieć, że marnowanie czasu na próby realizacji żądań scalania jest stratą czasu. Ustawienie front_merges na 0 wyłącza tę funkcję. Fuzje frontalne mogą nadal występować ze względu na zapisaną w pamięci podręcznej wskazówkę last_merge, ale ponieważ wiąże się to z zasadniczo zerowymi kosztami, nadal jest wykonywane. Ta wartość logiczna po prostu wyłącza wyszukiwanie przedniego sektora, gdy wywoływana jest funkcja scalania harmonogramu we/wy. Sumy scalania dysków są rejestrowane dla poszczególnych bloków w /proc/diskstats.

Inne programy planujące wejścia/wyjścia