Przeczytałem oryginalny artykuł SIGCOMM '97 PostScript o HFSC, jest to bardzo technicznie, ale rozumiem podstawową koncepcję. Zamiast podawać liniową krzywą usługi (jak w przypadku prawie każdego innego algorytmu szeregowania), można określić wypukłą lub wklęsłą krzywą usługi, dzięki czemu można rozdzielić szerokość pasma i opóźnienie. Jednak mimo że w niniejszym dokumencie wspomniano o rodzaju stosowanych algorytmów szeregowania (w czasie rzeczywistym i współużytkowaniu łącza), zawsze wspomina się tylko o JEDNEJ krzywej na klasę planowania (odsprzężenie odbywa się poprzez określenie tej krzywej, do tego potrzebna jest tylko jedna krzywa ).
Teraz HFSC został zaimplementowany dla BSD (OpenBSD, FreeBSD itp.) Przy użyciu struktury planowania ALTQ i został zaimplementowany Linux przy użyciu struktury planowania TC (część iproute2). Obie implementacje dodały dwie dodatkowe krzywe serwisowe, których NIE było w oryginalnym dokumencie! Krzywa serwisowa w czasie rzeczywistym i krzywa serwisowa górnego limitu. Ponownie zauważmy, że w oryginalnym artykule wspomniano o dwóch algorytmach planowania (w czasie rzeczywistym i współdzieleniu łącza), ale w tym dokumencie oba działają z jedną krzywą usług. Nigdy nie było dwóch niezależnych krzywych usług dla jednej z nich, jak obecnie w BSD i Linux.
Co gorsza, niektóre wersje ALTQ wydają się dodawać dodatkowy priorytet kolejki do HSFC (w oryginale nie ma czegoś takiego jak priorytet). Znalazłem kilka poradników BSD wspominających o tym ustawieniu priorytetu (mimo że strona podręcznika w najnowszej wersji ALTQ nie zna takiego parametru dla HSFC, więc oficjalnie nawet nie istnieje).
Wszystko to sprawia, że planowanie HFSC jest jeszcze bardziej skomplikowane niż algorytm opisany w oryginalnej pracy. W Internecie dostępnych jest mnóstwo samouczków, które często są ze sobą sprzeczne, z których jeden twierdzi, że jest odwrotnie. Jest to prawdopodobnie główny powód, dla którego nikt tak naprawdę nie rozumie, jak naprawdę działa harmonogram HFSC. Zanim będę mógł zadawać pytania, potrzebujemy jakiejś konfiguracji przykładowej. Użyję bardzo prostego, jak widać na poniższym obrazku:
alt text http://f.imagehost.org/0177/hfsc-test-setup.png
Oto kilka pytań, na które nie mogę odpowiedzieć, ponieważ samouczki są ze sobą sprzeczne:
Po co w ogóle potrzebuję krzywej w czasie rzeczywistym? Zakładając, że A1, A2, B1, B2 mają 128 kbit / s współdzielenia łącza (żadna krzywa w czasie rzeczywistym dla żadnej z nich), to każdy z nich otrzyma 128 kbit / s, jeśli katalog główny ma 512 kbit / s do dystrybucji (i A i B mają oczywiście 256 kbit / s), prawda? Dlaczego miałbym dodatkowo nadawać A1 i B1 krzywą czasu rzeczywistego o prędkości 128 kbit / s? Do czego to by było dobre? Nadać tym dwóm wyższy priorytet? Według oryginalnej pracy mogę nadać im wyższy priorytet za pomocą krzywej , o to w końcu chodzi o HFSC. Nadając obu klasom krzywą [256 kbit / s 20 ms 128 kbit / s] oba mają automatycznie dwa razy wyższy priorytet niż A2 i B2 (wciąż uzyskują średnio tylko 128 kbit / s)
Czy przepustowość w czasie rzeczywistym liczy się do przepustowości współdzielenia łącza? Np. Jeśli A1 i B1 mają tylko przepustowość dzielenia łącza 64 kbit / s w czasie rzeczywistym, to znaczy, że gdy są one obsługiwane w czasie rzeczywistym 64 kbit / s, ich wymóg udostępniania łącza jest również spełniony (mogą uzyskać nadmierną przepustowość, ale zignorujmy to na sekundę) czy to oznacza, że uzyskują kolejne 64 kbit / s za pośrednictwem łącza? Czy więc każda klasa ma „wymaganie” przepustowości w czasie rzeczywistym plus współdzielenie łącza? Czy klasa ma wyższe wymagania niż krzywa w czasie rzeczywistym, jeżeli krzywa udziału łącza jest wyższa niż krzywa czasu rzeczywistego (obecny wymóg udziału łącza równa się określonemu wymaganiu udziału łącza minus przepustowość w czasie rzeczywistym już zapewniona do tego klasa)?
Czy górna krzywa graniczna ma zastosowanie również w czasie rzeczywistym, tylko do udostępniania linków, a może do obu? Niektóre samouczki mówią w jeden sposób, inne w inny sposób. Niektórzy twierdzą nawet, że górna granica to maksymalna przepustowość w czasie rzeczywistym + przepustowość udostępniania łącza? Jaka jest prawda?
Zakładając, że zarówno A2, jak i B2 mają prędkość 128 kbit / s, czy robi to jakąkolwiek różnicę, jeśli A1 i B1 mają tylko 128 kbit / s tylko udział łącza, lub 64 kbit / s w czasie rzeczywistym i 128 kbit / s udział łącza, a jeśli tak, , Co za różnica?
Jeśli używam osobnej krzywej czasu rzeczywistego do zwiększenia priorytetów klas, dlaczego w ogóle potrzebowałbym „krzywych”? Dlaczego w czasie rzeczywistym nie ma płaskiej wartości i podziału linków również płaskiej wartości? Dlaczego obie krzywe? Potrzeba krzywych jest wyraźna w oryginalnym artykule, ponieważ istnieje tylko jeden tego rodzaju atrybut na klasę. Ale teraz, mając trzy atrybuty (w czasie rzeczywistym, współdzielenie łącza i górny limit), po co nadal potrzebuję krzywych na każdym z nich? Dlaczego miałbym chcieć, aby kształt krzywych (nie średnia przepustowość, ale ich nachylenie) był inny dla ruchu w czasie rzeczywistym i współdzielenia łącza?
Zgodnie z niewielką dostępną dokumentacją wartości krzywych w czasie rzeczywistym są całkowicie ignorowane dla klas wewnętrznych (klasa A i B), są one stosowane tylko do klas liści (A1, A2, B1, B2). Jeśli to prawda, dlaczego konfiguracja próbki ALTQ HFSC (wyszukiwanie konfiguracji próbki 3.3 ) ustawia krzywe w czasie rzeczywistym dla klas wewnętrznych i twierdzi, że ustawiają one gwarantowaną szybkość tych klas wewnętrznych? Czy to nie jest całkowicie bezcelowe? (uwaga: pshare ustawia krzywą podziału łącza w ALTQ i oblicza krzywą w czasie rzeczywistym; możesz to zobaczyć w akapicie powyżej przykładowej konfiguracji).
Niektóre samouczki mówią, że suma wszystkich krzywych w czasie rzeczywistym nie może być większa niż 80% prędkości linii, inni twierdzą, że nie może przekraczać 70% prędkości linii. Który z nich ma rację, czy może oba są w błędzie?
Jeden samouczek powiedział, że zapomnisz o całej teorii. Bez względu na to, jak rzeczy naprawdę działają (harmonogramy i rozkład przepustowości), wyobraź sobie trzy krzywe zgodnie z następującym „uproszczonym modelem umysłu”: w czasie rzeczywistym jest gwarantowana przepustowość, którą ta klasa zawsze otrzyma. link-share to przepustowość, którą ta klasa chce w pełni usatysfakcjonować, ale satysfakcji nie można zagwarantować. W przypadku nadmiernej przepustowości klasa może nawet zaoferować większą przepustowość, niż jest to konieczne do spełnienia, ale nigdy nie może użyć więcej niż mówi górna granica. Aby to wszystko działało, suma wszystkich przepustowości w czasie rzeczywistym nie może przekraczać xx% prędkości linii (patrz pytanie powyżej, procent się zmienia). Pytanie: Czy jest to mniej lub bardziej dokładne lub całkowite nieporozumienie z HSFC?
A jeśli powyższe założenie jest naprawdę dokładne, gdzie jest ustalanie priorytetów w tym modelu? Np. Każda klasa może mieć przepustowość w czasie rzeczywistym (gwarantowana), przepustowość udostępniania łącza (nie gwarantowana) i być może górną granicę, ale niektóre klasy mają wyższy priorytet niż inne klasy. W takim przypadku nadal muszę jakoś ustalić priorytety, nawet wśród ruchu tych klas w czasie rzeczywistym. Czy ustaliłbym priorytet według nachylenia krzywych? A jeśli tak, to która krzywa? Krzywa w czasie rzeczywistym? Krzywa link-share? Krzywa górnego limitu? Wszyscy? Czy dałbym wszystkim z nich to samo nachylenie lub każde inne i jak znaleźć właściwe nachylenie?
Nadal nie straciłem nadziei, że na świecie istnieje przynajmniej ręka pełna ludzi, którzy naprawdę rozumieli HFSC i są w stanie dokładnie odpowiedzieć na wszystkie te pytania. A robienie tego bez sprzeczania się w odpowiedziach byłoby naprawdę fajne ;-)
Odpowiedzi:
Czytanie artykułów na temat HFSC i jego kuzynów nie jest dobrym sposobem na zrozumienie tego. Podstawowym celem artykułu HFSC jest dostarczenie dokładnego matematycznego dowodu jego twierdzeń, a nie wyjaśnienie, jak to działa. Rzeczywiście nie możesz zrozumieć, jak to działa z samego papieru HFSC, musisz również przeczytać dokumenty, do których się odwołuje. Jeśli masz jakiś problem z roszczeniem lub ich dowodami, dobrym pomysłem może być skontaktowanie się z autorami artykułów, w przeciwnym razie wątpię, czy będą zainteresowani Twoją opinią.
Napisałem tutorial dla HFSC . Przeczytaj to, jeśli moje wyjaśnienia poniżej nie są jasne.
Krzywa w czasie rzeczywistym i krzywa udostępniania łącza są oceniane na różne sposoby. Krzywa czasu rzeczywistego uwzględnia to, co klasa zrobiła w całej swojej historii. Musi to zrobić, aby zapewnić dokładną alokację przepustowości i opóźnienia. Minusem nie jest to, co większość ludzi intuicyjnie uważa za sprawiedliwe . W czasie rzeczywistym, jeśli klasa pożycza pasmo, gdy nikt inny tego nie chce, jest karana, gdy ktoś inny chce go później. Oznacza to, że w ramach gwarancji w czasie rzeczywistym klasa nie może uzyskać przepustowości przez długi czas, ponieważ korzystała z niej wcześniej, kiedy nikt jej nie chciał.
Udostępnianie łącza jest sprawiedliwe, ponieważ nie karze klasy za korzystanie z wolnej przepustowości. Oznacza to jednak, że nie może zapewnić silnych gwarancji na opóźnienia.
Oddzielenie udostępniania linków od zapewniania gwarancji opóźnień jest nową rzeczą, którą HFSC wprowadza do tabeli, a artykuł tak mówi w pierwszym zdaniu: W tym artykule badamy hierarchiczne modele zarządzania zasobami i algorytmy, które wspierają zarówno udostępnianie linków, jak i gwarantowane usługi w czasie rzeczywistym z oddzielonym opóźnieniem (priorytet) i alokacją przepustowości. Słowo kluczowe w tym zdaniu jest oddzielone. Przetłumaczone, oznacza, że oczekujesz, że powiesz, jak nieużywane pasmo ma być współdzielone z ls, i określ, jakie gwarancje w czasie rzeczywistym (aka gwarancji latencji) są potrzebne z rt. Oba są ortogonalne.
Tak. W dokumencie HFSC określają przepustowość w kategoriach tego, co klasa wysłała, ponieważ klasa się zaległa (tzn. Ma pakiety oczekujące na wysłanie). Jedyna różnica między rt a ls polega na tym, że rt patrzy do przodu za każdym razem, gdy klasa zostaje zaległa i oblicza najniższą gwarantowaną przepustowość z tego zestawu, podczas gdy współdzielenie łącza wygląda tylko od ostatniego zaległości klasy. Więc rt bierze pod uwagę więcej bajtów niż ls, ale każdy bajt, który bierze pod uwagę, jest również brany pod uwagę przez rt.
Górny limit nie powstrzymuje wysyłania pakietów w celu spełnienia warunków w czasie rzeczywistym. Pakiety wysłane w warunkach czasu rzeczywistego nadal liczą się do górnego limitu, a zatem mogą znacznie opóźnić wysłanie pakietu w warunkach współdzielenia łącza w przyszłości. To kolejna różnica między udostępnianiem linków w czasie rzeczywistym.
Tak, to robi różnicę. Jak wyjaśniono powyżej, jeśli używasz czasu rzeczywistego, opóźnienia są gwarantowane, ale łącze nie jest dzielone sprawiedliwie (w szczególności klasa może cierpieć z powodu braku przepustowości), a górne limity nie są egzekwowane. Jeśli użyjesz udostępniania linków, opóźnienie nie jest gwarantowane, ale udostępnianie linków jest sprawiedliwe, nie ma ryzyka głodu, a górny limit jest egzekwowany. Czas rzeczywisty jest zawsze sprawdzany przed udostępnieniem łącza, jednak nie jest to konieczne, aby udział łącza został zignorowany. To dlatego, że pakiety są liczone inaczej. Ponieważ historia jest rozpatrywana w czasie rzeczywistym, pakiet może nie być konieczny, aby spełnić gwarancję w czasie rzeczywistym (z powodu jednego zliczonego z historii), ale jest potrzebny do zaspokojenia udziału łącza, ponieważ ignoruje pakiet historyczny.
Krzywa dla kontroli w czasie rzeczywistym pozwala na wymianę wąskiego opóźnienia dla jednej konkretnej klasy ruchu (np. VOIP) dla słabego opóźnienia dla innych klas ruchu (np. E-mail). Podejmując decyzję, który pakiet wysłać w ramach ograniczenia czasu rzeczywistego, HFSC wybiera ten, który jako pierwszy dokończy wysyłanie. Jednak nie wykorzystuje przepustowości łącza do obliczenia tego, wykorzystuje przepustowość przydzieloną przez krzywą czasu rzeczywistego. Zatem jeśli mamy pakiety VOIP i e-mail o tej samej długości, a pakiet VOIP ma krzywą wypukłą, która daje 10-krotne zwiększenie w porównaniu z krzywą wklęsłą dla poczty e-mail, wówczas 10 pakietów VOIP zostanie wysłanych przed pierwszym pakietem e-mail. Ale dzieje się tak tylko w przypadku serii, która powinna zająć najwyżej tyle czasu, ile potrzeba na przesłanie kilku pakietów - tj. Milisekund. Następnie krzywa VOIP powinna się spłaszczyć, i VOIP nie uzyska przyszłego przyspieszenia, chyba że się na jakiś czas wycofuje (co, biorąc pod uwagę, że VOIP jest aplikacją o niskiej przepustowości, powinno). Efektem tego wszystkiego jest zapewnienie, że te pierwsze pakiety VOIP są wysyłane szybciej niż cokolwiek innego, co daje VOIP małe opóźnienie kosztem e-maili, które mają duże opóźnienia.
Jak powiedziałem wcześniej, ponieważ udział linków nie patrzy na historię, nie może dać gwarancji opóźnień. Solidna gwarancja jest potrzebna w przypadku ruchu w czasie rzeczywistym, takiego jak VOIP. Jednak przeciętnie wypukła wspólna krzywa wypukła nadal zapewnia opóźnienie w ruchu. To po prostu nie jest gwarantowane. Nie przeszkadza w większości rzeczy, takich jak ruch internetowy przez e-mail.
Dokumentacja jest poprawna. Hierarchia (a tym samym wewnętrzne węzły) nie ma żadnego wpływu na obliczenia w czasie rzeczywistym. Nie mogę ci powiedzieć, dlaczego ALTQ najwyraźniej tak uważa.
Oba są w błędzie. Jeśli 70% lub 80% twojego ruchu ma wymagania dotyczące opóźnień, które muszą być określone w czasie rzeczywistym, w rzeczywistości prawie na pewno nie możesz ich zaspokoić za pomocą łącza, którego używasz. Potrzebujesz szybszego linku.
Jedynym sposobem, w jaki ktoś mógłby pomyśleć o określeniu 80% ruchu, powinien być czas rzeczywisty, jeśli kroczyłby w czasie rzeczywistym jako priorytet. Tak, aby zapewnić gwarancje opóźnień, zwiększasz priorytet niektórych pakietów. Ale powinno to trwać tylko przez milisekundy. To wszystko, z czym link może sobie poradzić i nadal zapewnia gwarancje opóźnień.
Bardzo mały ruch wymaga gwarancji opóźnień. VOIP to jeden, NTP inny. Resztę należy zrobić z udostępnianiem linków. Jeśli chcesz, aby sieć była szybka, robisz ją szybko, przydzielając jej większość pojemności łączy. Ten udział jest gwarantowany w długim okresie. Jeśli chcesz, aby miało to małe opóźnienie (średnio), nadaj mu wypukłą krzywą w ramach udostępniania linków.
Jest to dobry opis górnej granicy. Chociaż opis udostępniania linków jest ściśle dokładny, wprowadza w błąd. Chociaż jego prawdziwy udział łącza nie daje twardych gwarancji opóźnień, tak jak w czasie rzeczywistym, lepiej radzi sobie z przydzielaniem klasie przepustowości przydzielonej alokacji niż jej konkurenci, tacy jak CBQ i HTB. Mówiąc więc, udział linku „nie zapewnia gwarancji” utrzymuje go na poziomie wyższym niż jakikolwiek inny planista może zapewnić.
Opis w czasie rzeczywistym może być zarówno dokładny, ale tak mylący, że nazwałbym to błędnym. Jak sama nazwa wskazuje, celem czasu rzeczywistego nie jest zapewnienie gwarantowanej przepustowości. Ma to zapewnić gwarantowane opóźnienie - tzn. Pakiet jest wysyłany TERAZ, a nie jakiś losowy czas później, w zależności od sposobu użycia łącza. Większość ruchu nie wymaga gwarantowanego opóźnienia.
To powiedziawszy, czas rzeczywisty również nie daje idealnych gwarancji na opóźnienia. Mógłby, gdyby link nie był również zarządzany przez udostępnianie linków, ale większość użytkowników chce dodatkowej elastyczności posiadania obu i nie przychodzi za darmo. Czas rzeczywisty może przekroczyć termin opóźnienia do momentu wysłania jednego pakietu MTU. (Jeśli tak się stanie, dzieje się tak dlatego, że był to udział MTU w pakiecie linków, jednocześnie utrzymując łącze w stanie bezczynności na wypadek, gdyby otrzymał pakiet z krótkim terminem, który musiał zostać wysłany natychmiast. To kolejna różnica między udziałem linków i w czasie rzeczywistym. Aby zapewnić swoje gwarancje, w czasie rzeczywistym celowo można utrzymywać bezczynność linii, nawet jeśli istnieją pakiety do wysłania, co zapewnia mniej niż 100% wykorzystania łącza. Udział łącza zawsze wykorzystuje 100% dostępnej pojemności łączy. W przeciwieństwie do czasu rzeczywistego ,
Można powiedzieć, że czas rzeczywisty oferuje twarde gwarancje opóźnień, ponieważ opóźnienie jest ograniczone. Jeśli więc próbujesz zaoferować gwarancję opóźnienia 20 ms dla łącza 1 Mb / s, a udział łącza wysyła pakiety wielkości MTU (1500 bajtów), wiesz, że jeden z tych pakietów zajmie 12 ms. Zatem jeśli powiesz w czasie rzeczywistym, że chcesz opóźnienia 8 ms, nadal możesz dotrzymać terminu 20 ms - z absolutną gwarancją.
Nie ma modelu ustalania priorytetów. Poważnie. Jeśli chcesz nadać ruchowi bezwzględne priorytety, użyj pfifo. Po to jest. Ale także uwaga, że jeśli dać ruchu w sieci absolutny priorytet nad ruchu pocztowym, to znaczy pozwolić ruch internetowy nasycić link, a zatem żadne pakiety pocztowe docierają, w ogóle . Wszystkie połączenia e-mail następnie umierają.
W rzeczywistości nikt nie chce tego rodzaju ustalania priorytetów. Chcą tego, co zapewnia HFSC. Jeśli faktycznie masz ruch w czasie rzeczywistym, zapewnia to HFSC. Ale to będzie wszystko. Co do reszty, HFSC pozwala powiedzieć „na przeciążonym łączu, przydziel 90% do sieci i pozwól, aby e-mail spływał z prędkością 10%, i och, szybko wyślij dziwny pakiet DNS, ale nie pozwól komuś DOS mi go dostarczyć”.
źródło
Można zdefiniować krzywe o różnych nazwach:
Kiedy tworzysz definicję w HFSC tylko z szybkościami, automatycznie ustawia „dmax” na 0. Co w zasadzie oznacza, że nie uwzględnia opóźnienia. Dobra konfiguracja HFSC powinna obejmować zarówno szerokość pasma, jak i granice opóźnienia, których chcesz użyć dla swojej klasy, w przeciwnym razie algorytm nie będzie w stanie dokładnie określić, jaki priorytet powinna uzyskać klasa.
Ilekroć nadasz pakietom priorytet, inne pakiety będą musiały zostać zmniejszone. W oparciu o wartości „dmax” i „szybkość” wszystkie klasy zostaną zmultipleksowane przy użyciu wirtualnych timerów. Więcej informacji znajduje się w tc-hfsc (7).
Jeśli przepływ nie przekracza granic definicji klasy podziału łącza, wówczas krzywa w czasie rzeczywistym nie jest nigdy używana. Definiowanie krzywej w czasie rzeczywistym pozwala w tym przypadku np .: zagwarantować określony „dmax”.
Jeśli twoje definicje udostępniania linków są bezbłędne, nie potrzebujesz krzywych w czasie rzeczywistym. Możesz po prostu zdefiniować krzywe serwisowe (sc), ale to sprawi, że Twoja konfiguracja będzie trudniejsza.
Krzywa górnego limitu w twojej klasie jest stosowana tylko do podziału łącza, kiedy definiujesz krzywą ograniczenia górnego MUSISZ zdefiniować krzywą podziału łącza. Jednak nadal stosowana jest krzywa górnego limitu klas nadrzędnych.
Istnieje niewielka różnica, jeśli np. A2 = 0 kb / s i B2 = 256 kb / s. Wtedy czas wirtualny dla A2 będzie na maksimum. Ilekroć pakiety są klasyfikowane w A2, będą natychmiast przetwarzane. Jednak krzywa B2 w czasie rzeczywistym nadal zapewnia transmisję co najmniej 64 kbit / s
Krzywe w czasie rzeczywistym nie dzielą ruchu między liśćmi sąsiadów, podobnie jak krzywe udostępniania łącza.
Prawdą jest, że krzywe w czasie rzeczywistym są ignorowane dla klas wewnętrznych, są stosowane tylko do klas liści. Jednak krzywe w czasie rzeczywistym zdefiniowane dla tych klas wewnętrznych są uwzględniane przy obliczeniach dotyczących klas liści.
Chodzi im o to, że: nie można nadać priorytetu całemu ruchowi ... Za każdym razem, gdy nadasz priorytet pakietom, inne pakiety będą musiały zostać zmniejszone. W przypadku nadmiernej gwarancji algorytm staje się bezcelowy. Zdefiniuj klasy, które mają priorytet i zdefiniuj klasy, które mogą ucierpieć.
To jest poprawne.
Różnica między np. HFSC i HTB polega na tym, że HFSC pozwoli ci dokładnie określić, jaki priorytet ma mieć. Robisz to, definiując minimalne i maksymalne granice za pomocą wartości „dmax”.
źródło
Wreszcie przewodnik, który wydaje się wyjaśniać większość niespójności, a także, w jaki sposób obecna implementacja różni się od oryginalnej pracy:
http://manpages.ubuntu.com/manpages/precise/man7/tc-hfsc.7.html
Według tego przewodnika wiele innych przewodników i postów na forum na temat HFSC jest całkowicie nonsensownych; pokazuje po prostu, jak skomplikowany jest HFSC, ponieważ wiele osób, które wydają się być ekspertami i udają, że w pełni rozumieją HFSC, w rzeczywistości mają jedynie częściową wiedzę i składają fałszywe oświadczenia w oparciu o niezrozumienie koncepcji i tego, jak wszystkie te ustawienia grają razem.
Myślę, że w końcu zrezygnuję z HFSC. Jeśli potrafisz poprawnie skonfigurować HFSC, może to być najlepsza QoS, jaką możesz uzyskać, ale szanse, że całkowicie zepsujesz, są znacznie większe niż szanse na sukces.
źródło
Jeśli nie jesteś w stanie zdobyć oryginalnych autorów, spróbowałbym następnej:
Spróbuj także sprawdzić inne nowsze artykuły, które cytują ten. Mogą istnieć nowsze artykuły, które są kontynuacją badań w tej dziedzinie i mogą zawierać więcej informacji na temat zadawanych pytań.
źródło