java获得电脑性能_Java:使用SingletonStream获得性能

java获得电脑性能

仅具有一个元素的Java流有时会在应用程序中造成不必要的开销。 了解如何使用SingletonStream对象并为其中某些流获得十倍的性能,并了解如何同时简化代码。

背景

Java 8中的Stream库是迄今为止Java语言最强大的功能之一。 一旦您开始了解它的多功能性和所产生的代码可读性,您的Java代码样式将永远改变。 与其使用forifswitch语句以及众多中间变量来充斥所有琐碎的细节,不如使用大量的细节,而可以使用Stream ,它仅包含要做什么的描述,而不是实际上是如何完成的。

SingletonStream

几年前,我们必须为Java项目做出API决定:我们应该为两种快速的本地内存数据缓存方法选择哪种返回类型?

  • 唯一的搜索键,返回一个值或不返回任何值
  • 一个非唯一的搜索键,它返回任意数量的值(零到无穷大)。

这是最初的想法:

Optional<T> searchUnique(K key); // For unique keys
Stream<T> search(K key);         // For non-unique keys

但是,我们希望这两个方法看起来完全相同,并且都返回一个
Stream<T> 。 然后,API看起来会更加整洁,因为唯一的高速缓存看上去与非唯一的高速缓存完全相同。

但是,唯一搜索必须非常高效,并且每秒必须创建数百万个结果对象,而又不会产生太多开销。

解决方案

通过实现仅包含单个元素的SingletonStream (因此,与具有任意数量元素的普通Stream相比,可以进行高度优化),我们能够让这两种方法在保持性能的同时返回Stream 。 如果未找到searchUnique(K key) ,方法searchUnique(K key)将返回一个空流( Stream.empty() ),并且如果该键存在,则它将返回一个SingletonStream及其值与键相关联。 我们会得到:

Stream<T> searchUnique(K key); // For unique keys
Stream<T> search(K key);       // For non-unique keys

大! 我们可以吃饼干,仍然可以吃!

实施

SingletonStream是Speedment Stream ORM的一部分,可以在GitHub上查看。 随意使用的Speedment自己的项目中使用Speedment任何它的组件的初始化

SingletonStream是使用JVM的Escape Analysis进行堆栈分配的不错选择(在我以前的文章中, 这里此处有关Escape Analysis的更多信息 )。 该实现有两种形式。 如果将STRICT值设置为true ,则会得到一个完全惰性的Stream ,但是缺点是,一旦调用诸如.filter(), map()中间操作 ,我们将失去Singleton属性 。另一方面,将STRICT值设置为falseSingletonStream会急切地执行许多中间操作,并且能够返回新的SingletonStream从而保留Singleton属性 。 在许多情况下,这将提供更好的性能。

这里为参考流设计的解决方案也可以很容易地修改为单例流的原始形式。 因此,编写SingletonIntStream
SingletonLongStreamSingletonDoubleStream 。 这是SingletonLongStream

应该注意的是,该类可以进一步发展,以便它可以支持惰性评估,同时始终保持高性能。 这是未来的工作。

性能

有多种方法可以测试SingletonStream的性能,并将其与具有一个元素的标准Stream实现进行比较。

这是使用JMH的一种方法。 第一个测试(计数)仅对流中的元素数量进行计数,第二个测试(forEach)对流中的一个元素执行某些操作。

@Benchmark
public long singletonStreamCount() {
    return SingletonStream.of("A").count();
}

@Benchmark
public long streamCount() {
    return Stream.of("A").count();
}

@Benchmark
public void singletonStreamForEach() {
    SingletonStream.of("A")
        .limit(1)
        .forEach(blackHole());
}

@Benchmark
public void streamForEach() {
   Stream.of("A")
        .limit(1)
        .forEach(blackHole());
}

private static <T> Consumer<T> blackHole() {
return t -> {};
}

在MacBook Pro笔记本电脑上运行时,将产生以下结果:

...
Benchmark                               Mode  Cnt           Score   Error  Units
SingletonBench.singletonStreamCount    thrpt        333419753.335          ops/s
SingletonBench.singletonStreamForEach  thrpt       2312262034.214          ops/s
SingletonBench.streamCount             thrpt         27453782.595          ops/s
SingletonBench.streamForEach           thrpt         26156364.956          ops/s
...

“计数”操作的加速因子超过10。 对于“ forEach”操作,看来JVM能够完全优化SingletonStream的完整代码路径。

测试一下

使用Speedment 初始化程序下载Speedment。

完整的测试课程在这里可用。

结论

SingletonStream或多或少地作为扩展的Optional起作用,并在保持Stream库优点的同时提供高性能。

您可以通过将STRICT值设置为首选的严格性/性能选择来选择它的两个版本。

SingletonStream可以进一步改进。

翻译自: https://www.javacodegeeks.com/2018/10/java-gain-performance-singletonstream.html

java获得电脑性能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值