输入流输出流是以内存为标准_构建用于测试的超大内存输入流

输入流输出流是以内存为标准

由于某种原因,我需要非常大的,甚至可能是无限的InputStream ,它会反复地反复返回相同的byte[] 。 这样,我可以通过重复小样本来产生疯狂的大数据流。 可以在Guava中找到类似的功能: Iterable<T> Iterables.cycle(Iterable<T>)Iterator<T> Iterators.cycle(Iterator<T>) 。 例如,如果您需要01的无限来源,只需说出Iterables.cycle(0, 1)并无限获取Iterables.cycle(0, 1) 0, 1, 0, 1, 0, 1... 不幸的是,我还没有为InputStream找到这样的工具,所以我跳入自己编写的工具。 本文记录了我在此过程中犯的许多错误,主要是由于过于复杂和过度设计的简单解决方案。


我们实际上并不需要无限的InputStream ,能够创建非常大的InputStream (例如32 GiB)就足够了。 因此,我们采用以下方法:

public static InputStream repeat(byte[] sample, int times)

它基本上采用字节sample数组,并返回一个InputStream返回这些字节。 但是,当sample用完时,它将翻转,再次返回相同的字节-重复此过程指定的次数,直到InputStream信号结束。 我尚未真正尝试过但似乎最显而易见的一种解决方案:

public static InputStream repeat(byte[] sample, int times) {final byte[] allBytes = new byte[sample.length * times];for (int i = 0; i < times; i++) {System.arraycopy(sample, 0, allBytes, i * sample.length, sample.length);}return new ByteArrayInputStream(allBytes);
}

我看到你在那笑! 如果sample是100个字节,并且我们需要32 GiB的输入重复这100个字节,则生成的InputStream不应真正分配32 GiB的内存,我们在这里必须更加聪明。 实际上,上面的repeat()有另一个细微的错误。 Java中的数组限制为2 31 -1个条目( int ),比其高32 GiB。 该程序编译的原因是此处无声的整数溢出: sample.length * times 。 此乘法不适用于int

好的,让我们尝试至少在理论上可行的方法。 我的第一个想法是:如果我创建多个ByteArrayInputStream共享相同的byte[] sample (它们不进行急切的复制),然后以某种方式将它们连接在一起怎么办? 因此,我需要一些InputStream适配器,该适配器可以采用任意数量的基础InputStream并将它们链接在一起-当第一个流耗尽时,切换到下一个。 当您在Apache Commons或Guava中寻找某些东西,并且显然永远在JDK中时,这一尴尬时刻… java.io.SequenceInputStream几乎是理想的选择。 但是,它只能精确地链接两个基础InputStream 。 当然,由于SequenceInputStream本身就是InputStream ,我们可以递归地将其用作外部SequenceInputStream的参数。 重复此过程,我们可以将任意数量的ByteArrayInputStream在一起:

public static InputStream repeat(byte[] sample, int times) {if (times <= 1) {return new ByteArrayInputStream(sample);} else {return new SequenceInputStream(new ByteArrayInputStream(sample),repeat(sample, times - 1));}
}

如果times为1,则将sample包装在ByteArrayInputStream 。 否则,递归使用SequenceInputStream 。 我认为您可以立即发现此代码的问题:太深的递归。 嵌套级别与times参数相同,将达到数百万甚至数十亿。 肯定有更好的办法。 幸运的是,较小的改进将递归深度从O(n)更改为O(logn):

public static InputStream repeat(byte[] sample, int times) {if (times <= 1) {return new ByteArrayInputStream(sample);} else {return new SequenceInputStream(repeat(sample, times / 2),repeat(sample, times - times / 2));}
}

