Async/Overlapped Sockets Benchmark



  • @TyRoXx
    Wie viele funktionierende nicht-triviale Serverprogramme hast du mit Boost ASIO schon entwickelt?



  • hustbaer schrieb:

    @TyRoXx
    Wie viele funktionierende nicht-triviale Serverprogramme hast du mit Boost ASIO schon entwickelt?

    Was ist denn nicht-trivial? Netzwerk ist trivial. Verbindungen annehmen, empfangen, senden. Mit wenigen hundert Zeilen sind die ASIO-Sockets perfekt gekapselt und eingebunden.
    Das habe ich auch schon mehrmals mit BSD-Sockets gemacht. Die waren fehleranfällig und erforderten Anpassungen bei der Portierung, weil Microsoft Extra-Würste brät.
    Ganz abgesehen davon, dass ASIO eine asynchrone Architektur implementiert und als typische Anwendung Sockets mitliefert.
    Wer keine Ansprüche hat, kann BSD-Sockets nehmen. Ich habe aber Ansprüche an die Bibliotheken, die ich benutze.



  • Was ist der Unterschied zu einem Future mit einer blockierenden Send/Recv-Operation mit BSD=Sockets?



  • knivil schrieb:

    Was ist der Unterschied zu einem Future mit einer blockierenden Send/Recv-Operation mit BSD=Sockets?

    Bei blockierenden IO Requests, mit oder ohne Futures, mit oder ohne Thread-Pools, brauchst du einen Thread pro gleichzeitig ausstehendem IO Request. Weil der Thread ja vom IO Request blockiert wird.

    Bei asynchronem IO, mit oder ohne ASIO, brauchst du das nicht, da kannst du z.B. 10000 pending IO Requests haben, und trotzdem nur einen Thread (oder einen Pool mit weit weniger als 10000 Threads) verwenden. Trotzdem spart man sich im Vergleich zu select() + non-blocking den Overhead eines select() mit tausenden Sockets, und kann auch mit mehreren Threads Socket-IO machen.



  • TyRoXx schrieb:

    hustbaer schrieb:

    @TyRoXx
    Wie viele funktionierende nicht-triviale Serverprogramme hast du mit Boost ASIO schon entwickelt?

    Was ist denn nicht-trivial? Netzwerk ist trivial. Verbindungen annehmen, empfangen, senden. Mit wenigen hundert Zeilen sind die ASIO-Sockets perfekt gekapselt und eingebunden.
    Das habe ich auch schon mehrmals mit BSD-Sockets gemacht. Die waren fehleranfällig und erforderten Anpassungen bei der Portierung, weil Microsoft Extra-Würste brät.
    Ganz abgesehen davon, dass ASIO eine asynchrone Architektur implementiert und als typische Anwendung Sockets mitliefert.
    Wer keine Ansprüche hat, kann BSD-Sockets nehmen. Ich habe aber Ansprüche an die Bibliotheken, die ich benutze.

    Nochmal konkret die Frage: hast du schon was mit (Boost-)ASIO gemacht?

    Ich hab' ein Projekt mit Boost-ASIO angefangen (das dann leider abgebrochen wurde - was mit ASIO allerdings nix zu tun hatte), und durfte dort einige der Fallstricke und "Nettigkeiten" der Boost-ASIO kennenlernen.

    Und was ist nicht-trivial... Hm.
    Sagen wir mal ein Server der
    * Eine Liste der verbundenen Clients verwalten muss
    * Verbindungen zu den Clients (EDIT: zu *einzelnen* Clients) jederzeit trennen können muss
    * Eines der "lästigen" Protokolle ala HTTP verwenden muss, wo man dummerweise nicht von vornherein weiss wie viele Daten man noch lesen muss, bis man eine "Message" komplett empfangen hat



  • Bzgl. des "neuen" DDR3-RAMS: Die Netzwerktechnik entwickelt sich genauso, wenn auch nicht ganz so schnell. Vor ein paar Monaten noch wurde mit 100.000kbit/s Downstream für Privatkunden geworben.

    100.000 kbit/s sind doch gerade mal popelige ~12 MB/s.
    Dh. in etwa geht 1 Promille für das Buffer kopieren drauf. Zumindestens würde ich als Milchmädchen das so sagen.



  • hustbaer schrieb:

    Nochmal konkret die Frage: hast du schon was mit (Boost-)ASIO gemacht?

    Ja und es hat mich offensichtlich überzeugt.

    hustbaer schrieb:

    Ich hab' ein Projekt mit Boost-ASIO angefangen (das dann leider abgebrochen wurde - was mit ASIO allerdings nix zu tun hatte), und durfte dort einige der Fallstricke und "Nettigkeiten" der Boost-ASIO kennenlernen.

    Beispiele?



  • > Also warum soll man die in jeder Hinsicht schlechtere Lösung wählen? Ah, wahrscheinlich, weil die Dokumentation von ASIO ein bisschen technisch gehalten ist und einen aufmerksamen Leser erfordert. Mit BSD-Sockets bekommt man per Copy-and-Paste ein paar Minuten schneller eine Verbindung zustande, toll!

    Weil du auf einmal mit Sachen wie Threadsicherheit arbeiten musst, das ist alles andere als trivial.

    > 100.000 kbit/s sind doch gerade mal popelige ~12 MB/s.
    Dh. in etwa geht 1 Promille für das Buffer kopieren drauf. Zumindestens würde ich als Milchmädchen das so sagen.

    Naja, mittlerweile gibt's wohl schon 100 Mbit/s (http://netforbeginners.about.com/od/internet101/tp/What-Broadband-Internet-Choices-Are-Available.htm) (für Privatanwender), für Unternehmen und Serverfarmen sicher noch einiges mehr. Da werden aus deinem Promille einige Prozente.



  • TyRoXx schrieb:

    hustbaer schrieb:

    Nochmal konkret die Frage: hast du schon was mit (Boost-)ASIO gemacht?

    Ja und es hat mich offensichtlich überzeugt.

    hustbaer schrieb:

    Ich hab' ein Projekt mit Boost-ASIO angefangen (das dann leider abgebrochen wurde - was mit ASIO allerdings nix zu tun hatte), und durfte dort einige der Fallstricke und "Nettigkeiten" der Boost-ASIO kennenlernen.

    Beispiele?

    Als erstes fand ich mal toll einen Bug in der SSL Anbindung finden zu dürfen:
    https://svn.boost.org/trac/boost/ticket/2910
    (Das Ticket ist von mir)
    OK, das ist EIN Bug, wenn ich mir die Change-Logs von anderen Projekten so ansehe ... also da gibt es viel schlimmeres. Wenn man sowas allerdings (wie es bei mir der Fall war) am 3. oder 4. Tag des schönen neuen Projekts mit der schönen ASIO selbst findet, sträkt das natürlich nicht gerade das Vertrauen in die Lib.

    Dann fand ich es "interessant" herauszufinden, dass die ASIO Completion-Handler unter bestimmten Bedingungen nicht aufruft.
    Wenn das passiert, ist die einzige Möglichkeit draufzukommen dass es passiert ist, die, zu gucken wann die letzte Kopie des übergebenen Handlers zerstört wird.
    D.h. man braucht schon wieder shared_ptr in den Handlern, oder man muss selbst Referenzen zählen.
    Dummerweise gilt das "Handler wird nur im Strand ausgeführt" aber nur für den operator () des Handlers, nicht aber für das Erzeugen oder Zerstören von Kopien des Handlers.

    D.h. der Destruktor der letzten Kopie eines Handlers kann in irgendeinem Thread zu irgendeiner Zeit laufen. Tja blöd, wir wollten uns doch darauf verlassen dass der Strand für uns das Synchronisieren übernimmt. Doof. Aber ne, geht schon, post()en wir einfach ne Invokation der nötigen Cleanup-Funktion auf den Strand, dann ist wieder alles gut. Pustekuchen, nix ist gut, denn das post()en von Handlern kann ne Exception werfen. Nämlich wenn der Handler sich nicht kopieren lässt (OK, da ist man wohl selbst schuld), oder wenn einfach ein bad_alloc von irgendwoher geflogen kommt. Also doch doof.
    D.h. man scheisst entweder auf die Fälle wo der Speicher knapp wird ( set_new_handler(terminate) , yeah!), oder man muss erst wieder selbst synchronisieren. Na gut, synchronisieren wir eben selbst. Dann können wir wenigstens den Strand (und den damit verbundenen Overhead) loswerden. Oder doch nicht? Was mich gleich zum nächsten Punkt bringt...

    Der ganze Tanz mit den Strands, bloss weil man Verbindungen "von aussen" Trennen können möchte. Die einzige (sinnvolle) Möglichkeit (die ich kenne), die die ASIO diesbezüglich anbietet, ist den Stream zu schliessen. Jetzt darf man den Stream aber nicht einfach so schliessen, weil Operationen auf dem Stream nicht threadsafe sind. Dummerweise hat man aber ausser den erwähnten Strands keine Möglichkeit, die Ausführung von Handlern von "composed asynchronous operations" zu synchronisieren. Denen es ja ebenfalls erlaubt ist Operationen auf dem Stream zu machen. Es nützt also nichts, wenn man in seinem "Session" Objekt bereits selbst eine Mutex drinnen hat über die man bestimmte Dinge synchronisiert. Man muss trotzdem zusätzlich alle IOs in einen Strand einwickeln. Was den Overhead verdoppelt.

    Und das alles nur, weil man Sessions "tracken" (=eine zentrale Liste aller offenen Sessions verwalten), und Sessions unter bestimmten Bedingungen von aussen abbrechen können möchte.



  • asio muss schon eine unglaublich schlechte bibliothek sein, wenn es die arbeit erschwert anstatt zu vereinfachen (wie man es normalerweise von bibliotheken gewöhnt ist)



  • ps:
    Nur weil in diesem Thread (unter anderem von mir) select() + non-blocking IO als "Alternative" zu ASIO dargestellt wurde...

    Der echte "ASIO Killer" für Projekte die schnell fertig werden sollen, und keine Unmengen an gleichzeitigen Connections unterstützen müssen, ist mMn. nicht select() + non-blocking IO, sondern ein Thread pro Connection + blocking IO.

    Skaliert wunderbar bis zu etlichen hundert Clients pro Prozess, und man spart sich enorm viel Aufwand bei der Implementierung.
    (Erfahrung mit etlichen tausend Clients - die mit 64 bittigen Systemen kein grundsätzliches Problem darstellen - konnte ich noch keine sammeln. Würde mich aber nicht wundern, wenn das auch noch halbwegs OK funktioniert.)



  • AFAIK ist Boost Asio "tot". Letztes Release vor fast einem Jahr und der Autor meldet sich schon seit vielen vielen Monaten nicht mehr in der Mailinglist.



  • Also die Boost Version 1.48 ist noch kein Jahr alt, und da gab es doch etliche Änderungen in der ASIO:
    http://www.boost.org/users/history/version_1_48_0.html

    Und im TRAC tut sich auch noch was, z.B.:
    https://svn.boost.org/trac/boost/ticket/6310

    Sieht für mich nicht tot aus.

    Ich will die ASIO auch hier nicht schlechter darstellen als sie ist. Ich meine nur, dass sie lange nicht so einfach ist, wie manche meinen 🙂



  • > 100.000 kbit/s sind doch gerade mal popelige ~12 MB/s.
    Dh. in etwa geht 1 Promille für das Buffer kopieren drauf. Zumindestens würde ich als Milchmädchen das so sagen.

    Naja, mittlerweile gibt's wohl schon 100 Mbit/s (http://netforbeginners.about.com/od/internet101/tp/What-Broadband-Internet-Choices-Are-Available.htm) (für Privatanwender), für Unternehmen und Serverfarmen sicher noch einiges mehr. Da werden aus deinem Promille einige Prozente.

    100 Mbit/s = 12500 kb/s = ~11.92 Mib/s.
    Also ist es bei 100Mbit immer noch weniger als ein Promille, wenn noch sämtlicher Netzwerk-Overhead wie der TCP/IP Stack dazu kommt.
    In Rechenzentren mit mehreren Gbit, wo die Leitung glühen, mag es spürbar sein. Für den normalen Serverbetreiber wird aber der Performance-Unterschied wohl kaum "signifikant" sein, wie gesagt.



  • custom query schrieb:

    AFAIK ist Boost Asio "tot". Letztes Release vor fast einem Jahr und der Autor meldet sich schon seit vielen vielen Monaten nicht mehr in der Mailinglist.

    http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/history.html


Anmelden zum Antworten