GVKun编程网logo

Stopwatch.GetTimestamp() 在 linux 和 windows 上产生不同的结果(linux watchdog timeout)

2

对于想了解Stopwatch.GetTimestamp()在linux和windows上产生不同的结果的读者,本文将提供新的信息,我们将详细介绍linuxwatchdogtimeout,并且为您提供关

对于想了解Stopwatch.GetTimestamp() 在 linux 和 windows 上产生不同的结果的读者,本文将提供新的信息,我们将详细介绍linux watchdog timeout,并且为您提供关于.google.common.base.Stopwatch.()V from class org.apache.hadoop.mapred.FileInputFormat、Apache Commons-lang3 提供的 StopWatch 执行时间监视器,以及 Spring 提供的 StopWatch 分析、base.Stopwatch.()V from class org.apache.hadoop.mapred.FileInputFormat 》??、C# StopWatch 的使用的有价值信息。

本文目录一览:

Stopwatch.GetTimestamp() 在 linux 和 windows 上产生不同的结果(linux watchdog timeout)

Stopwatch.GetTimestamp() 在 linux 和 windows 上产生不同的结果(linux watchdog timeout)

如何解决Stopwatch.GetTimestamp() 在 linux 和 windows 上产生不同的结果

我希望有人能向我解释为什么下面的函数在 linux 和 windows 上产生难以置信的不同结果。

如果我有这么一小段代码:

  1. var elapsed = Stopwatch.GetTimestamp() / TimeSpan.TicksPerMillisecond;
  2. Thread.Sleep(1001); // lets sleep for one second
  3. var ts = Stopwatch.GetTimestamp() / TimeSpan.TicksPerMillisecond;
  4. var result = ts - elapsed > 10000L // roughly 10 seconds

在 Windows 环境中,resultfalse

但是在 linux 环境中,resulttrue

我读过 Stopwatch.GetTimestamp() 依赖于处理器。但这似乎太过分了。

据我所知,GetTimestamp 在 Windows 和 Linux 上产生的值大不相同。

例如在我的情况下运行上面的代码

在 Windows 上 Stopwatch.GetTimestamp() 产生的值大致在 165100732 的范围内

在 Linux 上 Stopwatch.GetTimestamp() 产生的值超过 200 倍,例如349232049523

所以我可以理解为什么 result 不同,即在 Windows 上它记录了 1 秒的经过持续时间,但在 Linux 上记录了接近 100 秒的经过持续时间。所以那部分没问题。

那么问题归结为为什么 Stopwatch.GetTimestamp() 在两种环境之间产生如此大不相同的数字?

解决方法

进一步挖掘后,我发现在使用 Stopwatch.GetTimestamp() 时我错误地执行了毫秒计算。

更新如下代码后,它开始表现一致。

  1. var elapsed = Stopwatch.GetTimestamp() / (Stopwatch.Frequency / 1000);
  2. Thread.Sleep(1001); // lets sleep for one second
  3. var ts = Stopwatch.GetTimestamp() / (Stopwatch.Frequency / 1000);
  4. var result = ts - elapsed > 10000L // roughly 10 seconds

答案感谢 Jens 对此 answer

的评论

.google.common.base.Stopwatch.<init>()V from class org.apache.hadoop.mapred.FileInputFormat

