Frage

Ich habe einen Mini-HTTP-Server in C ++ entwickelt, boost :: asio, und jetzt ist es mit mehreren Clients Ich bin Last zu testen und ich habe nicht in der Lage gewesen zu nahe kommen, die CPU zu sättigen. Ich teste auf einer Amazon EC2-Instanz, und etwa 50% Nutzung einer CPU, 20% eines anderen bekommen, und die restlichen zwei sind Leerlauf (nach htop).

Details:

  • Die Server Brände einen Thread pro Kern
  • Anfragen empfangen werden, analysiert, verarbeitet und Antworten werden ausgeschrieben
  • Die Anforderungen sind für Daten, die aus dem Speicher ausgelesen wird (schreibgeschützt für diesen Test)
  • Ich bin ‚Laden‘ der Server mit zwei Maschinen, die jeweils eine Java-Anwendung ausgeführt wird, 25 Threads ausgeführt wird, Senden von Anforderungen
  • Ich sehe etwa 230 Anfragen / s Durchsatz (dies ist Anwendung Anfragen, die aus vielen HTTP-Anforderungen zusammengesetzt sind)

Also, was soll ich betrachte dieses Ergebnis zu verbessern? In Anbetracht der CPU meist im Leerlauf ist, würde Ich mag, dass zusätzliche Kapazitäten nutzen, einen höheren Durchsatz zu bekommen, sagen 800 Anfragen / s oder was auch immer.

Ideen Ich habe:

  • Die Anforderungen sind sehr klein, und oft in wenigen ms erfüllt, ich könnte der Client ändern größere Anforderungen zu senden / compose (vielleicht mit batching)
  • Ich kann den HTTP-Server ändern Sie das Select-Entwurfsmuster zu verwenden, ist dies hier angebracht?
  • Ich könnte eine Profilierung tun, um zu versuchen, zu verstehen, was der Engpass ist / sind
War es hilfreich?

Lösung

boost :: asio ist nicht als faden freundlich, wie man es hoffen - es gibt eine große Sperre um den epoll Code in boost / Asio / detail / epoll_reactor.hpp was bedeutet, dass nur ein Thread nennen kann in den Kernel des epoll syscall zu einem Zeitpunkt. Und für ganz kleine Wünsche all dies macht den Unterschied (das heißt, Sie werden nur grob Single-Thread-Performance sehen).

Beachten Sie, dass dies eine Einschränkung, wie boost :: asio nutzt die Linux-Kernel-Einrichtungen, die nicht unbedingt den Linux-Kernel selbst. Die epoll syscall hat mehrere Threads unterstützen, wenn flankengetriggerter Ereignisse verwenden, aber es rechts (ohne übermäßige Verriegelung) bekommen kann ziemlich schwierig sein.

BTW, ich habe in diesem Bereich einige Arbeit getan (eine voll multithreaded flankengetriggerter epoll Ereignisschleife mit benutzer geplant Fäden / Fasern kombiniert) und machte einen Code unter der nginetd Projekt.

Andere Tipps

Wie Sie EC2 verwenden, sind alle Wetten ab.

Versuchen Sie es echte Hardware, und dann könnten Sie in der Lage sein zu sehen, was passiert. Der Versuch, Performance-Tests in VMs zu tun ist im Grunde unmöglich.

Ich habe noch nicht ausgearbeitet, was EC2 ist geeignet, wenn jemand herausfinden, lassen Sie es mich wissen.

Von Ihre Kommentare zu Netzwerknutzung,
Sie scheinen nicht viel Netzwerk Bewegung zu haben.

3 + 2.5 MiB/sec ist rund um den 50Mbps Ball-Park (im Vergleich zu Ihrem 1Gbps-Port).

Ich würde sagen, Sie eine der folgenden zwei Probleme haben,

  1. Unzureichende Arbeitsbelastung (niedrige Anforderungsrate von Ihren Kunden)
    • Blockierung in der Server (beeinflusster Antwort Generation)

bei cmeerw Notizen suchen und Ihre CPU-Auslastung Zahlen
(Bei 50% + 20% + 0% + 0% Leerlauf)
es scheint sehr wahrscheinlich eine Einschränkung in Ihrer Server-Implementierung.
Ich zweite cmeerw Antwort (+1).

