Frage

Ich habe eine Frage zu sehen, warum „Polling ist schlecht“. In Bezug auf die Menge an Prozessorzeit von einem Thread verwendet zu minimieren, wäre es besser, einen Spin wait (dh Umfrage für eine erforderliche Änderung in einer while-Schleife) zu tun, oder warten Sie auf einem Kernel-Objekt (zB ein Kernel-Ereignisobjekt in den Fenstern) ?

Für Zusammenhang davon aus, dass der Code auf jeder Art von Prozessor zu laufen wäre erforderlich, Single-Core, Hyper-Threading, mehradrige usw. übernehmen Sie auch, dass ein Thread, bis er nicht mehr weiter kann das Abfrageergebnis zufriedenstellend abfragen oder warten würde, ist wenn es anstelle des Wartens abgefragt. Schließlich ist die Zeit zwischen, wenn ein Thread beginnt (oder Polling) warten, und wenn die Bedingung erfüllt ist möglicherweise von sehr kurzer Zeit auf eine lange Zeit variieren kann.

Da das O ist wahrscheinlich effiziente „poll“ im Fall von „warten“, will ich nicht das sehen „waiting bedeutet nur, jemand anderes hat die Abfrage“ Argument, das ist alte Nachrichten, und nicht unbedingt 100% genau.

War es hilfreich?

Lösung

Sofern die OS vernünftige Implementierungen dieser Art von Gleichzeitigkeit Primitiven haben, ist es auf jeden Fall besser auf einem Kernel-Objekt zu warten.

Unter anderem, auf diese Weise kann das O weiß nicht, den Faden in Frage für zusätzliche Zeitscheiben zu planen, bis das Objekt gewartet-für ist in einem entsprechenden Zustand befindet. Ansonsten haben Sie einen Thread, der ständig neu geplant wird immer kontextschalteten, und dann für eine Zeit ausgeführt wird.

Sie ausdrücklich darum gebeten, über die Prozessorzeit für einen Thread zu minimieren: in diesem Beispiel den Faden auf einem Kernel-Objekt blockiert ZERO Zeit verwenden würde; das Abrufthread alle möglichen Zeit verwenden würde.

Darüber hinaus ist das „jemand anderes ist polling“ Argument muss nicht wahr sein. Wenn ein Kernel-Objekt des entsprechenden Zustand eintritt, kann der Kernel aussieht in diesem Augenblick, um zu sehen, die Fäden für das Objekt warten ... und dann eine oder mehr von ihnen plant für die Ausführung. Es gibt keine Notwendigkeit für den Kernel (oder sonst jemand) etwas in diesem Fall abzufragen.

Andere Tipps

Das Warten ist die „schönere“ Art und Weise zu verhalten. Wenn Sie auf einem Kernel warten Objekt Thread wird keine CPU-Zeit gewährt werden, da sie durch den Scheduler bekannt ist, dass es keine Arbeit fertig ist. Ihr Gewinde ist nur noch CPU-Zeit gegeben werden, wenn es wartet Bedingung erfüllt ist. Was bedeutet, werden Sie keine CPU-Ressourcen unnötig werden hogging.

Ich denke, ein Punkt, der noch nicht erhoben worden ist, dass, wenn Ihr Betriebssystem eine Menge Arbeit zu tun hat, yeilds Ihren Thread zu einem anderen Prozess blockiert. Wenn alle Prozesse verwenden, um die blockierenden Primitiven, wo sie sollten (wie Kernel wartet, Datei / Netzwerk IO usw.) können Sie den Kernel mehr Informationen sind zu geben zu entscheiden, welche Threads ausgeführt werden soll. Als solches wird es mehr Arbeit in der gleichen Menge an Zeit zu tun. Wenn Ihre Anwendung etwas Nützliches während des Wartens auf die Datei oder das Paket zu öffnen, tun könnte, um anzukommen, dann wird yeilding sogar helfen, eigene App sind.

Warten hat mehr Ressourcen beinhalten und bedeutet einen zusätzlichen Kontextwechsel. Tatsächlich verwenden einige Synchronisations Primitiven, wie CLR Monitore und Win32 kritische Abschnitte ein Zwei-Phasen-Sperrprotokoll - einige Spin Warte Vordergrund tatsächlich getan wird eine echte Warte tun

.

Ich stelle mir die Zwei-Phasen-Sache zu tun wäre sehr schwierig und würde eine Menge Tests und Forschung einzubeziehen. Also, wenn Sie die Zeit und Ressourcen haben, halten Sie sich an den Fenstern Primitiven ... sie haben bereits die Forschung für Sie.