.google.common.base.Stopwatch.()V from class org.apache.hadoop.mapred.FileInputFormat

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.CommandLineWrapper.main(CommandLineWrapper.java:67)
Caused by: java.lang.IllegalAccessError: tried to access method com.google.common.base.Stopwatch.<init>()V from class org.apache.hadoop.mapred.FileInputFormat
    at org.apache.hadoop.mapred.FileInputFormat.getSplits(FileInputFormat.java:312)
    at org.apache.spark.rdd.HadoopRDD.getPartitions(HadoopRDD.scala:204)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
    at scala.Option.getOrElse(Option.scala:121)
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:251)
    at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
    at scala.Option.getOrElse(Option.scala:121)
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:251)
    at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
    at scala.Option.getOrElse(Option.scala:121)
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:251)
    at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
    at scala.Option.getOrElse(Option.scala:121)
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:251)
    at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
    at scala.Option.getOrElse(Option.scala:121)
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:251)
    at org.apache.spark.SparkContext.runJob(SparkContext.scala:2126)
    at org.apache.spark.rdd.RDD$$anonfun$collect$1.apply(RDD.scala:945)
    at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
    at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:112)
    at org.apache.spark.rdd.RDD.withScope(RDD.scala:363)
    at org.apache.spark.rdd.RDD.collect(RDD.scala:944)
    at org.apache.spark.sql.execution.SparkPlan.executeCollect(SparkPlan.scala:299)
    at org.apache.spark.sql.Dataset.org$apache$spark$sql$Dataset$$collectFromPlan(Dataset.scala:3384)
    at org.apache.spark.sql.Dataset$$anonfun$collect$1.apply(Dataset.scala:2783)
    at org.apache.spark.sql.Dataset$$anonfun$collect$1.apply(Dataset.scala:2783)
    at org.apache.spark.sql.Dataset$$anonfun$53.apply(Dataset.scala:3365)
    at org.apache.spark.sql.execution.SQLExecution$$anonfun$withNewExecutionId$1.apply(SQLExecution.scala:78)
    at org.apache.spark.sql.execution.SQLExecution$.withSQLConfPropagated(SQLExecution.scala:125)
    at org.apache.spark.sql.execution.SQLExecution$.withNewExecutionId(SQLExecution.scala:73)
    at org.apache.spark.sql.Dataset.withAction(Dataset.scala:3364)
    at org.apache.spark.sql.Dataset.collect(Dataset.scala:2783)

Apache Commons-lang3 提供的 StopWatch 执行时间监视器,以及 Spring 提供的 StopWatch 分析

Apache Commons-lang3 提供的 StopWatch 执行时间监视器,以及 Spring 提供的 StopWatch 分析

高春辉、王春生、朱峰:关于开源创业的 15 件小事

编码过程中我们经常会希望得到一段代码(一个方法)的执行时间,本文将介绍两种时间监视器(秒表)来让你优雅的、灵活的处理这个问题。

Java 源生方式
这种方式最最简单,最好理解,当然也是最为常用:我们自己书写。
例如:我们如果要统计一段代码的执行时间,经常会这么来写:

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis ();   // 获取开始时间

        // 函数主体代码
        //...

        long endTime = System.currentTimeMillis (); // 获取结束时间
        System.out.println ("程序运行时间:" + (endTime - startTime) + "ms");
    }

大多数时候我们使用 ms 来表示即可,但是这么写缺乏灵活性。倘若我们要展示成纳秒、秒、甚至分钟,还得我们自己处理(把毫秒值拿来进行转换~)

当然可能到了 JDK8 以后,我们这么做能变得稍微灵活一些:可以这么处理:

    public static void main(String[] args) {
        Instant start = Instant.now();
        //doSomething();
        Instant end = Instant.now();

        Duration duration = Duration.between(start, end);
        System.out.println("millis = " + duration.toMillis());
    }
1
2
3
4
5
6
7
8
这个比上面灵活度强一些。但也还是有一定的缺点:步骤稍显复杂,总体上还是不够优雅,也不是那么的灵活。
那么本文针对此问题介绍一个工具:StopWatch 执行时间监视器。借助它来统计我们程序的执行时间,带给非常多的方便和优雅。

StopWatch 需要依赖额外的 Jar:commons-lang3 或者 spring-core,但因这两个 Jar 是 Java 开发中都必导的,因此依赖兼容性方面可以忽略

StopWatch 有很多开源的框架都有提供类似的功能:比如 Apache 的 commons-lang3,当然还有 Spring framwork 自己提供的,本文将针对此俩分别做介绍~

