Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging logarithmically 1, 10, 100, 1000, etc

Tags:

c#

.net

logarithm

Is there a more efficient way of doing the following, something just feels wrong about it? I'm looking for the most time efficient way of logging logarithmically.

    public bool Read()
    {
        long count = Interlocked.Increment(ref _count);
        switch (count)
        {
            case 1L:
            case 10L:
            case 100L:
            case 1000L:
            case 10000L:
            case 100000L:
            case 1000000L:
            case 10000000L:
            case 100000000L:
            case 1000000000L:
            case 10000000000L:
            case 100000000000L:
            case 1000000000000L:
            case 10000000000000L:
            case 100000000000000L:
            case 10000000000000000L:
            case 100000000000000000L:
            case 1000000000000000000L:
                _logger.LogFormattable(LogLevel.Debug, $"{count} Rows Read");
                break;
        }

        return _reader.Read();
    }

Update:

Here are my micro benchmark tests.

  • Method1: Übercoder's way with keep up with state
  • Method2: My way with the big switch statement
  • Method3: Markus Weninger's way with the nice Math Function

Since for me 100,000,000 records being read without logging takes around 20 minutes then an extra 4 seconds is nothing. I'm going with the beautiful Math way of doing things. Mathod3 wins in my scenario.

Run time for 100,000,000 iterations averaged over 100 attempts

Method1 Max: 00:00:00.3253789
Method1 Min: 00:00:00.2261253
Method1 Avg: 00:00:00.2417223

Method2 Max: 00:00:00.5295368
Method2 Min: 00:00:00.3618406
Method2 Avg: 00:00:00.3904475

Method3 Max: 00:00:04.0637217
Method3 Min: 00:00:03.2023237
Method3 Avg: 00:00:03.3979303
like image 791
Aaron Stainback Avatar asked Feb 12 '16 22:02

Aaron Stainback


2 Answers

If performance is not a big problem, I would use the following

if(Math.Log10(count) % 1 == 0)
  _logger.LogFormattable(LogLevel.Debug, $"{count} Rows Read");

This question states the following:

For floating point numbers, n % 1 == 0 is typically the way to check if there is anything past the decimal point.


Edit: To complete my answer, it is also possible to keep track of the next logging value, as @Übercoder posted in his answer.

long nextLoggingValueForLogX = 1;
if (count == nextLoggingValueForLogX )
{
   nextLoggingValueForLogX *= 10; // Increase it by your needs, e.g., logarithmically by multiplying with 10
   _logger.LogFormattable(LogLevel.Debug, $"{count} Rows Read");
}

Yet this method will come up with a new variable for every log that shouldn't be executed every time. This will introduce extra code and also extra work if it has to be made thread-safe.

like image 83
Markus Weninger Avatar answered Sep 17 '22 20:09

Markus Weninger


static long logTrigger = 1;


if (count == logTrigger)
{
   logTrigger *= 10;
   // do your logging
}
like image 25
Jens Meinecke Avatar answered Sep 17 '22 20:09

Jens Meinecke