gpt4 book ai didi

java - 执行器框架在性能测试中增加了大量时间?

转载 作者:行者123 更新时间:2023-12-01 13:36:26 25 4
gpt4 key购买 nike

我正在开发一个项目,在该项目中我尝试使用 RestTemplate 对我的一台服务器进行 URL 调用它给我返回一个 JSON 字符串作为响应,并且工作正常......

现在我决定对此进行一些性能测试......

下面是我的代码,它使用 ExecutorServiceCallables -

public class URLTest {

private ExecutorService executor = Executors.newFixedThreadPool(10);

public String getData() {
Future<String> future = executor.submit(new Task());
String response = null;

try {
System.out.println("Started..");
response = future.get(200, TimeUnit.MILLISECONDS);
System.out.println("Finished!");
} catch (TimeoutException e) {
System.out.println("Terminated!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}

return response;
}
}

下面是我的任务类,它实现了 Callable 接口(interface) -

class Task implements Callable<String> {

private RestTemplate restTemplate = new RestTemplate();

public String call() throws Exception {
String url = "some_url";
// TimerTest timer = TimerTest.getInstance(); // line 3
String response = restTemplate.getForObject(url, String.class);
// timer.getDuration(); // line 4
System.out.println(response);

return response;

}
}

下面是我在另一个类中的代码 DemoTest它调用 getData URLTest中的方法类500 times并测量它的第 95 个百分位数,因为这就是我需要做的 -

public class DemoTest { 
public static void main(String[] args) {

URLTest bc = new URLTest();
for (int i = 0; i <= 500; i++) {
TimerTest timer = TimerTest.getInstance(); // line 1
bc.getData();
timer.getDuration(); // line 2
}

// this method prints out the 95th percentile
logPercentileInfo();

}
}

按照上面的代码,我总是将第 95 个百分位数视为 14-15 ms (这对我的用例不利,因为它是端到端流程,这就是我需要测量的)但是如果我注释掉 line 1line 2DemoTest类并取消注释 line 3line 4Task类,然后再次运行该程序,它将开始给我第 95 个百分位,如 3 ms .

我很惊讶为什么?是ExectuorFramework在这里添加所有延迟?为什么如果我只测量 RestTemplate 的性能调用,那么与端到端性能相比,它总是能给我更好的性能?

我的主要目标是尽可能减少这里的延迟。我的用例很简单,对我的一台启用了超时功能的服务器进行 URL 调用,这意味着服务器是否需要花费大量时间来响应,然后使整个调用超时。

我的客户端程序和服务器都在同一数据中心的生产环境中运行,因此 ping 时间约为 0.5 毫秒。

我运行了几次来进行此测试,但结果仍然相同..

有什么我遗漏的东西或者ExecutorService的其他风格吗?我需要使用吗?我怎样才能提高我在这里的表现?任何建议都会有很大帮助..

更新:-

添加了一些预热时间 -

   public static void main(String[] args) {

URLTest bc = new URLTest();

// little bit warmup
for (int i = 0; i <= 500; i++) {
bc.getData();
}

for (int i = 0; i <= 500; i++) {
TimerTest timer = TimerTest.getInstance();
bc.getData();
timer.getDuration();
}

logPercentileInfo();

}

最佳答案

ExecutorService 正在增加延迟,因为它必须管理工作线程和工作队列。

但这不应该是 12ms 差异的原因。

据我所知,这里存在几个问题:

  • maaartinus 提到您的池已“饱和”。但对我来说,情况似乎恰恰相反:每个任务都被提交,提交线程正在等待(通过 future.get)直到任务完成
  • 计时器的分辨率可能太低,无法可靠地测量 <10 毫秒的时间跨度(这取决于多个因素 - 特别是据说 Windows 系统的计时器分辨率相对较低)
  • 在一种情况下,您正在测量 System.out.println(response) 的时间,而在另一种情况下,您则没有测量

编辑:根据评论中的要求,ExecutorCompletionService 的示例:

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


public class ExecutorCompletionExample
{
public static void main(String[] args)
{
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletionService<String> completionService =
new ExecutorCompletionService<String>(executor);

int n = 500;
for (int i = 0; i < n; i++)
{
Task task = new Task("Task"+i);
completionService.submit(task);
}


for (int i = 0; i < n; ++i)
{
try
{
Future<String> future = completionService.take();
String response = future.get();
System.out.println("Response: "+response);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
return;
}
catch (ExecutionException e)
{
e.printStackTrace();
}
}
}
}


class Task implements Callable<String>
{
private static Random random = new Random(0);

private String name;
private long delay;

Task(String name)
{
this.name = name;
this.delay = 10 + random.nextInt(10)*10;
}
public String call() throws Exception
{
//String response = restTemplate.getForObject(url, String.class);
Thread.sleep(delay);
String response = "Response of "+name+" with delay "+delay;
return response;
}
}

用法相当简单,据我了解,最初的问题涉及到与 CompletionService 接口(interface)的描述相对应的任务:

"A service that decouples the production of new asynchronous tasks from the consumption of the results of completed tasks. .. A CompletionService can for example be used to manage asynchronous IO, in which tasks that perform reads are submitted in one part of a program or system, and then acted upon in a different part of the program when the reads complete, possibly in a different order than they were requested."

无法根据给定的示例来测试这是否真正符合预期的用例(当然,它是否有助于实现所需的总体延迟减少)。

关于java - 执行器框架在性能测试中增加了大量时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21231135/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com