Commons-lang3 的 StopWatch
Apache 提供的这个任务执行监视器功能丰富强大(比 Spring 的强大),灵活性强,如下经典实用案例:

    public static void main(String[] args) throws Exception {
        StopWatch watch = StopWatch.createStarted (); // 创建后立即 start,常用
        //StopWatch watch = new StopWatch();
        //watch.start();

        Thread.sleep(1000);
        System.out.println ("统计从开始到现在运行时间:" + watch.getTime () + "ms"); //1000ms

        Thread.sleep(1000);
        watch.split();
        System.out.println ("从 start 到此刻为止的时间:" + watch.getTime ());
        System.out.println ("从开始到第一个切入点运行时间:" + watch.getSplitTime ()); //2245

        Thread.sleep(1000);
        watch.split();
        System.out.println ("从开始到第二个切入点运行时间:" + watch.getSplitTime ());

        watch.reset (); // 重置后必须使用 start 方法
        watch.start();
        Thread.sleep(1000);
        System.out.println ("重新开始后到当前运行时间是:" + watch.getTime ()); //1000

        watch.suspend (); // 暂停
        Thread.sleep (6000); // 模拟暂停 6 秒钟

        watch.resume (); // 上面 suspend,这里要想重新统计,需要恢复一下
        System.out.println ("恢复后执行的时间是:" + watch.getTime ()); //1000  注意此时这个值还是 1000

        watch.stop();
        System.out.println ("花费的时间》》" + watch.getTime () + "ms"); //1002ms
        System.out.println ("花费的时间》》" + watch.getTime (TimeUnit.SECONDS) + "s"); //1s 可以直接转成 s

    }

打印结果:

统计从开始到现在运行时间:1007ms
从 start 到此刻为止的时间:2008
从开始到第一个切入点运行时间:2008
从开始到第二个切入点运行时间:3009
重新开始后到当前运行时间是:1000
恢复后执行的时间是:1000
花费的时间》》1001ms
花费的时间》》1s


如上就是 StopWatch 的基本使用方法,足以见到了它的强大吧,当然使用起来复杂度也是提升了些的。

核心原理解释
原理相对简单,简单看看源码便知:

// @since 2.0
public class StopWatch {
    // @since 3.5  这个静态方法出现得稍微晚点哦~
    public static StopWatch createStarted() {
        final StopWatch sw = new StopWatch();
        sw.start();
        return sw;
    }

    // 这些成员变量是实现的核心~~~~~~~~~~~~~~
    private State runningState = State.UNSTARTED;
    private SplitState splitState = SplitState.UNSPLIT;
    private long startTime;
    // 思考:为何有了 nonaTime 这里还得记录一个 Millis Time 呢???
    // 因为 nanoTime 只能拿来计算差值(耗时) 但是 getStartTime () 这个老 API 还得靠 MillsTime~~~
    private long startTimeMillis;
    private long stopTime;
    
    // 可见:start 方法可不是能够多次调用的哦~~和状态是有关的
    public void start() {
        if (this.runningState == State.STOPPED) {
            throw new IllegalStateException("Stopwatch must be reset before being restarted. ");
        }
        if (this.runningState != State.UNSTARTED) {
            throw new IllegalStateException("Stopwatch already started. ");
        }
        this.startTime = System.nanoTime();
        this.startTimeMillis = System.currentTimeMillis();
        this.runningState = State.RUNNING;
    }

    // 停表时,最重要的是记录下了 stopTime 的值~~~然后标记状态
    public void stop() {
        if (this.runningState != State.RUNNING && this.runningState != State.SUSPENDED) {
            throw new IllegalStateException("Stopwatch is not running. ");
        }
        if (this.runningState == State.RUNNING) {
            this.stopTime = System.nanoTime();
        }
        this.runningState = State.STOPPED;
    }

    // 状态变为非开始状态...
    public void reset() {
        this.runningState = State.UNSTARTED;
        this.splitState = SplitState.UNSPLIT;
    }

