以对数方式记录 1、10、100、1000 等
Logging logarithmically 1, 10, 100, 1000, etc
是否有更有效的方法来执行以下操作,感觉有些不对劲?我正在寻找最省时的对数记录方式。
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();
}
更新:
这是我的微基准测试。
- 方法一:Übercoder 跟上状态的方法
- 方法 2:我使用大 switch 语句的方法
- 方法 3:Markus Weninger 的数学函数方法
因为对我来说,读取 100,000,000 条记录而无需记录大约需要 20 分钟,那么额外的 4 秒算不了什么。我要用漂亮的数学方式做事。 Mathod3 在我的场景中获胜。
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
如果性能不是大问题,我会用下面的
if(Math.Log10(count) % 1 == 0)
_logger.LogFormattable(LogLevel.Debug, $"{count} Rows Read");
This question 声明如下:
For floating point numbers, n % 1 == 0 is typically the way to check if there is anything past the decimal point.
编辑:为了完成我的回答,还可以跟踪下一个日志记录值,正如@Übercoder 在他的回答中发布的那样。
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");
}
然而,此方法将为每个不应该每次都执行的日志提供一个新变量。如果必须使其成为线程安全的,这将引入额外的代码和额外的工作。
static long logTrigger = 1;
if (count == logTrigger)
{
logTrigger *= 10;
// do your logging
}
是否有更有效的方法来执行以下操作,感觉有些不对劲?我正在寻找最省时的对数记录方式。
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();
}
更新:
这是我的微基准测试。
- 方法一:Übercoder 跟上状态的方法
- 方法 2:我使用大 switch 语句的方法
- 方法 3:Markus Weninger 的数学函数方法
因为对我来说,读取 100,000,000 条记录而无需记录大约需要 20 分钟,那么额外的 4 秒算不了什么。我要用漂亮的数学方式做事。 Mathod3 在我的场景中获胜。
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
如果性能不是大问题,我会用下面的
if(Math.Log10(count) % 1 == 0)
_logger.LogFormattable(LogLevel.Debug, $"{count} Rows Read");
This question 声明如下:
For floating point numbers, n % 1 == 0 is typically the way to check if there is anything past the decimal point.
编辑:为了完成我的回答,还可以跟踪下一个日志记录值,正如@Übercoder 在他的回答中发布的那样。
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");
}
然而,此方法将为每个不应该每次都执行的日志提供一个新变量。如果必须使其成为线程安全的,这将引入额外的代码和额外的工作。
static long logTrigger = 1;
if (count == logTrigger)
{
logTrigger *= 10;
// do your logging
}