Es gibt nur wenige Orte, in der Regel innerhalb des OS Low-Level Dinge (Interrupt-Handler / Gerätetreiber), in dem Spin-Warte Sinn macht / erforderlich ist. Mehrzweck-Anwendungen sind immer besser auf einige Synchronisations Primitiven wie mutexes / Bedingungsvariablen / Semaphore warten.

Ich bin mit Darksquid, wenn Ihr O anständige Gleichzeitigkeit Primitiven hat, dann sollten Sie nicht abfragen müssen. Polling kommt in der Regel in seinem eigenen auf Echtzeit-Systemen oder eingeschränkte Hardware, die nicht ein Betriebssystem hat, dann müssen Sie abfragen, da Sie nicht die Möglichkeit haben könnten () zu warten, sondern auch, weil es Ihnen feinkörnige Kontrolle darüber, wie lange gibt im Gegensatz Sie wollen in einem bestimmten Zustand warten, auf Gedeih und Verderb des Abwicklers zu sein.

Waiting (Blockierung) ist fast immer die beste Wahl ( „best“ im Sinne der effiziente Nutzung von Verarbeitungsressourcen zu machen und die Auswirkungen auf anderen Code minimiert auf demselben System ausgeführt wird). Die wichtigsten Ausnahmen sind:

  1. Wenn die erwartete Abfragedauer klein ist (ähnlich groß wie die Kosten für die Sperrung syscall).
  2. Meist in Embedded-Systemen, wenn der CPU eine bestimmte Aufgabe durchführen und es gewidmet ist kein Vorteil, die CPU im Leerlauf (z einig Software-Router in den späten 90er Jahren gebaut, diesen Ansatz verwendet.) Zu haben,

Polling im Allgemeinen nicht innerhalb von OS-Kernel verwendet Blockier-System zu implementieren, ruft -. Statt, Ereignisse (Interrupts, Timer, Aktionen auf mutexes) in einem blockierten Prozess führt oder wird aus ausführbarem Thread

Es gibt vier grundlegende Ansätze könnte man annehmen:

  1. Verwenden Sie einige OS warten primitiv zu warten, bis das Ereignis eintritt
  2. Verwenden Sie einige OS Timer primitive irgend definierten Geschwindigkeit zu prüfen, ob das Ereignis noch aufgetreten
  3. Immer wieder überprüfen, ob das Ereignis aufgetreten ist, sondern verwenden Sie ein O primitive eine Zeitscheibe für eine beliebige und unbekannte Dauer erhalten jederzeit es nicht hat.
  4. Immer wieder überprüfen, ob das Ereignis aufgetreten ist, ohne Nachgeben der CPU, wenn es nicht hat.

Wenn # 1 praktisch ist, ist es oft der beste Ansatz, wenn man nicht die Antwort auf das Ereignis zu verzögern könnte von Vorteil sein. Zum Beispiel, wenn man erwartet, eine große Menge an seriellen Schnittstelle Daten über den Verlauf von mehreren Sekunden zu empfangen, und wenn Daten 100ms Verarbeitung, nachdem er als Verarbeitung es nur so gut sein wird gesendet periodische Abfrage einen der beiden letzteren unter Verwendung sofort, Ansätze könnte besser sein, als eine „Daten empfangen“ Ereignis einrichten.

Ansatz # 3 ist ziemlich grob, aber in vielen Fällen kann eine gute sein. Es wird oft mehr CPU-Zeit und Ressourcen vergeudet als 1 # nähern würde, aber es wird in vielen Fällen einfacher zu implementieren und die Ressourcenverschwendung in vielen Fällen klein genug sein, keine Rolle.

Ansatz # 2 ist oft komplizierter als # 3, hat aber den Vorteil, viele Ressourcen mit einem einzigen Timer zu handhaben zu können und keinen dedizierten Thread.

Ansatz # 4 ist manchmal in Embedded-Systemen notwendig, aber ist in der Regel sehr schlecht, wenn man nicht direkt Polling-Hardware und das wird zu tun hat, etwas nicht sinnvoll, bis das betreffende Ereignis eintritt. In vielen Fällen wird es nicht möglich sein, die Bedingung auf gewartet wird auftreten, bis der Thread für sie warten, um die CPU liefert. Nachgeben der CPU als in Ansatz # 3 wird in der Tat kann der wartende Thread das Ereignis früher sehen, als es hogging würde.

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