[英]What is the point of Apache Lang3 StopWatch.split()?
I am currently evaluating implementations between Apache StopWatch and Guava's Stopwatch and the split functionality in the former intrigued me, but I am struggling to understand what exactly it does, and what value it has.我目前正在评估 Apache 秒表和番石榴的秒表之间的实现,前者的拆分功能让我很感兴趣,但我很难理解它到底做了什么,以及它有什么价值。
According to the documentation for StopWatch: https://commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/time/StopWatch.html根据秒表的文档: https://commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/time/StopWatch.ZD2535FDC70AD5FC27988E
split() the watch to get the time whilst the watch continues in the background.
split() 手表在后台继续运行时获取时间。 unsplit() will remove the effect of the split.
unsplit() 将删除拆分的效果。 At this point, these three options are available again.
此时,这三个选项再次可用。
And I found some examples, such as this , which offer very little, since it appears split is just cumulative.我发现了一些例子,比如this ,它提供的很少,因为它看起来 split 只是累积的。 The page says the method is for "splitting the time", which I figured as much based on the method, but the page makes no mention to what that actually means.
该页面说该方法用于“分割时间”,我根据该方法得出了同样多的结论,但该页面没有提及这实际上意味着什么。 It would even appear that this example is utterly wrong, because the docs suggest that you should
unsplit
before you split
again.甚至看起来这个例子是完全错误的,因为文档建议你应该在再次
unsplit
之前取消split
。
I initially thought it was for the following usecase:我最初认为它适用于以下用例:
StopWatch stopwatch = StopWatch.createStarted();
do something for 5 seconds
stopwatch.split();
do something for 10 seconds
stopwatch.stop();
System.out.println(stopwatch.getTime());
System.out.println(stopwatch.getSplitTime());
I thought that stopwatch total time would read as 15 seconds, and stopwatch split time would read as either 10 or 5 seconds, but it appears that both methods output 15 seconds.我认为秒表总时间读作 15 秒,秒表分割时间读作 10 或 5 秒,但似乎这两种方法 output 都是 15 秒。
Next, I thought maybe the split value is a delta you can take, and then remove from the total timer, something like:接下来,我认为拆分值可能是您可以采用的增量,然后从总计时器中删除,例如:
StopWatch stopwatch = StopWatch.createStarted();
do something for 5 seconds
stopwatch.split();
do something for 10 seconds
stopwatch.unsplit();
stopwatch.stop();
System.out.println(stopwatch.getTime());
// System.out.println(stopwatch.getSplitTime()); errors because of unsplit
My thought here was that the split time would be 10 seconds, and when unsplit from the main timer, the main timer would read as 5 seconds... but this seems no different from a suspend()
call... I also tried this, and the timings remain the same nonetheless for me.我的想法是拆分时间为 10 秒,当从主计时器未拆分时,主计时器将读取为 5 秒......但这似乎与
suspend()
调用没有什么不同......我也试过这个,而且时间对我来说还是一样的。
Am I missing something here, or is my interpretation of what this is supposed to do all wrong?我在这里遗漏了什么,还是我对这应该做的事情的解释都是错误的?
This is the source code for getSplitTime()
( it calls this other function internally ):这是
getSplitTime()
的源代码(它在内部调用另一个 function ):
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;
}
So it will return stopTime-startTime
.所以它会返回
stopTime-startTime
。 Beware of stopTime
.当心
stopTime
。 It's the liar that's confusing you.是骗子让你困惑。
This is the code for stop()
:这是
stop()
的代码:
public void stop() {
if (this.runningState != State.RUNNING && this.runningState != State.SUSPENDED) {
throw new IllegalStateException("Stopwatch is not running. ");
}
if (this.runningState == State.RUNNING)
{
//is this the same stopTime getSplitTime uses? yep, it is
this.stopTime = System.nanoTime();
}
this.runningState = State.STOPPED;
}
What's happenning then?那会发生什么?
Calling stop()
updates the stopTime
variable and makes the stopwatch "forget" the last time it was splitted.调用
stop()
会更新stopTime
变量并使秒表“忘记”上次拆分的时间。
Both split()
and stop()
modify the same variable, stopTime
, which is overrided when you call stop()
at the end of your process. split()
和stop()
都修改了相同的变量stopTime
,当您在进程结束时调用stop()
时,该变量会被覆盖。
Although sharing the same variable may look wierd, it really makes sense, as an splittedTime
of an StopWatch
should never be bigger than the total elapsed time.尽管共享同一个变量可能看起来很奇怪,但它确实很有意义,因为
StopWatch
的splittedTime
永远不应大于总经过时间。 So it's a game regarding the order of the functions executed in the StopWatch
.所以这是一个关于
StopWatch
中执行的功能顺序的游戏。
This is the code for split()
, in order to see that both methods do use stopTime
:这是
split()
的代码,以便看到这两种方法都使用stopTime
:
public void split() {
if (this.runningState != State.RUNNING) {
throw new IllegalStateException("Stopwatch is not running. ");
}
this.stopTime = System.nanoTime(); // you again little f..
this.splitState = SplitState.SPLIT;
}
That's why this little adorable Apache liar shows you 15 seconds on the splittedTime: because stop()
updated the stopTime
variable getSplitTime()
will use to return its value.这就是为什么这个可爱的 Apache 骗子会在 splittedTime 上显示 15 秒:因为
stop()
更新了stopTime
变量getSplitTime()
将用于返回其值。 ( the first code snippet ) (第一个代码片段)
Note the simplicity of the split()
function ( this also barely answers OP's question ).请注意
split()
function 的简单性(这也几乎没有回答 OP 的问题)。 It is responsible of:它负责:
StopWatch
is running.StopWatch
是否正在运行。stopTime
.stopTime
。splitState
to SPLIT
.splitState
设置为SPLIT
。 TLDR lol
Calling getSplitTime()
before stopping the StopWatch
should show you the desired value :在停止
StopWatch
之前调用getSplitTime()
应该会显示所需的值:
stopTime
won't be updated by stop()
yet. stopTime
不会被stop()
更新。split()
and the startTime
.split()
和startTime
之间经过的时间。 Some examples: ( yes, editing at saturday night cause I need a social life )一些例子:(是的,周六晚上编辑,因为我需要社交生活)
StopWatch stopwatch = StopWatch.createStarted();
do something for 5 seconds
stopwatch.split(); //stopTime is updated [by split()]
System.out.println(stopwatch.getSplitTime()); // will show 5 seconds
do something for 10 seconds
System.out.println(stopwatch.getSplitTime()); // will also show 5 seconds
stopwatch.stop(); //stopTime is updated again [by stop()]
System.out.println(stopwatch.getTime()); // 15s
System.out.println(stopwatch.getSplitTime()); // 15s
Another one:另一个:
StopWatch stopwatch = StopWatch.createStarted();
do something for 5 seconds
stopwatch.split();
System.out.println(stopwatch.getSplitTime()); // 5s
do something for 10 seconds
stopwatch.split();
System.out.println(stopwatch.getSplitTime()); // 15s
do something for 1 second
stopwatch.stop();
System.out.println(stopwatch.getTime()); // 16s
And a last one.最后一个。 Mocked the time with
sleeps
, just for the fun, you know.用
sleeps
来嘲笑时间,只是为了好玩,你知道的。 I was so bored I really imported the apache jar in order to test this locally :我太无聊了,我真的进口了 apache jar 以便在本地进行测试:
StopWatch stopwatch = StopWatch.createStarted();
Thread.sleep(5000);
stopwatch.split();
System.out.println(stopwatch.getSplitTime()); // 5s
Thread.sleep(10000);
stopwatch.split();
System.out.println(stopwatch.getSplitTime()); // 15s
stopwatch.reset(); // allows the stopWatch to be started again
stopwatch.start(); // updates startTime
Thread.sleep(2000);
stopwatch.split();
System.out.println(stopwatch.getSplitTime()); // 2s
Thread.sleep(1000);
stopwatch.stop();
System.out.println(stopwatch.getTime()); // 3s
System.out.println(stopwatch.getSplitTime()); // 3s
//it was so fun putting the sleeps
Note that calling getSplitTime()
on an stopped Watch
won't throw any exception, because the method will only check wheter the splitState
is SPLIT
.请注意,在停止的
Watch
上调用getSplitTime()
不会引发任何异常,因为该方法只会检查splitState
是否为SPLIT
。
The confusion may be caused by these two facts:混淆可能是由以下两个事实引起的:
stop()
regardless of the SplitState
, making your last split()
futile without you being aware.stop()
而不管SplitState
,使您的最后一个split()
在您不知道的情况下徒劳无功。 Futile, I love that word.splittedTime
on an stopped watch (if it is still on SPLIT
state), when it really just will return the total elapsed time between the last start()
and the stopping time.splittedTime
(如果它仍处于SPLIT
状态),它实际上只会返回上次start()
和停止时间之间的总经过时间。 (little liar) In this scenario, where the stopwatch is stopped and splitted at the same time , getTime()
and getSplitTime()
will always show the same value when called after stop()
.在这种情况下,秒表同时停止和拆分,
getTime()
和getSplitTime()
在stop()
之后调用时将始终显示相同的值。
[Personal and subjective opinion] [个人和主观意见]
Let's say you have a Counters
class with different variables to check elapsed times.假设您有一个带有不同变量的
Counters
class 来检查经过的时间。 You also want to output the total elapsed time for each operation, every 60 seconds.您还希望 output 每次操作的总经过时间,每 60 秒。 In this example,
counters
is an instance of a Counters
class that owns two long
variables: fileTime
and sendTime
, that will accumulate the elapsed time within each operation during an specific interval ( 60s ).在此示例中,
counters
是Counters
class 的一个实例,它拥有两个long
变量: fileTime
和sendTime
,它们将在特定时间间隔 ( 60s ) 内累积每个操作中的经过时间。 This is just an example that assumes each iteration takes less than 1000 ms (so it will always show 60 seconds on the elapsed time):这只是一个假设每次迭代时间少于 1000 毫秒的示例(因此它总是显示经过时间为 60 秒):
long statsTimer = System.currentTimeMillis();
while (mustWork)
{
long elapsedStatsTimer = System.currentTimeMillis()-statsTimer; //hits 60185
if (elapsedStatsTimer > 60000)
{
//counters.showTimes()
System.out.println("Showing elapsed times for the last "+
(elapsedStatsTimer/1000)+ " secs"); //(60185/1000) - 60 secs
System.out.println("Files time: "+counters.fileTime+" ms"); //23695 ms
System.out.println("Send time : "+counters.sendTime+" ms"); //36280 ms
long workTime = counters.sendTime+counters.fileTime;
System.out.println("Work time : "+workTime+" ms"); //59975 ms
System.out.println("Others : "+(elapsedStatsTimer-workTime)+" ms"); //210 ms
//counters.reset()
counters.fileTime=0;
counters.sendTime=0;
statsTimer= System.currentTimeMillis();
}
long timer = System.currentTimeMillis();
//do something with a file
counters.fileTime+=System.currentTimeMillis-timer;
timer = System.currentTimeMillis();
//send a message
counters.sendTime+=System.currentTimeMillis()-timer;
}
That Counters
class could implement the reset()
and showTimes()
functions, in order to clean up the code above. Counters
class 可以实现reset()
和showTimes()
函数,以清理上面的代码。 It could also manage the elapsedStatsTimer
variable.它还可以管理
elapsedStatsTimer
变量。 This is just an example to simplify its behaviour.这只是简化其行为的示例。
For this use case, in which you need to measure different operations persistently , I think this way is easier to use and seems to have a similar performance, as the StopWatch
internally makes the exact same thing.对于这种需要持续测量不同操作的用例,我认为这种方式更易于使用并且似乎具有相似的性能,因为
StopWatch
在内部进行完全相同的事情。 But hey, it's just my way to do it: ).但是,嘿,这只是我的做法:)。
I will accept downvotes for this opinion in an honorable and futile way.我将以一种光荣和徒劳的方式接受对这一观点的反对票。
I would love to finish with a minute of silence in honour of unsplit()
, which may be one of the most irrelevant methods ever existed.我很想以一分钟的沉默来结束
unsplit()
,这可能是有史以来最不相关的方法之一。
[/Personal and subjective opinion] [/个人主观意见]
Just noticed TLDR
section is actually bigger than the previous section:_ )刚刚注意到
TLDR
部分实际上比上一部分大:_)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.