现在我正在改进java I/O的性能。我对使用java I/O在网络上读/写流有一些疯狂的怀疑,正如我下面提到的。在我的脑海里有几个观点来来去去。但是我想清除所有的
URL url = new URL("http://example.com/connector/url2Service");
URLConnection urlConnection = url.openConnection(); // Position 1
HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
String requestStr = buildRequestString();// Position 2
ByteArrayOutputStream rqByteArrayOutputStream = new ByteArrayOutputStream();
rqByteArrayOutputStream.write(((String)requestStr).getBytes()); // Position 3
httpURLConnection.setDoOutput(true);
httpURLConnection.setUseCaches(false);
httpURLConnection.setDoInput(true);
httpURLConnection.setRequestMethod("POST");
rqByteArrayOutputStream.writeTo(httpURLConnection.getOutputStream()); // Position 4
// Waiting for the response.
InputStream inputStream = httpURLConnection.getInputStream(); // Position 5
ByteArrayOutputStream rsByteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) { // Position 6
rsByteArrayOutputStream.write(buffer, 0, length);// Position 7
}
String response = new String(rsByteArrayOutputStream.toByteArray());// Position 8
我的理解
- Position 1:这将提供与远程资源通信的对象。但是连接尚未建立。
- 位置2:构建和获取请求。
- 位置3:将字节写入ByteArrayOutputStream
- 位置4:这是与服务器开始通信的位置。我们在写字节。因此,服务器可以开始读取它们。当执行退出这一行时,我们已经完成了发送请求对象。
- 位置5:当我们退出这一行时,服务器已经完成发送响应对象。所以,我们可以开始读取响应对象了。
- 位置6:读取对象为4096字节块。
- 位置7:将读取的字节写入ByteArrayOutputStream。
- Position 8:完成读取响应并将其转换为String。
我的问题
- 什么时候我们可以说请求上传是完成了吗?(我相信这是完成时,我们执行存在的立场4)
- 有什么意义我们可以说响应下载完成了吗?(我对第5点和第8点有疑问)
- 当我们退出第5点时,是否意味着响应是完全的已下载还是刚刚开始下载?
- 网络(带宽)在多大程度上会影响性能?(第5,6,7…点)
- 现在我正在调整输入流读取代码。如果你有任何建议请分享?
引用:
- http://www.oracle.com/technetwork/articles/javase/perftuning - 137844. - html
- http://www.oracle.com/technetwork/java/performance - 139413. - html
- http://www.javaworld.com/article/2076241/build-ci-sdlc/tweak-your-io-performance-for-faster-runtime.html
- http://www.kegel.com/java/wp-javaio.html
什么时候我们可以说请求上传已经完成?(我相信这是完成时,我们执行存在的位置4)
是的,但是你已经在ByteArrayOutputStream上浪费了一些时间。只需将请求直接写入连接输出流。节省内存和延迟。
我们可以说响应下载完成的点是什么?(我对第5点和第8点有疑问)
当你从read()方法收到-1时
当我们退出第5点时,这意味着响应已完全下载还是刚刚开始下载?
。请求已经写好,您还没有开始加载任何东西,所以没有下载任何东西。它可能已经开始到达到套接字接收缓冲区,但是您无法看到。
网络(带宽)在多大程度上会影响性能?(第5,6,7…点)
都不是。您正在使用网络带宽,直到您得到-1。
现在我正在调整InputStream读取代码。如果你有任何建议请分享?
使用更大的缓冲区。你能做的也不多了。
-
在建立连接时,请求可能被缓冲在系统缓冲区中,因此请求的发送-"上传"-在通过位置6之前不能保证完成。此时,您知道服务器已经接收到get请求,因为它现在正在发送响应。传递位置4只是意味着你的程序已经将请求传递到你自己的系统缓冲区。
-
响应已经收到-"下载"完成-在最后一次通过位置6之后,当它返回-1表示流结束
-
当您退出位置5时,响应可能已经收到,也可能没有收到。您所做的只是获得对已经存在的输入流的显式访问。
有可能响应已经完全被接收,并且已经在系统TCP缓冲区中被缓冲,也有可能没有响应被接收。 从位置4到位置6的最后一次迭代都必须打开网络资源。在您的代码中,您继续使连接无限期地打开。退出位置6/7
while
环后关闭连接,可以节省网络资源。(a)不要使用rqByteArrayOutputStream。相反,将来自连接的输出流包装在OutputStreamWriter中,并将请求字符串直接写入该输出流。这节省了几行代码,并删除了复制请求字符串的一次迭代。
(b)在输出流和输入流上调用close(),以允许释放网络资源。
与JDK Http相关的类是基于旧java的。io的实现。查看OpenJDK的HttpURLConnection中的代码。(详细介绍OpenJDK的根目录,基于Oracle JDK 7)基于操作系统原语的Nio实现直接提供了一个全新的性能范围。NIO =非阻塞IO或事件驱动IO。
Netty是一个基于java的高性能网络实现。nio原语。我曾经参与过一个项目,利用netty在sun blade硬件上实现了5位数的性能。Netty示例http代码可以在这里找到。
LMAX的Martin Thompson写的另一篇关于ByteArrayOutputStream性能的好文章是java序列化。这样可以更深入地理解java性能或内置JDK类的性能。
这是你要找的信息吗?由于遗留的JDK代码库而应该使用的?