老实说,这是我尝试的第一个实现。 这是分而治之原理的简单应用 ,在这里我们将结果平均分成两个较小的子问题。 看起来很聪明,但是有一个问题:容易证明我们创建了t( t =timesByteArrayInputStreams和O(t) SequenceInputStream 。 共享sample字节数组时,数百万个各种InputStream实例浪费了内存。 这导致我们可以选择实现,无论times多少, InputStream创建一个InputStream

import com.google.common.collect.Iterators;
import org.apache.commons.lang3.ArrayUtils;public static InputStream repeat(byte[] sample, int times) {final Byte[] objArray = ArrayUtils.toObject(sample);final Iterator<Byte> infinite = Iterators.cycle(objArray);final Iterator<Byte> limited = Iterators.limit(infinite, sample.length * times);return new InputStream() {@Overridepublic int read() throws IOException {return limited.hasNext() ?limited.next() & 0xFF :-1;}};
}

毕竟,我们将使用Iterators.cycle() 。 但是在我们必须将byte[]转换为Byte[]因为迭代器只能与objets一起使用,而不能与原语一起使用。 没有惯用的方法ArrayUtils.toObject(byte[])语数组转换为盒装类型数组,因此我使用来自Apache Commons Lang的ArrayUtils.toObject(byte[]) 。 有了对象数组,我们可以创建一个infinite迭代器,循环遍历sample值。 由于我们不需要无限的流,因此再次使用了来自Guava的Iterators.limit(Iterator<T>, int)来切断无限迭代Iterators.limit(Iterator<T>, int) 。 现在,我们只需要从Iterator<Byte>InputStream进行桥接–毕竟它们在语义上代表同一件事。

该解决方案遭受两个问题。 首先,由于拆箱,它会产生大量垃圾。 垃圾回收并不太关心死的,短命的物品,但看起来仍然很浪费。 我们之前已经遇到的第二个问题: sample.length * times乘以倍数可能会导致整数溢出。 由于Iterators.limit()占用intlong ,因此没有固定的理由,因此无法修复。 顺便说一句,我们通过按位 0xFF避免了第三个问题-否则,值为-1 byte将表示流的结束,事实并非如此。 x & 0xFF已正确转换为无符号255int )。

因此,即使上面的实现是简短而甜美,声明式而不是命令式的,但它仍然太慢且受限制。 如果您有C背景,我可以想象您看到我挣扎时会感到多么不舒服。 在我最后想到的是最简单,痛苦的简单和低级的实现之后:

public static InputStream repeat(byte[] sample, int times) {return new InputStream() {private long pos = 0;private final long total = (long)sample.length * times;public int read() throws IOException {return pos < total ?sample[(int)(pos++ % sample.length)] :-1;}};
}

无GC的纯JDK,快速,简单易懂。 让这成为您的一个教训:从您想到的最简单的解决方案开始,不要过度设计并且不要太聪明。 我以前的解决方案(声明性,功能性,不变性等)–也许它们看起来很聪明,但是它们既不快速也不容易理解。

我们刚刚开发的实用程序不仅是一个玩具项目,还将在后续文章中使用 。

翻译自: https://www.javacodegeeks.com/2014/07/building-extremely-large-in-memory-inputstream-for-testing-purposes.html

输入流输出流是以内存为标准

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/340632.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

laravel 分词搜索匹配度_【地名地址】面向智慧城市的高精度地名地址匹配方法...

点击上方蓝字关注我们↑↑↑↑原 文 摘 要针对智慧城市建设中各种业务数据对地名地址匹配准确度和效率不高的问题&#xff0c;本文提出一种面向智慧城市的高精度地名地址匹配方法。该方法在基于中文分词的地名地址匹配技术框架下&#xff0c;综合利用精细化地名地址库构建、地名…

使用通用mapper实现条件查询_使用dsum轻松搞定多条件查询,学会它,再也想用sumifs了...

在excel中条件求和想必大家都不陌生&#xff0c;这个可以说是我们工作中经常遇到的问题&#xff0c;常见的条件求和函数有sumif以及sumifs&#xff0c;但是还有一个更加强但知道的人却非常少的函数&#xff0c;他就是dsum函数&#xff0c;dsum相交于sumif以及sumifs函数理解起来…