    // 暂停:stopTime 也给了一个值
    public void suspend() {
        if (this.runningState != State.RUNNING) {
            throw new IllegalStateException("Stopwatch must be running to suspend. ");
        }
        this.stopTime = System.nanoTime();
        this.runningState = State.SUSPENDED;
    }

    // 这两个方法是获取差值的
    public long getTime() {
        return getNanoTime() / NANO_2_MILLIS;
    }
    // @since 3.5
    public long getTime(final TimeUnit timeUnit) {
        return timeUnit.convert(getNanoTime(), TimeUnit.NANOSECONDS);
    }

    // @since 2.4 老 API  这叫获取启动的时间(啥时候启动的)
    public long getStartTime() {
        if (this.runningState == State.UNSTARTED) {
            throw new IllegalStateException("Stopwatch has not been started");
        }
        // System.nanoTime is for elapsed time
        return this.startTimeMillis;
    }
}

可以看到原理是很简单的,无非就是包装了暂停、回复、split 等功能嘛

使用细节
getTime 和 getSplitTime 有啥区别呢?
为了说明问题,此处我们看看 getNanoTime () 和 getSplitNanoTime () 亦可:

    public long getNanoTime() {
        if (this.runningState == State.STOPPED || this.runningState == State.SUSPENDED) {
            return this.stopTime - this.startTime;
        } else if (this.runningState == State.UNSTARTED) {
            return 0;
        } else if (this.runningState == State.RUNNING) {
            return System.nanoTime() - this.startTime;
        }
        throw new RuntimeException("Illegal running state has occurred.");
    }

     public long getSplitNanoTime() {
        if (this.splitState != SplitState.SPLIT) {
            throw new IllegalStateException("Stopwatch must be split to get the split time. ");
        }
        return this.stopTime - this.startTime;
    }

我们发现:

调用 getSplit... 相关方法前,必须先调用 Split 方法
spilit () 方法源码如下:

    public void split() {
        if (this.runningState != State.RUNNING) {
            throw new IllegalStateException("Stopwatch is not running. ");
        }
        this.stopTime = System.nanoTime();
        this.splitState = SplitState.SPLIT;
    }

在调用 split 方法后,watch 的状态改为了 SPLIT。且,且,且 stopTime 设置为了当前时间。因此此处我们的 stopTime 停止了,这个时候调用 getSplitNanoTime (),返回的是 start 到 split 那时的时间差值。因此用此方法可以插入先停止 stopTime ()(有点插队的赶脚),最后再输出(先插好队,最后在输出)~

而 getTime () 就是拿当前的时间戳,减去 startTime,一般不涉及到 stopTime 的值,因此 splitTime 处理计算时间显然更加的灵活,但是,一般我们使用 getTime () 就足够了

Spring 的 StopWatch
Spring 提供的这个任务监视器,我还是蛮喜欢使用的,因为一个它能够帮我同事监控多个任务,使用起来也很方便。先看一个简单的使用案例:

注意:一个监视器能够记录多个任务的执行时间这个特点非常重要哦~
比如:我们可以记录多段代码耗时时间,然后一次性打印~

    public static void main(String[] args) throws Exception {
        // 强烈每一个秒表都给一个 id,这样查看日志起来能够更加的精确
        // 至于 Id 我觉得给 UUID 是可行的~
        StopWatch sw = new StopWatch(UUID.randomUUID().toString());

        sw.start ("起床");
        Thread.sleep(1000);
        System.out.println ("当前任务名称:" + sw.currentTaskName ());
        sw.stop();

        sw.start ("洗漱");
        Thread.sleep(2000);
        System.out.println ("当前任务名称:" + sw.currentTaskName ());
        sw.stop();

        sw.start ("锁门");
        Thread.sleep(500);
        System.out.println ("当前任务名称:" + sw.currentTaskName ());
        sw.stop();

        System.out.println (sw.prettyPrint ()); // 这个方法打印在我们记录日志时是非常友好的  还有百分比的分析哦
        System.out.println(sw.shortSummary());
        System.out.println (sw.currentTaskName ()); //stop 后它的值为 null


        // 最后一个任务的相关信息
        System.out.println(sw.getLastTaskName());
        System.out.println(sw.getLastTaskInfo());

        // 任务总的耗时  如果你想获取到每个任务详情(包括它的任务名、耗时等等)可使用
        System.out.println ("所有任务总耗时:" + sw.getTotalTimeMillis ());
        System.out.println ("任务总数:" + sw.getTaskCount ());
        System.out.println ("所有任务详情:" + sw.getTaskInfo ()); // 拿到所有的任务
    }