230 Anfragen / s scheint für solche einfachen Asynchron-Anfragen sehr gering. Als solches ist es, mehrere Threads wahrscheinlich vorzeitige Optimierung - bekommen es in einem einzigen Thread richtig und abgestimmt zu arbeiten und sehen, wenn Sie noch brauchen. Nur loszuwerden Verriegelung nicht benötigten Dinge bis zu Geschwindigkeit bekommen kann.

diesem Artikel einige Details hat und Diskussion über I / O-Strategien für Web-Server -Stil Leistung circa 2003. Jeder bekam etwas aktuellere?

ASIO ist gut für kleine bis mittlere Aufgaben, aber es ist nicht sehr gut auf die Leistung des zugrunde liegenden Systems nutzen. Weder sind Raw-Socket Anrufe oder sogar IOCP unter Windows aber wenn Sie erfahren sind Sie immer besser sein als ASIO. In beiden Fällen gibt es eine Menge Aufwand mit all diesen Methoden, nur mehr mit ASIO.

Für das, was es wert ist. mit Raw-Socket Anrufe auf meinem benutzerdefinierten HTTP kann 800K dynamische Anfragen pro Sekunde mit einem 4-Kern-I7 dienen. Es dient aus dem RAM, das ist, wo Sie für die Höhe der Leistung sein müssen. Auf dieser Ebene der Leistung der Netzwerktreiber und OS verbrauchen etwa 40% der CPU. Mit ASIO Ich kann um bekommen 50 bis 100K Anfragen pro Sekunde, seine Leistung ist sehr variabel und meist gebunden in meiner app. Der Beitrag von @cmeerw meist erklärt, warum.

Eine Möglichkeit zur Verbesserung der Leistung ist durch eine UDP-Proxy-Implementierung. HTTP-Anforderungen abfängt und sie dann über UDP-Routing zu Back-End-UDP-HTTP-Server können Sie eine Menge von TCP-Overhead in den Betriebssystem-Stacks umgehen. Sie können auch vordere Enden, die Leitung durch auf UDP haben sich, nicht zu schwer, sich selbst zu tun sein sollte. Ein Vorteil eines HTTP-Proxy UDP ist, dass es Sie etwas Gutes Frontend ohne Änderungen nutzen können, und Sie können sie ohne Auswirkungen nach Belieben tauschen. Sie müssen nur noch ein paar Servern, sie umzusetzen. Diese Modifikation auf meinem Beispiel senkte die OS CPU-Auslastung auf 10%, die pro Sekunde meine Anfragen erhöhte sich auf knapp über eine Million an diesem einzigen Backend. Und FWIW Sie sollten immer einen Frontend-Backend-Setup für jede performante Website haben, weil die Frontends kann die Daten zwischenspeichern, ohne den wichtigen dynamische Anfragen Backend zu verlangsamen.

Die Zukunft scheint Ihre eigenen Treiber zu schreiben, das seinen eigenen Netzwerk-Stack implementiert, so dass Sie so nah an die Wünsche wie möglich erhalten und ein eigenes Protokoll umsetzen werden. Was wahrscheinlich nicht das, was die meisten Programmierer wollen hören, wie es komplizierter ist. In meinem Fall würde ich in der Lage sein, 40% mehr CPU zu verwenden und über 1 Millionen dynamische Anfragen pro Sekunde bewegen. Der UDP-Proxy-Methode kann erhalten Sie eine optimale Leistung zu schließen, ohne dies zu tun brauchen, aber Sie werden mehr Server müssen - obwohl, wenn Sie so viele Anfragen pro Sekunde tun Sie in der Regel mehrere Netzwerkkarten und mehrere Frontends müssen die Bandbreite so zu handhaben, die ein paar leichte UDP-Proxies dort nicht so große Sache ist.

Hoffnung einige dieser kann Ihnen nützlich sein.

Wie viele Instanzen von io_service haben Sie? Erhöhung Asio hat einen Beispiel das schafft ein io_service pro CPU und nutzen sie in der Art von Roundrobin.

Sie können noch vier Threads erstellen und eine pro CPU zuweisen, aber jeder Thread kann auf seiner eigenen io_service abzufragen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top