mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 19:32:19 +00:00
Currently the log filter strings are used in a string comparison against the source filename each time log message is emitted. If no log filters at all are set, there's obviously no string comparison to be done. If any single log filter is set though, this imposes a compute burden on every logging call even if logs from the file in question are disabled. This string comparison must also be done while the logging mutex is held, which has implications for concurrency when multiple threads are emitting log messages. This changes the log filtering to be done based on the virLogSource object name. The virLogSource struct is extended to contain 'serial' and 'priority' fields. Any time the global log filter rules are changed a global serial number is incremented. When a log message is emitted, the serial in the virLogSource instance is compared with the global serial number. If out of date, then the 'priority' field in the virLogSource instance is updated based on the new filter rules. The 'priority' field is checked to see whether the log message should be sent to the log outputs. The comparisons of the 'serial' and 'priority' fields are done with no locks held. So in the common case each logging call has an overhead of 2 integer comparisons, with no locks held. Only if the decision is made to forward the message to the log output, or if the 'serial' value is out of date do locks need to be acquired. Technically the comparisons of the 'serial' and 'priority' fields should be done with locks held, or using atomic operations. Both of these options have a notable performance impact, however, and since all writes a protected by a global mutex, it is believed that worst case behaviour where the fields are read concurrently with being written would merely result in an mistaken emission or dropping of the log message in question. This is an acceptable tradeoff for the performance benefit of avoiding locking. As a quick benchmark, a demo program that registers 500 file descriptors with the event loop (eg equiv of 500 QEMU monitor commands), creates pending read I/O on every FD, and then runs virEventRunDefaultImpl() took 4.6 seconds to do 51200 iterations. After this optimization it only takes 3.3 seconds, with the log APIs no longer being a relevant factor in the running time. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
LibVirt : simple API for virtualization Libvirt is a C toolkit to interact with the virtualization capabilities of recent versions of Linux (and other OSes). It is free software available under the GNU Lesser General Public License. Virtualization of the Linux Operating System means the ability to run multiple instances of Operating Systems concurrently on a single hardware system where the basic resources are driven by a Linux instance. The library aim at providing long term stable C API initially for the Xen paravirtualization but should be able to integrate other virtualization mechanisms if needed. Daniel Veillard <veillard@redhat.com>
Description
Libvirt provides a portable, long term stable C API for managing the
virtualization technologies provided by many operating systems. It
includes support for QEMU, KVM, Xen, LXC, bhyve, Virtuozzo, VMware
vCenter and ESX, VMware Desktop, Hyper-V, VirtualBox and the POWER
Hypervisor.
Languages
C
94.8%
Python
2%
Meson
0.9%
Shell
0.8%
Dockerfile
0.6%
Other
0.8%