eGospodarka.pl

eGospodarka.plGrupypl.comp.programming › Integracja bibliotek event-based
Ilość wypowiedzi w tym wątku: 16

  • 1. Data: 2020-06-08 23:58:58
    Temat: Integracja bibliotek event-based
    Od: Maciej Sobczak <s...@g...com>

    To jest wyciągnięty pod-wątek z wątku o serwerze HTTP.

    Powiedzmy, że program używa 3 bibliotek event-based. Żeby nie trzeba było mieć wątków
    i innych muteksów.
    W jednej trzeba zrobić server->next(), w drugiej agent.do_some_work() a w trzeciej
    worker::process(). Powiedzmy, że te funkcje od razu wychodzą jak nie mają nic do
    roboty, a jak mają, to szybko robią (bo na nic nie czekają) i też wychodzą.

    Co należy zrobić, żeby użyć ich razem w jednym programie?
    Takie coś:

    while (true)
    {
    server->next();
    agent.do_some_work();
    worker::process();
    }

    jest złe, bo kręci się w kółko i zużywa prąd nawet (zwłaszcza) wtedy, gdy nie ma nic
    do zrobienia. Nie chcemy tak.

    Jakie jest poprawne rozwiązanie dla integracji tych 3 bibliotek?

    --
    Maciej Sobczak * http://www.inspirel.com


  • 2. Data: 2020-06-09 00:32:25
    Temat: Re: Integracja bibliotek event-based
    Od: heby <h...@p...onet.pl>

    On 08/06/2020 23:58, Maciej Sobczak wrote:
    > Jakie jest poprawne rozwiązanie dla integracji tych 3 bibliotek?

    To zależy co robią.

    Jeśli ich zadaniem jest coś policzyć i zniknąć to masz dobrze.

    Jesli ich zadaniem jest coś policzyć tylko jak będzie potrzeba to od
    tego masz wsparcie OSa i jego pętlę komunikatów. Być może też jakieś
    wątki pod spodem, ale klient o nich nie wie, bibliteka często też nie
    wie. Ogólnie cooperative multitasking bazuje na tym że robisz jak
    przychodzi jakiś event. Systemowy zazwyczaj. Można poprosić aby
    przychodził non-stop jeden za drugim. Każdemu w/g potrzeb.

    Oba podejścia są od dziesiątek lat katowane choćby w Qt i masz tam jakiś
    obraz tego jak zrobić 1) (onIdle()) i jak zrobić 2) (push event). Mogą z
    sobą działać bardzo gładko i elegancko.

    Mam duże (w sensie wielopoziomoe) algorytmy rozbite na pojednycze kroki
    i popychane z onIdle z głownej pętli. Spadek wydajności jest, ale
    pomijalny, choć oczywiscie wszystko zależy od tego jak realizowany jest
    yeld(). To podejście jest nie dla sztuki, tylko warunki brzegowe
    utrudniają użycie watków. Na szczęscie nie ma najmniejszego problemu, w
    dodatku mogę takie coroutines wrzucić *dynamicznie* do wątku i z niego
    wyjąć kiedy tylko chcę, na przykład w połowie pracy.

    Teoretycznie każdy algorytm można przerobić na coroutine za pomocą
    boost::context ale koszt może być wysoki, to wszak przełącza kontekst,
    prawie jak wątek. W przypadku ręcznym najczęściej pasuje jakiś wzorzec
    typu maszyn stanów. Do ogarnięcia w typowych przypadkach, rekurencja
    jest bardziej bolesna, ale niewiele.


  • 3. Data: 2020-06-09 00:38:22
    Temat: Re: Integracja bibliotek event-based
    Od: heby <h...@p...onet.pl>

    On 09/06/2020 00:32, heby wrote:
    > wie. Ogólnie cooperative multitasking bazuje na tym że robisz jak
    > przychodzi jakiś event. Systemowy zazwyczaj. Można poprosić aby
    > przychodził non-stop jeden za drugim. Każdemu w/g potrzeb.

    z grubsza to jest tak:

    std::vector< jobs > jobs;

    Scheduler::onIdle()
    {
    if ( somethingToDo( jobs) )
    {
    sheduleNextOnIdleEvent();
    doSomething( shuffle( jobs ) );
    }
    // stop onIdle callbacks by doing nothing
    }

    I to samoczynnie się zatrzyma jak coroutines zakończą pracę.

    Mechanizm onIdle jest systemowy i jest drugorzędne jak działa.


  • 4. Data: 2020-06-09 09:46:40
    Temat: Re: Integracja bibliotek event-based
    Od: Mateusz Viste <m...@x...invalid>

    2020-06-08 o 14:58 -0700, Maciej Sobczak napisał:
    > while (true)
    > {
    > server->next();
    > agent.do_some_work();
    > worker::process();
    > }
    >
    > jest złe, bo kręci się w kółko i zużywa prąd nawet (zwłaszcza) wtedy,
    > gdy nie ma nic do zrobienia. Nie chcemy tak.

    Zdecydowanie nie chcemy. 30 lat temu na 386 to jeszcze uchodziło, bo
    program był jeden na raz a i prądożernośćią CPU nikt się nie
    przejmował. Dziś trochę wstyd, kiedy po uruchomieniu programu
    wentylator w laptopie zaczyna się kręcić. :)

    > Jakie jest poprawne rozwiązanie dla integracji tych 3 bibliotek?

    To zależy co one mają robić. Skoro mowa o serwerze, to domniemywam że
    punktem wejścia jest pojawienie się jakiegoś nowego stanu na
    sockecie. Jeśli tak, to sprawa prosta:

    for (;;) {
    select(sockfd+1, &socksetr, &socksetw, &socksete, &timeout);
    /* TODO obsługa SIGINT */
    /* TODO obsługa timeout */
    server->next();
    agent.do_some_work();
    worker::process();
    }


    Mateusz


  • 5. Data: 2020-06-09 22:58:58
    Temat: Re: Integracja bibliotek event-based
    Od: Maciej Sobczak <s...@g...com>

    W dniu wtorek, 9 czerwca 2020 09:46:44 UTC+2 użytkownik Mateusz Viste napisał:
    > > Jakie jest poprawne rozwiązanie dla integracji tych 3 bibliotek?
    >
    > To zależy co one mają robić.

    Każda robi coś innego.

    > Skoro mowa o serwerze, to domniemywam że
    > punktem wejścia jest pojawienie się jakiegoś nowego stanu na
    > sockecie.

    Ale my nie widzimy tych socketów, bo one są ukryte w tych bibliotekach. Jedna
    obsługuje HTTP, druga asynchroniczną bazę danych a trzecia odbiera tweety z Twittera.
    Każda z nich ma zapewne jakieś sockety, ale nie wiemy o tym.

    > Jeśli tak, to sprawa prosta:
    >
    > for (;;) {
    > select(sockfd+1, &socksetr, &socksetw, &socksete, &timeout);

    No więc wcale nie jest prosta, bo nie możemy zrobić tego selecta.

    Możemy próbować to, co pokazał heby z onIdle i podobnymi, ale co jak mamy nie jedną,
    ale właśnie 3 biblioteki? Żadna z nich nie może zablokować żadnej z wywołanych
    funkcji (to jest błąd u heby[*]), bo to zatrzyma pętlę, a być może pozostałe
    biblioteki mają wtedy coś do zrobienia.

    Więc gramy dalej. :-)

    [*] Kurdę, łatwiej się odmienia "u Sebastiana", niż "u heby".

    --
    Maciej Sobczak * http://www.inspirel.com


  • 6. Data: 2020-06-09 23:18:35
    Temat: Re: Integracja bibliotek event-based
    Od: heby <h...@p...onet.pl>

    On 09/06/2020 22:58, Maciej Sobczak wrote:
    > Żadna z nich nie może zablokować żadnej z wywołanych funkcji (to jest błąd u
    heby[*])

    To jest kontrakt. Jesli go złamiesz to masz problem. Więc to nie jest
    błąd, bo jeśli tak to taki sam błąd możesz zrobić w preemptive blokując
    muteks i wyrzucając klucz do kibla.

    > [*] Kurdę, łatwiej się odmienia "u Sebastiana", niż "u heby".

    To odmieniaj. Eternal Speptember randomicznie podpisuje mi maile, raz
    heby z adresu raz pełnym podpisem. Ch... wie dlaczego. Pewno nie mają
    unit testów ...


  • 7. Data: 2020-06-10 10:56:25
    Temat: Re: Integracja bibliotek event-based
    Od: Mateusz Viste <m...@x...invalid>

    2020-06-09 o 13:58 -0700, Maciej Sobczak napisał:
    > Ale my nie widzimy tych socketów, bo one są ukryte w tych
    > bibliotekach.

    To jakieś strasznie opakowane te biblioteki, że nie pozwalają dobrać
    się do źródłowego socketa.

    > Jedna obsługuje HTTP, druga asynchroniczną bazę danych
    > a trzecia odbiera tweety z Twittera. Każda z nich ma zapewne jakieś
    > sockety, ale nie wiemy o tym.

    A co mówi dokumentacja tych bibliotek? Chyba ich autorzy nie zakładają,
    że ktoś będzie busy loop tworzył czekając na tweeta?

    Jeśli chodzi o asynchroniczną bazę danych, to klient wysłał jakieś
    polecenia i czeka na odpowiedź, jednocześnie robiąc coś innego. W
    takiej sytuacji wystarczy odczekać chwilę (np. pustym selectem) i
    sprawdzać jakimś db_isBusy() czy baza skończyła co miała robić. W
    zależności od założeń projektowych tę samą metodę można zastosować dla
    tweetów i "obsługi http" (cokolwiek by miało to znaczyć).

    Słowem - to samo co sugerowałem wcześniej, tyle że z pustym sockset w
    select() i sztywnym timeout, stosownie dobranym by niczego nie
    zakorkować. Ale to tylko jeśli biblioteki faktycznie nie udostępniają
    jakichkolwiek mechanizmów sygnalizacji swoich potrzeb.

    Mateusz


  • 8. Data: 2020-06-10 23:19:42
    Temat: Re: Integracja bibliotek event-based
    Od: Maciej Sobczak <s...@g...com>

    > > Ale my nie widzimy tych socketów, bo one są ukryte w tych
    > > bibliotekach.
    >
    > To jakieś strasznie opakowane te biblioteki, że nie pozwalają dobrać
    > się do źródłowego socketa.

    Jest gorzej. To nie muszą być sockety. Np. system QNX ma fajny mechanizm komunikacji
    IPC, który istnieje poza przestrzenią deskryptorów plików. A ktoś inny będzie się
    komunikował przez pamięć dzieloną. Itd. Więc nawet gdybyś miał dostęp do bebechów, to
    i tak nie zapiąłbyś wszystkiego razem jednym selectem.

    No i nie możemy zakładać, że socket jest jeden, albo że ciągle ten sam, itd. Straszne
    komplikacje.

    > A co mówi dokumentacja tych bibliotek?

    To, co napisałem. Że wymienione funkcje robią robotę i wychodzą albo od razu
    wychodzą.

    > Chyba ich autorzy nie zakładają,
    > że ktoś będzie busy loop tworzył czekając na tweeta?

    Nie musi być busy loop. Bo możemy też założyć, że w każdej bibliotece jest dodatkowa
    funkcja wait_for_work(). Albo że te funkcje mają dodatkowy argument, żeby czekać. Tak
    jest w YAMI4. Wtedy pętla użytkownika nie musi być busy - po prostu blokuje się, jak
    nie ma nic do roboty.

    Ale mamy 3 takie funkcje. I co teraz?

    > W
    > takiej sytuacji wystarczy odczekać chwilę

    Dalej kiepsko, bo chcemy bez opóźnień przetwarzać zadania, jeśli są dostępne, i nie
    marnować prądu, jeśli nie są.

    > Ale to tylko jeśli biblioteki faktycznie nie udostępniają
    > jakichkolwiek mechanizmów sygnalizacji swoich potrzeb.

    Dobry trop.
    To w jaki sposób chciałbyś być poinformowany, że biblioteka ma potrzebę?

    Przypominam, że mamy 3 biblioteki. Przyjmijmy wersję idealną, że wszystkie 3 będą
    mieć ten mechanizm. Jaki?

    --
    Maciej Sobczak * http://www.inspirel.com


  • 9. Data: 2020-06-11 10:37:32
    Temat: Re: Integracja bibliotek event-based
    Od: Mateusz Viste <m...@x...invalid>

    2020-06-10 o 14:19 -0700, Maciej Sobczak napisał:
    > Jest gorzej. To nie muszą być sockety. Np. system QNX ma fajny
    > mechanizm komunikacji IPC, który istnieje poza przestrzenią
    > deskryptorów plików. A ktoś inny będzie się komunikował przez pamięć
    > dzieloną.

    Trzymajmy się założeń: była mowa o bibliotece "do http", innej "do
    tweetera" i trzeciej "baza danych". Każda z nich raczej (?) opiera się
    na socketach.

    > No i nie możemy zakładać, że socket jest jeden, albo że ciągle ten
    > sam, itd. Straszne komplikacje.

    Jeśli jest ten sam to komplikacji nie ma - jeśli się urywa to
    biblioteka zwraca błąd i trzeba zainicjalizować na nowo. Jeśli
    natomiast socket się tworzy nowy przy każdym zawołaniu (np. sprawdzanie
    tweetów via nową sesję ssl za każdym razem), to każde sprawdzenia
    powinno być regularnie wywoływane przez program.

    > dodatkowy argument, żeby czekać. Tak jest w YAMI4. Wtedy pętla
    > użytkownika nie musi być busy - po prostu blokuje się, jak nie ma nic
    > do roboty.

    Po bardzo pobieżnym przejrzeniu rozumiem to tak, że inspirel oczekuje
    że stworzysz swój własny wątek specjalnie dla wołania ich biblioteki:

    "All activity has to be driven by the application, which is supposed to
    'lease' one of its threads for doing the I/O work on behalf of the
    agent. This is achieved by calling the Do_Some_Work procedure in Ada
    or the do_some_work function in C++.

    The 'do some work' routine performs a single unit of work and
    returns to the caller. In a typical application it will be called in
    a tight loop."

    W takiej sytuacji niewiele można zrobić. Patrz niżej.

    > > Ale to tylko jeśli biblioteki faktycznie nie udostępniają
    > > jakichkolwiek mechanizmów sygnalizacji swoich potrzeb.
    >
    > Dobry trop.
    > To w jaki sposób chciałbyś być poinformowany, że biblioteka ma
    > potrzebę?
    >
    > Przypominam, że mamy 3 biblioteki. Przyjmijmy wersję idealną, że
    > wszystkie 3 będą mieć ten mechanizm. Jaki?

    Idealnie? No to chcę sam obsługiwać kanał danych (socket, IPC,
    whatever), a bibliotekę będę wołał tylko po to, żeby te dane
    obrobić/przetłumaczyć. Alternatywnie - niech biblioteka da dostęp do
    socketów, wówczas wiem, że jak coś się zmieni na kablu to powinien
    zawołać kogoś do obsługi. Ostatnia opcja: niech biblioteka da jakiś
    swój blokujący "wait_for_event()", sama niech blokuje w sposób
    eko-mądry i zależny od implementacji, a ja sobie ją wywołam w osobnym
    wątku. 3 biblioteki = 3 wątki, da się przeżyć.

    Mateusz


  • 10. Data: 2020-06-11 20:00:34
    Temat: Re: Integracja bibliotek event-based
    Od: Maciej Sobczak <s...@g...com>


    > Trzymajmy się założeń: była mowa o bibliotece "do http", innej "do
    > tweetera" i trzeciej "baza danych".

    Nie. Była mowa o integracji kilku bibliotek event-based.
    Przykłady dot. HTTP, bazy danych i Twittera to były *przykłady* do zobrazowania
    problemu a nie konkretne zadania do rozwiązania.
    Właściwym problemem jest integracja bibliotek narzucających jakiś idiom czy wzorzec
    ich obsługi.

    > Każda z nich raczej (?) opiera się
    > na socketach.

    Nie. W szczególności biblioteka do baz danych automatycznie dobierze metodę
    komunikacji zależnie od tego, gdzie jest baza. W szczególności, jeśli baza jest na
    tym samym komputerze, to istnieją sprawniejsze metody komunikacji, niż sockety.

    Wyobraź sobie dla jeszcze szerszego spektrum, że jedna z tych bibliotek to zwykłe
    GUI, gdzie "gotowość" to event w kolejce, bo użytkownik coś kliknął.

    Czyli tu nie chodzi o sockety. Tu chodzi o integrację bibliotek.

    > > No i nie możemy zakładać, że socket jest jeden, albo że ciągle ten
    > > sam, itd. Straszne komplikacje.
    >
    > Jeśli jest ten sam to komplikacji nie ma - jeśli się urywa to
    > biblioteka zwraca błąd i trzeba zainicjalizować na nowo. Jeśli
    > natomiast socket się tworzy nowy przy każdym zawołaniu (np. sprawdzanie
    > tweetów via nową sesję ssl za każdym razem), to każde sprawdzenia
    > powinno być regularnie wywoływane przez program.

    Nie na temat, ale dalej źle. Przykładowo, YAMI4 może mieć tysiące socketów. Pomijając
    drobny fakt, że select() nie nadaje się do obsługi tysięcy socketów, biblioteka
    stosuje algorytmy control-flow decydujące o tym, który kanał w ogóle albo w danym
    momencie zasługuje na obsługę. Czyli z faktu, że wśród tysięcy socketów kilkaset ma
    dane gotowe do odczytu wcale nie wynika, że to jest stan gotowości do wykonania
    zadania, bo akurat te sockety z gotowymi danymi nie muszą mieć "zielonego światła" na
    ruch komunikatów i może się okazać, że wtedy nadal jest "idle". O tym decyduje
    biblioteka.
    Dlatego nie możesz się nastawiać na to, że będziesz sobie sam obserwował te sockety,
    bo i tak nie masz kontekstu do pełnej oceny sytuacji.

    Co więcej, jest kompletnie bez sensu, żebyś duplikował ciężką pracę, którą biblioteka
    i tak robi w środku.

    > > Przypominam, że mamy 3 biblioteki. Przyjmijmy wersję idealną, że
    > > wszystkie 3 będą mieć ten mechanizm. Jaki?
    >
    > Idealnie? No to chcę sam obsługiwać kanał danych (socket, IPC,
    > whatever), a bibliotekę będę wołał tylko po to, żeby te dane
    > obrobić/przetłumaczyć.

    Już ustaliliśmy (powyżej), że nie.

    > Ostatnia opcja: niech biblioteka da jakiś
    > swój blokujący "wait_for_event()", sama niech blokuje w sposób
    > eko-mądry i zależny od implementacji, a ja sobie ją wywołam w osobnym
    > wątku. 3 biblioteki = 3 wątki, da się przeżyć.

    Świetnie.
    Doszedłeś w ten sposób do wniosku, że do obsługi *kilku* bibliotek event-based
    potrzebne są wątki. Albo wyjdą z biblioteki albo do niej wejdą. Ale będą potrzebne.

    Głębsza analiza wygląda tak:
    Pojęcie "idle" lub "nie ma zadania", itp. to pojęcia *lokalne*, zrozumiałe tylko w
    obrębie jednej biblioteki. Tzn. w bibliotece GUI to pojęcie oznacza, że user nic nie
    kliknął, w bibliotece komunikacyjnej że nie ma komunikatu, w bibliotece do baz danych
    że nie ma jeszcze odpowiedzi na wcześniejsze zapytanie, itd. To są stany *lokalne*.
    Jeżeli program jest w całości oparty o rytm pracy *jednej* biblioteki (tak jak w
    prostym GUI opartym o zdarzenia z okna), to ten lokalny koncept jest też globalny,
    czyli dotyczy całego programu. Wtedy nie są potrzebne ani wątki, ani muteksy.

    Ale jeśli mamy kilka takich bibliotek, każda ze swoim własnym konceptem "idle", to
    ich integracja jest problemem, bo globalnie "idle" oznacza, że *nikt* nie ma nic do
    roboty a tego stanu nie da się uwspólnić w jednym wątku, bez ciężkich kompromisów
    typu kręcenie się w pętli z odpytywaniem (nawet z jakimś mniej lub bardziej
    przemyślanym opóźnieniem).

    Dlatego albo:
    1. pozwolimy tym bibliotekom niezależnie informować o swoim bieżącym stanie przez
    callbacki wychodzące z tych bibliotek (w takim callbacku można np. odetkać główną
    pętlę czekającą na jakiejś fladze stopu) (co wymaga istnienia wątków w tych
    bibliotekach), albo
    2. zrobimy sobie osobne wątki do kręcenia blokującymi pętlami dla każdej biblioteki
    osobno, albo
    3. w ogóle schowamy ten koncept "idle" razem z pętlami zdarzeń i pozwolimy
    bibliotekom kręcić swoimi zdarzeniami samodzielnie (z własnych wątków).

    Tak czy inaczej mamy wątki. I ich konsekwencje.
    Ktoś ma pomysł na rozwiązanie tego problemu bez wątków?

    --
    Maciej Sobczak * http://www.inspirel.com

strony : [ 1 ] . 2



Szukaj w grupach

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: