如何使用Java中的System.nanoTime()增加事件的频率发射?

问题描述 投票:0回答:1

我创建了一个Java程序来以特定的频率发出事件。我使用System.nanoTime()而不是Thread.sleep(),因为根据许多参考herehere,第一个间隔的精度更高。但是,我想当我尝试将其设置为发出每秒1M记录的数据速率时,并没有达到目标。这是我的代码:

long delayInNanoSeconds = 1000000;

private void generateTaxiRideEvent(SourceContext<TaxiRide> sourceContext) throws Exception {
    gzipStream = new GZIPInputStream(new FileInputStream(dataFilePath));
    reader = new BufferedReader(new InputStreamReader(gzipStream, StandardCharsets.UTF_8));
    String line;
    TaxiRide taxiRide;
    while (reader.ready() && (line = reader.readLine()) != null) {
        taxiRide = TaxiRide.fromString(line);
        sourceContext.collectWithTimestamp(taxiRide, getEventTime(taxiRide));
        // sleep in nanoseconds to have a reproducible data rate for the data source
        this.dataRateListener.busySleep();
    }
}

public void busySleep() {
    final long startTime = System.nanoTime();
    while ((System.nanoTime() - startTime) < this.delayInNanoSeconds) ;
}

因此,当我在delayInNanoSeconds变量中等待10000纳秒时,我将获得100K的工作量记录/秒(1_000_000_000 / 10_000 = 100K r / s)。当我在delayInNanoSeconds变量中等待2000纳秒时,我将获得500K rec / sec(1_000_000_000 / 2_000 = 500K r / s)。 1000纳秒的工作量将达到1M记录/秒(1_000_000_000 / 1000 = 1M r / s)。 500纳秒的工作量为2M rec / sec(1_000_000_000 / 500 = 2M r / s)。

[我看到here,最好使用double而不是long来提高精度。有关系吗?还是问题仅仅是操作系统限制(我正在使用Linux Ubuntu 18)?也许是因为我正在使用readLine()方法并且有一种更快的方法来发出这些事件?我认为当我使用GZIPInputStream类时,我正在将整个文件加载到内存中,并且readLine()不再访问磁盘。如何提高应用程序的数据速率?

java performance delay benchmarking timedelay
1个回答
0
投票

@@ TobiasGeiselmann提出了一个很好的观点:您的延迟计算未考虑花费的时间之间调用busySleep

您应该计算相对于上一个截止日期的截止日期,而不是当前时间after记录。也不要使用前一个System.nanoTime()的结果;那将是>>实际截止日期的一段时间,因此您将以这种方式积累错误。

在第一次迭代之前,找到当前时间并设置long deadline = System.nanoTime() + 1000;。在此之后的每个迭代中,执行deadline += 1000;并使用您的busy-wait循环旋转直到现在> =截止日期。


如果您的系统足够快以在每次迭代中运行一次获得时间的功能时保持运转,这将起作用。如果不是,那么您可以每4次迭代检查一次截止时间(循环展开),以摊销nanoTime()的费用,因此您要登录4次或类似的突发事件。

当然,即使您仅使用no延迟调用,您的系统仍然不够快,您需要优化一些方法来解决此问题。您不能延迟很短的时间,并且检查时钟本身会花费一些时间。

© www.soinside.com 2019 - 2024. All rights reserved.