输入文字自动生成图片_批量生成变化的图片文字海报

最近“双十一”活动大家已经进入了鸡血状态&#xff0c;运营的小伙伴给设计出了个难题&#xff0c;搞的设计小伙伴们进入了癫狂模式。本着工具提升效率的原则&#xff0c;我又开始去研究如何批量修改图片内容了&#xff0c;小小的成果和大家分享一下。提出问题为每一位支付了定…

生成私钥 p q rsa_【安全】理解 RSA 算法

Public-key Crytography简介Public-key cryptography (公开密钥加密) 又称 asymmetric cryptography (非对称加密)&#xff0c;即存在两把不同的密钥&#xff0c;分别称为公钥 Pu 和私钥 Pr&#xff0c;公钥通常用来加密明文 M&#xff0c;只有私钥才能解密密文 C&#xff0c;如…

Java:如何创建轻量级数据库微服务

基于云的Java数据库应用程序的数量每分钟都在增加。 许多组织部署了数百甚至数千个微服务实例。 但是&#xff0c;相对于运行时环境&#xff0c;大多数应用程序会带来惊人数量的不必要开销。 反过来&#xff0c;这会使应用程序运行更慢&#xff0c;运行成本更高。 在本文中&am…

垃圾分类毕设java程序_垃圾“拍一拍”,分类不用愁!生活垃圾分类查询小程序上线啦...

垃圾种类太多&#xff1f;分类容易搞混&#xff1f;乐清人 注意啦&#xff0c;拿起手机就能查&#xff01;11月6日&#xff0c;生活垃圾分类查询系统登陆乐清市综合行政执法局官方微信公众号&#xff0c;输入垃圾名称即可快速了解垃圾所属哪一类&#xff0c;还有拍照识别查询&a…

带有Prometheus的弹簧靴和千分尺第5部分:旋转Prometheus

以前&#xff0c;我们获得了Spring Boot Application适配器&#xff0c;以便为Prometheus公开端点。 该博客将重点介绍如何设置和配置Prometheus&#xff0c;以便为Spring Boot端点提供服务器。 因此&#xff0c;让我们开始使用docker来启动Prometheus服务器。 在继续进行Pr…

允许跨域访问_PHP设置多域名允许跨域访问

php中文网最新课程 每日17点准时技术干货分享 针对 PHP 语言设置多域名允许跨域访问 服务器变量: 服务器变量存储在 $_SERVER 数组中,在这个数组中有一个特殊的键值:HTTP_ORIGIN。 这个键只在跨域的时候才会存在值,同源时为空字符串 响应头设置允许某域名访问:access-cont…

python函数的作用降低编程复杂度_Python函数式编程

lambda本文将介绍Python中函数式编程的特性。在对函数式编程的概念有了了解后&#xff0c;本文会介绍iterators和generators等语言特性&#xff0c;还有itertools和functools等相关的库。函数式编程本章节将会介绍函数式编程的一些基本概念&#xff1b;如果只是对Python的语言特…

Apache Camel 3.1 –即将推出更多骆驼核心优化

希望一切都很好&#xff0c;您可以安全进入2020年。 Camel团队已经在忙于开发下一个Camel 3.1版本。 目标之一是继续优化骆驼核心&#xff0c;这一次我们花了一些时间来寻找路由引擎中的一些热点。 我们所研究的方面之一也是在Camel路由的每个消息中发生的对象分配。 JVM本身…

判断字符为空_算法题:字符串转换整数 (atoi)

题目描述题解分析他人更优解一、题目描述二、题解import math class Solution:def myAtoi(self,str):str str.strip() #去除字符串两边的空格if len(str) 0: return 0 #如果字符串为空返回0if not str[0].isdigit() and str[0] ! - and str[0] ! : #判断第一个字符是…

