Ich schreibe eine Multithreadanwendung in Qt (mehrere Threads mit ihren eigenen Ereignisschleifen). Bei der Protokollierung möchte ich, dass der Logger eine Thread-ID (mit aussagekräftigen Namen) in das Protokoll aufnimmt. Der Qt-Standard-Logger scheint dazu nicht in der Lage zu sein. Also habe ich drei Möglichkeiten:
Welcher ist besser und was sind die besten Praktiken im Allgemeinen?
Einige Dinge, um nach Fragen in Kommentaren zu klären:
postEvent()
, die Thread-sicher ist. Es stellt sich also die Frage, ob der Logger-Thread genügend Arbeit pro Ereignis machen muss, um die Kosten für das Marshallen der Ereignisdaten über eine Art von Warteschlange zu rechtfertigen.
Dies sind allgemeine Bemerkungen, da ich keine Erfahrung mit Qt habe. Im Hinblick auf die Kosten des Einreihens im Allgemeinen: I / O lässt normalerweise andere Laufzeitkosten verblassen, also sollte es keine Rolle spielen.
Eigenschaften eines dedizierten Logging-Threads:
Die (Vor-) Vorteile der direkten Protokollierung von jedem Thread sind die Umkehrung des Obigen. Keine zwei Threads können gleichzeitig protokollieren (entweder weil Funktionen wie printf()
implizit eine FILE
sperren, oder weil Sie die Protokollfunktion explizit synchronisieren); Dadurch werden alle Threads, die protokolliert werden sollen, blockiert, bis der aktuelle Thread ausgeführt wird. Wenn die Protokollierung zu Debugging-Zwecken durchgeführt wird, kann es erforderlich sein, ungepuffert zu protokollieren (damit die Daten bei einem nachfolgenden Absturz nicht verloren gehen), wodurch sich die Auswirkungen auf die Laufzeit verschlechtern.
Wie schlecht das ist, hängt von der Art der Anwendung sowie vom Protokollierungsmechanismus und der Datenmenge ab.
Ich habe Logging-Mechanismen für Qt-Anwendungen mit dem Qt-Event-Mechanismus sauber implementiert.
In einer Qt-Anwendung gibt es eine einzelne Instanz von QApplication , die die Anwendung darstellt.
Sie können Ihre eigenen Ereignisse erstellen, indem Sie von QEvent erben und sie veröffentlichen und mit den QApplication-Objekt für die Anwendung.
So haben Sie zum Beispiel Ihre Log-Ereignisklasse
%Vor%Und Sie können Ereignisse aus jedem Qt-Thread mit
posten %Vor%Der Handler könnte ein Hauptfensterobjekt (wenn Sie in ein Fenster loggen wollen) oder ein dediziertes Objekt sein, wenn Sie z.B. Log in eine Datei.
Überschreiben Sie in dem Objekt, das die Ereignisse behandelt, QObject :: event, um die Protokollnachrichten zu verarbeiten
%Vor%Ich verstehe nicht ganz, warum jeder Thread, der die Protokollierung selbst durchführt, einen expliziten Mutex verwenden müsste.
Wenn Sie sich bei einer Datenträgerdatei anmelden, kann jeder Thread in einer eigenen Datei protokollieren. Sie können die Dateien mit einem gemeinsamen Präfix benennen:
%Vor%Das Betriebssystem serialisiert den Zugriff über seine Dateisystem-Mutex (s).
Wenn Sie sich bei einer Datenbank anmelden, die den gleichzeitigen Zugriff unterstützt, wie zum Beispiel sqlite mit ausgewählten Optionen für den gemeinsamen Zugriff, wird der Datenbanktreiber für den Serialisierungszugriff zuständig sein.
Wenn Sie sich bei einem gemeinsamen Thread anmelden, hat die Ereigniswarteschlange einen Mutex, mit dem Sie automatisch serialisieren, wenn Sie postEvent
.
Sie haben Recht, dass Sie mit dem Signal-Slot-Mechanismus nicht viel Zeit für die direkte Verwendung von Ereignissen benötigen. In der Tat wird garantiert, dass mehr Speicherzuweisungen vorgenommen werden. Daher sollten Sie lieber selbst ein Ereignis posten, idealerweise ein Ereignis, das QVarLengthArray<char>
einer Größe verwendet, die "den meisten" Protokollmeldungen entspricht. Dann wird ein solches Ereignis mit einem einzigen malloc
-Aufruf zugewiesen:
Hätten Sie eine QByteArray
oder eine QString
verwendet, hätte der Ausdruck new MyLogEvent
mindestens zwei Zuordnungen ausgeführt.
Tags und Links c++ qt multithreading logging