为什么 Java HTTP 请求这么慢(与 Python 相比),以及如何使它们更快?

Xid*_*doc 3 java networking http python-requests okhttp

Java 是一种美丽的语言,据说也非常高效。来自使用 Python 的背景,我想看看这两种语言之间的区别 - 从一开始我就对 Java 基于 OOP 的语法的明确性和清晰性印象深刻。但是,我也想测试一下语言之间的性能差异。

我首先尝试通过计算速度测试两种语言之间的性能差异。为此,我用每种语言编写了一些代码——程序试图计算一个数学问题,并且会迭代很多次。我不会在这里添加这段代码,但我会说结果——Python 几乎比 Java 慢 2 倍(按时间衡量)。有趣,但这是意料之中的。毕竟,我想尝试使用 Java 的全部原因是因为有很多人吹嘘计算速度。

之后,我进行了第二次测试——建立到网站的 HTTP 连接,以便下载网页。对于这个测试,我编写了另一个测试程序,它的功能与上一个测试相同,只是它不是计算数学方程,而是使用 HTTP 库下载网页。

我最终用 Python 编写了以下脚本。它非常简单,它在下载网页时迭代 10 次,然后打印平均值。

from requests import get
from time import time

# Start the timer
start = time()

# Loop 10 times
for i in range(10):
    # Execute GET request
    get("https://httpbin.org/get")

# Stop the timer
stop = time()

# Calculate and print average
avg = (stop - start) / 10

print(avg)
# Prints 0.5385, on my system.
Run Code Online (Sandbox Code Playgroud)

对于 Java 测试,我编写了以下代码。它与之前的测试相同,但使用 Java 实现。

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import java.io.IOException;
import java.util.Objects;

public class Test {

    public static String run(String url) throws IOException {
        // Code taken from OKHTTP docs
        // https://square.github.io/okhttp/
        // https://raw.githubusercontent.com/square/okhttp/master/samples/guide/src/main/java/okhttp3/guide/GetExample.java
        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
            .url(url)
            .build();

        try (Response response = client.newCall(request).execute()) {
            return Objects.requireNonNull(response.body()).string();
        }
    }

    public static void main(String[] args) throws IOException {
        // Start the timer
        long startTime = System.nanoTime();

        // Loop 10 times
        for (int i = 0; i < 10; i++) {
            // Execute GET request
            run("https://httpbin.org/get");
        }

        // Stop the timer
        long endTime = System.nanoTime();

        // Calculate the average
        float average = (((float) (endTime - startTime)) / 1000000000) / 10;

        // Print results (1.05035 on my system)
        System.out.println(average);
    }
}
Run Code Online (Sandbox Code Playgroud)

呵呵……没想到吧。唉,Java 不是应该比 Python 快吗?我很震惊地看到 Java 在这个测试中几乎比 Python 慢 2 倍,但我决心找到一个有利于 Java 的结论。为了满足这一点,我决定使用 Java 默认库而不是OkHttp库来重新编写测试。我不会在这里展示代码,因为它很长,但我曾经HttpURLConnection帮助过我。我的结果仍然相同,但比OkHttp图书馆略快。

我的最终测试是和之前的测试一样,但在http://网站上(以防由于 SSL 连接而导致速度变慢)。我的结果还是一样——Python 快了近 2 倍。我唯一能想到为什么会发生这种情况是因为requestsPython 库将用 C 编码,但正如您从其 GitHub 页面的“语言”部分看到的那样,所有requests库都是用纯 Python 编程的。

我想了解为什么 Java 在运行 HTTP 连接时如此缓慢,如果我的系统设置或 Java 测试代码有问题,我应该编写什么来改进结果?另外,如果可能的话,如何发送 Java HTTP 请求以使其比 Python 请求更快requests

小智 6

我真的很怀疑你得到的结果,所以我尝试了与你完全相同的 Python 代码和mainJava 方法(使用 https)。
这是run读取响应的整个 JSON 内容的 Java方法:

private static String run(String url) throws IOException {
    final URLConnection c = new URL(url).openConnection();
    c.connect();
    try (InputStream is = c.getInputStream()) {
        final byte[] buf = new byte[1024];
        final StringBuilder b = new StringBuilder();
        int read = 0;
        while ((read = is.read(buf)) != -1) {
            b.append(new String(buf, 0, read));
        }
        return b.toString();
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的系统上的结果:

  • Python 2.7.12:0.5117351770401001
  • Python 3.5.2:0.48344600200653076
  • Java 1.8:0.19684727

10 次迭代可能不足以获得好的结果,但在这里,Java 至少要快 2 倍。