python 3.5.2设计页面_怎么解决win10系统搭建Python 3.5.2开发环境的处理方案

今天小编告诉大家如何对win10系统搭建Python 3.5.2开发环境进行设置&#xff0c;可能很多用户都不知道怎么对win10系统搭建Python 3.5.2开发环境进行设置&#xff0c;但当我们遇到对win10系统搭建Python 3.5.2开发环境进行设置的问题怎么办呢&#xff1f;遇到这种情况不要着急&…

Eclipse系列的隐藏宝藏-2019年版

Eclipse Collections是一个开放源代码Java Collections框架。 在此博客中&#xff0c;我将演示该框架的五个鲜为人知的功能。 我在去年的Java Advent Calendar中发布了一个类似的博客 。 请参阅博客末尾的资源以获取有关该框架的更多信息。 1. countBy() &#xff1a;要查找特…

mongodb一致性协议_mongo的怎么保持事物的一致性-问答-阿里云开发者社区-阿里云...

http://docs.mongoing.com/manual-zh/tutorial/perform-two-phase-commits.html要么操作全都执行&#xff0c;要么都不执行&#xff0c;不能执行一半&#xff0c;改了几条数据了&#xff0c;看哎哟好像不对&#xff0c;那扔着吧。Consistency 在数据库领域的意思跟在分布式系统…

picturectrl控件中加载图片并显示_在 CRA 中使用 webp 图片提升加载性能

webp 是 google 提倡的一种新的 image 格式&#xff0c;意在为 web 提供体积更小的图片格式。通常情况下&#xff0c;无损压缩可以减小 25%-35% 的体积&#xff08;有例外情况&#xff0c;反而会增大体积&#xff0c;但是是因为转换图片格式不兼容引起的&#xff09;&#xff0…

怎么打开网卡rss_RSS 进阶篇:Huginn - 真·为任意网页定制 RSS 源(PhantomJs 抓取)...

定制网页RSS源主要有FEED43和Huginn两种方法。FEED43&#xff1a;简单免费&#xff0c;六小时抓取一次&#xff0c;每次抓取20条静态页面。使用攻略- RSS 入门篇&#xff1a;FEED43&FeedEx-为静态网页定制 RSS 源2. Huginn&#xff1a;自由度高&#xff0c;可设定抓取频率、…

编写junit 测试_编写JUnit测试的另一种方法(Jasmine方法)

编写junit 测试最近&#xff0c;我为一个小型个人项目编写了很多Jasmine测试。 我花了一些时间才终于感到正确地完成了测试。 在此之后&#xff0c;当切换回JUnit测试时&#xff0c;我总是很难过。 由于某种原因&#xff0c;JUnit测试不再那么好&#xff0c;我想知道是否有可能…

python4 什么时候_Python4要来了?快来看看Python之父怎么说

大家好&#xff0c;我是菜鸟哥&#xff0c;今天跟大家一起聊一下Python4的话题&#xff01;从2020年的1月1号开始&#xff0c;Python官方正式的停止了对于Python2的维护。Python也正式的进入了Python3的时代。而随着时间的发展&#xff0c;关于Python4的发布也逐渐的成为了大家…

python类成员变量_Python 类变量和成员变量

Python 类变量和成员变量类与对象的方法我们已经讨论了类与对象的功能部分&#xff0c;现在我们来看一下它的数据部分。事实上&#xff0c;它们只是与类和对象的名称空间 绑定 的普通变量&#xff0c;即这些名称只在这些类与对象的前提下有效。有两种类型的 域 ——类的变量和对…

JDK 14 – JEP 361从预览中切换表达式

在我以前的文章中 &#xff0c;我写了有关作为JDK 12的预览功能发布的开关表达式和相关增强功能的信息。随后&#xff0c;在JDK 13中提出了一些更改&#xff0c;例如使用yield关键字从switch块返回值并在预览中发布。 在即将于明年3月在GA上发布的即将发布的JDK 14版本中&…