据说write(int b)与 write(byte[] b)的效率不一样???测试发现,在发送相同内容的数据时(100000个26),write(int b)确实比write(byte[] b)效率要低,经过一层层查看代码与试验,得知了出现这个问题的原因。
一言以蔽之,write(byte[] b)与write(int a)都在OutputStream的子类SocketOutputStream中被重写,write(int a)中调用了write(byte[] b),而每次调用write(byte[] b),实际上都会申请一段空间来缓存b,假如这段空间的长度为65536,b的长度为65536,a的个数为65536,而则write(byte[] b)需要申请1次长度为65536的空间,而write(int a)则需要申请65536次长度为65536的空间。申请/释放是一个耗费时间的操作,两种方法在传输n个byte时,write(int a)需要申请/释放空间n次,而write(byte[] b)则至多需要两次,总的申请/释放空间不同导致了write(int b)与 write(byte[] b)的效率不同
STEP 1
推测:源码实现方式不同;
求证:不同查看源码,发现write(byte[] b)是调用了write(int b),不应当有效率差别,但是源码注释中说Subclasses are encouraged to override this method and provide a more efficient implementation.。
当传送一个很大很大的长度的数组时(length = 10000000,除此之外,每次测试对比,都是100000个int或者长度为100000的byte数组),发现报错位置at java.base/java.net.SocketOutputStream.socketWrite0 。
通过
System.out.println(outputStream.getClass());
发现object.getOutputStream()返回的OutputStream实例其实是OutputStream的子类SocketOutputStream的实体,查看源码发现write(int b)的实现为
public void write(int b) throws IOException {
temp[0] = (byte)b;
socketWrite(temp, 0, 1);
}
write(byte[] b)的实现为
public void write(byte b[]) throws IOException {
socketWrite(b, 0, b.length);
}
STEP 2
推测:是temp[0] = (byte)b;占用了时间
求证:比较1次传入长度为10000的byte数组,和传入10000次长度为1的byte数组,发现并没有什么明显改善。进入socketWrite方法查看,发现调用了socketWrite0(fd, b, off, len);
private void socketWrite(byte b[], int off, int len) throws IOException {
if (len <= 0 || off < 0 || len > b.length - off) {
if (len == 0) {