打印:

当前任务名称:起床
当前任务名称:洗漱
当前任务名称:锁门
StopWatch ''d6ba9412-d551-4ba7-8b0e-1b7ccb42855d'': running time (millis) = 3504
-----------------------------------------
ms     %     Task name
-----------------------------------------
01001  029%  起床
02000  057%  洗漱
00503  014%  锁门

StopWatch ''d6ba9412-d551-4ba7-8b0e-1b7ccb42855d'': running time (millis) = 3504
null
锁门
org.springframework.util.StopWatch$TaskInfo@2d554825
所有任务总耗时:3504
任务总数:3
所有任务详情:[Lorg.springframework.util.StopWatch$TaskInfo;@68837a77

我个人偏爱使用 Spring 提供的这个监视器,是因为它提供的 prettyPrint () 打印在日志里进行分析可以非常的直观,并且我觉得提供的多任务支持也更加实用一点,当然仅仅个人偏好而已~
 

base.Stopwatch.<init>()V from class org.apache.hadoop.mapred.FileInputFormat 》??

base.Stopwatch.()V from class org.apache.hadoop.mapred.FileInputFormat 》??

IllegalAccessError: tried to access method com.google.common.base.Stopwatch.<init>()V from class org.apache.hadoop.mapred.FileInputFormat
    at org.apache.hadoop.mapred.FileInputFormat.getSplits(FileInputFormat.java:312)
    at org.apache.spark.rdd.HadoopRDD.getPartitions(HadoopRDD.scala:204)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
    at scala.Option.getOrElse(Option.scala:121)
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:251)
    at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
    at scala.Option.getOrElse(Option.scala:121)
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:251)
    at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
    at scala.Option.getOrElse(Option.scala:121)
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:251)
    at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
    at scala.Option.getOrElse(Option.scala:121)
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:251)
    at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
    at scala.Option.getOrElse(Option.scala:121)

C# StopWatch 的使用

C# StopWatch 的使用

使用 StopWatch 类,可以计时,需引入 System.Diagnostics 命名空间。

static void Main(string[] args)
        {
            Console.WriteLine("Main Start....");
            Stopwatch sw = new Stopwatch();
            sw.Start();
            Thread.Sleep(3000);
            sw.Stop();
            Console.WriteLine("time elapsed "+sw.ElapsedMilliseconds);
            sw.Restart();                            //置0,并重新开始计时,     如果直接使用Start(),必须先调用Reset()置0
            Thread.Sleep(3000);
            sw.Stop();
            Console.WriteLine("Main end...." + sw.Elapsed);
            Console.ReadLine();
        }

运行结果:

Main Start....
time elapsed 3004
Main end....00:00:03.0093181

关于Stopwatch.GetTimestamp() 在 linux 和 windows 上产生不同的结果linux watchdog timeout的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于.google.common.base.Stopwatch.()V from class org.apache.hadoop.mapred.FileInputFormat、Apache Commons-lang3 提供的 StopWatch 执行时间监视器,以及 Spring 提供的 StopWatch 分析、base.Stopwatch.()V from class org.apache.hadoop.mapred.FileInputFormat 》??、C# StopWatch 的使用等相关内容,可以在本站寻找。

本文标签: