Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 解释性能差异_Java_Performance_Java 8_Java Stream - Fatal编程技术网

Java 解释性能差异

Java 解释性能差异,java,performance,java-8,java-stream,Java,Performance,Java 8,Java Stream,这是和 这些测试的时间安排千差万别,但要经过相同的实现。我想知道为什么时间不同 private static final int ITERATIONS = 100; private static final DataFactory RANDOM_DF = DataFactoryImpl.defaultInstance(); @Test // 6s public void testGetMaxLength() throws Exception { for ( int i = 1; i

这是和

这些测试的时间安排千差万别,但要经过相同的实现。我想知道为什么时间不同

private static final int ITERATIONS = 100;
private static final DataFactory RANDOM_DF = DataFactoryImpl.defaultInstance();


@Test // 6s
public void testGetMaxLength() throws Exception {
    for ( int i = 1; i < ITERATIONS; i++ ) {
        testGetMaxLength( i );
    }
}

private void testGetMaxLength( final int length ) {
    for ( int i = 0; i < ITERATIONS; i++ ) {
        String word = RANDOM_DF.word().getMaxLength( length );
        assertThat( word, not( isEmptyOrNullString() ) );
        assertThat( word.length(), allOf( greaterThanOrEqualTo( 1 ), lessThanOrEqualTo( length ) ) );
    }
}

@Test //  301ms
public void testGetLength() throws Exception {
    for ( int i = 1; i < ITERATIONS; i++ ) {
        testGetLength( i );
    }
}

private void testGetLength( final int length ) {
    for ( int i = 0; i < ITERATIONS; i++ ) {
        String word = RANDOM_DF.word().getLength( length );
        assertThat( word, not( isEmptyOrNullString() ) );
        assertThat( word.length(), equalTo( length ) );
下面是不同的实现

@FunctionalInterface
public interface RandomStringFactory {

    default String getMaxLength( final int maxInclusive ) {
        return this.getRange( 1, maxInclusive );
    }

    String getRange( final int minInclusive, final int maxInclusive );

    default String getLength( int length ) {
        return this.getRange( length, length );
    }
}
以及
word

DataFactoryImpl( final IntBinaryOperator randomSource, final List<String> wordSource ) {
    this.random = randomSource;
    this.wordSource = wordSource.stream().collect( Collectors.groupingBy( String::length ) );
}

public static DataFactory defaultInstance() {
    return new DataFactoryImpl( RandomUtils::nextInt, dict() );
}

default RandomStringFactory word() {
    return ( min, max ) -> valueFromMap( getWordSource(), ( size ) -> getRandom().applyAsInt( 0, size ), min, max )
            .orElse( alphabetic().getRange( min, max ) );


}

区别实际上在于您用来生成随机数的实现。如果
startInclusive
endInclusive
参数匹配(如
getLength()
),它只返回非常快的参数。否则,它请求
java.util.Random
对象的静态实例来获取随机数。
java.util.Random
是线程安全的,但存在非常严重的争用问题:您不能单独从不同的线程请求随机数:它们将在CAS循环中耗尽。当您在
值frommap
中使用
.parallelStream()
时,遇到了以下问题

此处应用的最简单修复方法是使用:

请注意,
ThreadLocalRandom.nextInt()
没有类似于
RandomUtils.nextInt()
的快速路径,因此如果要保留它,请使用:

new DataFactoryImpl( 
    (a, b) -> a == b ? a : ThreadLocalRandom.current().nextInt(a, b+1), dict() );
小心不要将
ThreadLocalRandom.current()
实例缓存在外部(如字段或静态变量):此调用必须在实际请求随机数的同一线程中执行

为什么这两种方法的测量结果如此不同 实现

嗯,考虑到你有一个“共享实现”来计算一组书籍中的页面。

在第一种情况下,这套书由一本书组成。你打开最后一页,看看它的编号,就这样!小菜一碟

在第二种情况下,给定的一套书籍是国家图书馆。。。这个类比有用吗


你的测试也是如此
testGetLength
选择具有给定长度的随机单词,其中所有单词都已按其长度分组

过滤器(e->e.getKey()>=minInclusive&&e.getKey()30)

testGetMaxLength
选择一个比给定长度短的随机单词。这类词汇的列表从来都不是空的。更糟糕的是,您的
flatMap+collect
将所有按长度的列表合并到一个非常大的组合列表中,并且此操作非常缓慢。您是否尝试过使用探查器

有什么方法可以改进getMaxLength的最坏情况吗


当然。但这需要对算法和使用的数据结构进行彻底的重新设计。例如,您可以按单词长度对所有词典进行排序,然后构建一个数组支持的索引,将一个长度映射到该长度单词的结果列表中的最后一个位置。在这种情况下,您将能够在一个恒定的时间内获得一个范围(1,maxLength)。

您是在问为什么流与并行流实现之间的时间不同,还是两个测试之间的时间不同?考虑到唯一的区别似乎是getLength和getMaxLength的调用,如果您使用其中一个@Xenotracide,那么遵循这一点也会更简单,这似乎是一个显而易见的地方。不幸的是,你还没有提供它们。是的,我可以看到,但这是非常困难的遵循所有级别的间接。本质上,您似乎在问为什么getRange(1,something)比getRange(something,something)慢。这可能是因为过滤器在后一种情况下会抛出很多东西吗?很难说,我们没有你的数据,你的代码又大又间接。@xenoterracide,再看一看事实上,我打赌如果你写了一个,你会很快看到性能差异的来源。看来我理解你的问题所在,但总的来说@pvg是正确的:在发布到SO之前,您应该尽可能简化代码。通常在简化过程中,您可以自己理解问题所在。因此,我将
defaultInstance
的实现替换为您的负1差
nextInt(a,b)
,而不是
b+1
,因为这会在从列表中请求值时导致随机越界。此实现需要
13s
publicstaticdatafactorydefaultinstance(){returnnewdatafactoryimpl((a,b)->a==b?a:ThreadLocalRandom.current().nextInt(a,b),dict());}
实际上一直在为此类问题寻找一个与Intellij Idea很好地集成的好分析器,从那时起。这是我遇到的为数不多的性能问题之一,我认为更需要一个分析器(问题是相对的,因为实际使用并不打算在一个循环中达到1000次)
public static DataFactory defaultInstance() {
    return new DataFactoryImpl( (a, b) -> a == b ? a :    ThreadLocalRandom.current().nextInt(a, b), dict() ); 
}
new DataFactoryImpl( (a, b) -> ThreadLocalRandom.current().nextInt(a, b+1), dict() );
new DataFactoryImpl( 
    (a, b) -> a == b ? a : ThreadLocalRandom.current().nextInt(a, b+1), dict() );