- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在尝试通过实现生产者-消费者模式来提高软件的性能。在我的特定情况下,我有一个按顺序创建行的生产者和多个为给定批处理的行执行某些任务的消费者。
我现在面临的问题是,当我测量生产者-消费者模式的性能时,我可以看到生产者的运行时间大幅增加,但我不明白为什么会出现这种情况。
到目前为止,我主要分析了我的代码并进行了微基准测试,但结果并没有让我找到实际的问题。
public class ProdCons {
static class Row {
String[] _cols;
Row() {
_cols = Stream.generate(() -> "Row-Entry").limit(5).toArray(String[]::new);
}
}
static class Producer {
private static final int N_ITER = 8000000;
final ExecutorService _execService;
final int _batchSize;
final Function<Row[], Consumer> _f;
Producer(final int batchSize, final int nThreads, Function<Row[], Consumer> f) throws InterruptedException {
_execService = Executors.newFixedThreadPool(nThreads);
_batchSize = batchSize;
_f = f;
// init all threads to exclude their generaration time
startThreads();
}
private void startThreads() throws InterruptedException {
List<Callable<Void>> l = Stream.generate(() -> new Callable<Void>() {
@Override
public Void call() throws Exception {
Thread.sleep(10);
return null;
}
}).limit(4).collect(Collectors.toList());
_execService.invokeAll(l);
}
long run() throws InterruptedException {
final long start = System.nanoTime();
int idx = 0;
Row[] batch = new Row[_batchSize];
for (int i = 0; i < N_ITER; i++) {
batch[idx++] = new Row();
if (idx == _batchSize) {
_execService.submit(_f.apply(batch));
batch = new Row[_batchSize];
idx = 0;
}
}
final long time = System.nanoTime() - start;
_execService.shutdownNow();
_execService.awaitTermination(100, TimeUnit.MILLISECONDS);
return time;
}
}
static abstract class Consumer implements Callable<String> {
final Row[] _rowBatch;
Consumer(final Row[] data) {
_rowBatch = data;
}
}
static class NoOpConsumer extends Consumer {
NoOpConsumer(Row[] data) {
super(data);
}
@Override
public String call() throws Exception {
return null;
}
}
static class SomeConsumer extends Consumer {
SomeConsumer(Row[] data) {
super(data);
}
@Override
public String call() throws Exception {
String res = null;
for (int i = 0; i < 1000; i++) {
res = "";
for (final Row r : _rowBatch) {
for (final String s : r._cols) {
res += s;
}
}
}
return res;
}
}
public static void main(String[] args) throws InterruptedException {
final int nRuns = 10;
long totTime = 0;
for (int i = 0; i < nRuns; i++) {
totTime += new Producer(100, 1, (data) -> new NoOpConsumer(data)).run();
}
System.out.println("Avg time with NoOpConsumer:\t" + (totTime / 1000000000d) / nRuns + "s");
totTime = 0;
for (int i = 0; i < nRuns; i++) {
totTime += new Producer(100, 1, (data) -> new SomeConsumer(data)).run();
}
System.out.println("Avg time with SomeConsumer:\t" + (totTime / 1000000000d) / nRuns + "s");
}
实际上,由于消费者与生产者在不同的线程中运行,我希望生产者的运行时间不会受到消费者工作负载的影响。但是,运行该程序我得到以下输出
#1 线程,#100 批量大小
NoOpConsumer 的平均时间:0.7507254368s
与 SomeConsumer 的平均时间:1.5334749871s
请注意,时间测量仅测量生产时间,而不测量消费者时间,并且不提交任何作业需要平均时间。 ~0.6 秒。
更令人惊讶的是,当我将线程数量从 1 增加到 4 时,我得到以下结果(具有超线程的 4 核)。
#4 线程,#100 批量大小
NoOpConsumer 的平均时间:0.7741189636s
与 SomeConsumer 的平均时间:2.5561667638s
我做错了什么吗?我缺少什么?目前我必须相信运行时间差异是由于上下文切换或与我的系统相关的任何事情造成的。
最佳答案
线程之间并不是完全隔离的。
看起来您的 SomeConsumer
类分配了大量内存,这会产生在所有线程(包括生产者线程)之间共享的垃圾收集工作。
它还会访问大量内存,这可能会将生产者使用的内存从 L1 或 L2 缓存中剔除。访问实际内存比访问缓存花费的时间要长得多,因此这也会使您的生产者花费更长的时间。
另请注意,我实际上并未验证您是否正确测量了生产者时间,并且很容易在此处犯错误。
关于java - 为什么消费者会降低生产者的绩效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55677378/
我想知道在 Java 7 菱形运算符 与以前版本的 Java 的语言构造方面是否存在任何已知的性能差异。 基本上,使用这个是否更快: List myList = new ArrayList<>() M
我有一个巨大的应用程序,它使用 Entity Framework 4。它是服务器上的 WCF(托管在 Windows 服务中)和客户端上的 WPF。 它的某些部分很慢,我想知道是不是因为数据库访问很慢
我是一名优秀的程序员,十分优秀!