Statistics

All the tests were done sending 10000 logs in total, sending them as fast as possible:

ScenarioProcessThreadsOutputLogging ProxyCentral LoggerOnewayTotalAverageMinMax
1Client1 Log (stdout)(error)(error)(error)18380 us1.8 us1.6 us308 us
1Client1 Log (stdout)(tick)(error)(error)601893 us60.1 us5.9 us525.8 us
2Client1Log (stdout)(tick)(tick)(error)681522 us68.1 us52.8 us531.7 us
3Client1Log (stdout)(tick)(tick)(tick)337458 us33.719.2 us353.4 us
4Client1Log (file)(error)(error)(error)18639 us1.8 us1.6 us295 us
4Client1Log (file)(tick)(error)(error)548046 us54.8 us6.3 us783.2 us
5Client1Log (file)(tick)(tick)(error)619841 us61.9 us52.5 us946.9 us
6Client1Log (file)(tick)(tick)(tick)320333 us32.016.8 us393.5 us
7Client1stdout(error)(error)(error)18841 us1.8 us0.8 us447.9 us
8Client1file(error)(error)(error)21358 us2.1 us1.4 us332.8 us
9Client1no-op(error)(error)(error)834 us0.1 us0.02 us95.2 us
10Client10 Log (stdout)(error)(error)(error)64520.4 us6.4 us1.7 us610.9 us
10Client10 Log (stdout)(tick)(error)(error)1415860 us141.5 us4.9 us12617.4 us
11Client10Log (stdout)(tick)(tick)(error)2950060 us294.902 us66.257 us5005.26 us
12Client10Log (stdout)(tick)(tick)(tick)958351 us95.75 us16.7 us65872.4 us
13Client10Log (file)(error)(error)(error)63096.3 us6.2 us1.7 us1007.8 us
13Client10Log (file)(tick)(error)(error)930486 us93.0 us6.8 us15150.4 us
14Client10Log (file)(tick)(tick)(error)2319040 us231.8 us54.7 us5164.8 us
15Client10Log (file)(tick)(tick)(tick)660748 us66.0 us15.3 us67563.6 us
16Client10stdout(error)(error)(error)301182 us30.1 us0.8 us1655.3 us
17Client10file(error)(error)(error)210906 us21.06 us1.5 us285.3 us
18Client10no-op(error)(error)(error)2409 us0.2 us0.02 us257.84 us
19Component1 Log (stdout)
(error)(error)



20Component1Log (stdout)
(tick)(error)



21Component1Log (stdout)
(tick)(tick)



22Component1Log (file)
(error)(error)



23Component1Log (file)
(tick)(error)



24Component1Log (file)
(tick)(tick)



25Component1stdout
(error)(error)



26Component1file
(error)(error)



27Component1no-op
(error)(error)



28Component10 Log (stdout)
(error)(error)



29Component10Log (stdout)
(tick)(error)



30Component10Log (stdout)
(tick)(tick)



31Component10Log (file)
(error)(error)



32Component10Log (file)
(tick)(error)



33Component10Log (file)
(tick)(tick)



34Component10stdout
(error)(error)



35Component10file
(error)(error)



36Component10no-op
(error)(error)



Analysis

LoggingProxy

From the statistics results, we can infer that (in a local environment) the biggest performance hit comes from the LoggingProxy itself and not the communication with the Central Logger. Going a bit further we found two slow downs down the path:

                xmlElement = XMLParser::parseString(iter->c_str(), true);

And

            ts.tv_sec=0;
            ts.tv_nsec=100;
            //FIXME: This nanosleep provide stability to the logging system. It shouldn't exist :(
            nanosleep(&ts,NULL);

Which combined with several mutexes, end up generating thread contention on the logging system.

The impact is of about 60/70 μs on average for each log call, which is not a big number, but we would like to be closer to the 1/10 μs range.

There are different strategies that could be used to fix this problem, such as refactoring the code, replacing the XML parsing library or the mechanism used within the library, re-structuring the use of mutexes to multiple instances or changing them to be RW mutexes.

Central Logger

In the case of the central logger, it's not a mystery the slow down comes from the remote call to the central logger.

            m_logger->writeRecords(reclist);

Here the slowdown accounts for ~70/80 μs on a local deployment, but can get closer to 1 ms when the central logger is on a different machine than the process generating the logs.

Again, there are several alternatives to improve the thread contention problems, for example by queuing this task and dispatching them on a separate thread. It is also possible to replace the writeRecords method to be oneway on the IDL, which makes it 2x/3x faster on the local deployment, and it also makes it invariant to the deployment as this call does not wait for a reply from the remote object. The drawback is losing the ability to assess whether the message was sent or there was a problem along the way, which could be leveraged by the use of a callback object.


  • No labels