我正在尝试对我们的客户代码进行基准测试。因此,我决定编写一个多线程程序来对我的客户端代码进行基准测试。我正在尝试测量time (95 Percentile)
下面的方法需要多少?
attributes = deClient.getDEAttributes(columnsList);
因此,下面是我编写的用于对上述方法进行基准测试的多线程代码。在两种情况下,我看到了很多变化-
1)首先,使用20 threads
和来处理多线程代码running for 15 minutes
。我得到95%的37ms
。我正在使用-
ExecutorService service = Executors.newFixedThreadPool(20);
2)但是,如果我运行相同的程序以15 minutes
使用-
ExecutorService service = Executors.newSingleThreadExecutor();
代替
ExecutorService service = Executors.newFixedThreadPool(20);
7ms
当我使用运行代码时,我得到95%,比上面的数字要少得多newFixedThreadPool(20)
。
谁能告诉我以下原因导致此类高性能问题的原因是什么?
newSingleThreadExecutor vs newFixedThreadPool(20)
而且通过两种方式我都运行我的程序15 minutes
。
以下是我的代码-
public static void main(String[] args) {
try {
// create thread pool with given size
//ExecutorService service = Executors.newFixedThreadPool(20);
ExecutorService service = Executors.newSingleThreadExecutor();
long startTime = System.currentTimeMillis();
long endTime = startTime + (15 * 60 * 1000);//Running for 15 minutes
for (int i = 0; i < threads; i++) {
service.submit(new ServiceTask(endTime, serviceList));
}
// wait for termination
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) {
} catch (Exception e) {
}
}
下面是实现Runnable接口的类-
class ServiceTask implements Runnable {
private static final Logger LOG = Logger.getLogger(ServiceTask.class.getName());
private static Random random = new SecureRandom();
public static volatile AtomicInteger countSize = new AtomicInteger();
private final long endTime;
private final LinkedHashMap<String, ServiceInfo> tableLists;
public static ConcurrentHashMap<Long, Long> selectHistogram = new ConcurrentHashMap<Long, Long>();
public ServiceTask(long endTime, LinkedHashMap<String, ServiceInfo> tableList) {
this.endTime = endTime;
this.tableLists = tableList;
}
@Override
public void run() {
try {
while (System.currentTimeMillis() <= endTime) {
double randomNumber = random.nextDouble() * 100.0;
ServiceInfo service = selectRandomService(randomNumber);
final String id = generateRandomId(random);
final List<String> columnsList = getColumns(service.getColumns());
List<DEAttribute<?>> attributes = null;
DEKey bk = new DEKey(service.getKeys(), id);
List<DEKey> list = new ArrayList<DEKey>();
list.add(bk);
Client deClient = new Client(list);
final long start = System.nanoTime();
attributes = deClient.getDEAttributes(columnsList);
final long end = System.nanoTime() - start;
final long key = end / 1000000L;
boolean done = false;
while(!done) {
Long oldValue = selectHistogram.putIfAbsent(key, 1L);
if(oldValue != null) {
done = selectHistogram.replace(key, oldValue, oldValue + 1);
} else {
done = true;
}
}
countSize.getAndAdd(attributes.size());
handleDEAttribute(attributes);
if (BEServiceLnP.sleepTime > 0L) {
Thread.sleep(BEServiceLnP.sleepTime);
}
}
} catch (Exception e) {
}
}
}
更新:-
这是我的处理器规格-我正在Linux机器上运行程序,其中2个处理器定义为:
vendor_id : GenuineIntel
cpu family : 6
model : 45
model name : Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz
stepping : 7
cpu MHz : 2599.999
cache size : 20480 KB
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology tsc_reliable nonstop_tsc aperfmperf pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes hypervisor lahf_lm arat pln pts
bogomips : 5199.99
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management:
谁能告诉我
newSingleThreadExecutor
vs 如此高性能问题的原因是什么newFixedThreadPool(20)
?
如果并行运行的任务(如果是20个)比处理器(我怀疑您有20个以上的处理器)要多得多,那么是的,每个单独的任务将需要更长的时间才能完成。对于计算机而言,一次执行一个任务比在同时运行的多个线程之间切换要容易得多。即使将池中的线程数限制为拥有的CPU数,每个任务的运行速度可能也会变慢,尽管会略有降低。
但是,如果比较不同大小的线程池的 吞吐量
(完成多个任务所需的时间),则应该看到20个线程的吞吐量应该更高。如果您用20个线程执行1000个任务,则总体而言,完成任务要比仅使用1个线程快得多。每个任务可能需要更长的时间,但它们将并行执行。给定线程开销等,它可能不会快20倍,但是可能快15倍。
您不必担心单个任务的速度,而应该通过调整池中的线程数来尝试最大化任务吞吐量。使用多少线程在很大程度上取决于IO数量,每个任务使用的CPU周期,锁,同步块,在OS上运行的其他应用程序以及其他因素。
就池中的线程数而言,人们通常会使用1-2倍的CPU作为启动内存的最佳位置,以最大程度地提高吞吐量。更多的IO请求或线程阻塞操作将添加更多的线程。更多的CPU绑定将减少线程数,使其更接近可用的CPU数。如果您的应用程序正在与服务器上其他更重要的应用程序竞争OS周期,则可能需要更少的线程。
可以通过调用Executors类的静态newFixedThreadPool()方法获得固定的线程池。 语法 (Syntax) ExecutorService fixedPool = Executors.newFixedThreadPool(2); 哪里 最多2个线程将处于活动状态以处理任务。 如果提交的线程超过2个,则它们将保留在队列中,直到线程可用。 如果线程在执行器执行关闭期间因故障而终止,
可以通过调用Executors类的静态newSingleThreadExecutor()方法来获取单个线程池。 语法 (Syntax) ExecutorService executor = Executors.newSingleThreadExecutor(); 其中newSingleThreadExecutor方法创建一次执行单个任务的执行程序。 例子 (Example) 以下TestThre
我试着使用ActiveMQ组件(在Spring Boot内部),但最终得到了一些奇怪的结果。 1-我从SEDA发送了2000条消息到目的地队列 我是这样做的: 2-现在我尝试使用中的这些文件,我将这样做: 所以我的问题是: 1-为什么我将文件发送到队列时速度非常慢?但我可以如此快速地使用这些消息(在这个测试中,它比以前快了50倍多)!!! 我在笔记本电脑上消费和生产了这两种东西。 任何帮助都将不胜
问题内容: 我读到React非常快。最近,我写了一个应用程序来测试对角的反应。不幸的是,我发现反应的表现要慢于角度反应。 http://shojib.github.io/ngJS/#/speedtest/react/1 这是react的源代码。我是新来的人。我确定我的反应代码在这里做错了。我发现它异常缓慢。 https://jsbin.com/viviva/edit?js,输出 看看是否有任何反应
问题内容: 最近,我在查询性能方面遇到了一些问题。经过长时间的努力,我终于发现带有select前缀的查询如下: 是慢300倍,然后以这种方式启动查询: 有人可以帮我吗,为什么呢?关于此的一些外部文档将非常有用。 用于测试的表是: SALES_UNIT 表包含一些基本的信息 自动售货机 节点,例如名称等。唯一的关联是表SALES_UNIT_TYPE,例如ManyToOne。主键是ID和字段VALID
问题内容: 我们有一个本机应用程序,它使用GPU(OpenCL)通过一种特定的方法处理大数据,并且运行得很好,没有问题。该项目的一部分(网络和分发)由进行开发,我们只需要调用本机应用程序/库即可。 我们试图使用类将其称为独立的外部过程。问题是我们无法控制应用程序(事件,处理程序,线程等)。我们还尝试将C代码转换为Java代码,但是性能下降了。除了将本机代码作为进程运行之外,我还在考虑JNA和JNI