gpt4 book ai didi

java - 在 Java 中通过套接字有效地发送大的 int[]

转载 作者:搜寻专家 更新时间:2023-10-30 19:45:37 24 4
gpt4 key购买 nike

我正在开发一个 Java 应用程序,我需要通过套接字连接尽快将 500,000 个整数的数组从一部 Android 手机发送到另一部 Android 手机。主要瓶颈似乎是转换整数,以便套接字可以接受它们,无论我使用 ObjectOutputStreams、ByteBuffers 还是低级掩码和移位转换。通过套接字从一个 Java 应用程序向另一个应用程序发送 int[] 的最快方法是什么?

这是迄今为止我尝试过的所有代码,以及我正在测试的 LG Optimus V 的基准(600 MHz ARM 处理器,Android 2.2)。

低级掩码和移位:0.2 秒

public static byte[] intToByte(int[] input)
{
byte[] output = new byte[input.length*4];

for(int i = 0; i < input.length; i++) {
output[i*4] = (byte)(input[i] & 0xFF);
output[i*4 + 1] = (byte)((input[i] & 0xFF00) >>> 8);
output[i*4 + 2] = (byte)((input[i] & 0xFF0000) >>> 16);
output[i*4 + 3] = (byte)((input[i] & 0xFF000000) >>> 24);
}

return output;
}

使用 ByteBuffer 和 IntBuffer:0.75 秒

public static byte[] intToByte(int[] input)
{
ByteBuffer byteBuffer = ByteBuffer.allocate(input.length * 4);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(input);

byte[] array = byteBuffer.array();

return array;
}

ObjectOutputStream:3.1 秒(我尝试使用 DataOutPutStream 和 writeInt() 而不是 writeObject() 进行变体,但没有太大区别)

public static void sendSerialDataTCP(String address, int[] array) throws IOException
{
Socket senderSocket = new Socket(address, 4446);

OutputStream os = senderSocket.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream (os);
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(array);

oos.flush();
bos.flush();
os.flush();
oos.close();
os.close();
bos.close();

senderSocket.close();
}

最后,我用来发送 byte[] 的代码:比 intToByte() 函数多花 0.2 秒

public static void sendDataTCP(String address, byte[] data) throws IOException
{
Socket senderSocket = new Socket(address, 4446);

OutputStream os = senderSocket.getOutputStream();
os.write(data, 0, data.length);
os.flush();

senderSocket.close();
}

我正在套接字的两侧编写代码,因此我可以尝试任何类型的字节顺序、压缩、序列化等。必须有一种方法可以在 Java 中更有效地进行这种转换。请帮忙!

最佳答案

正如我在评论中指出的那样,我认为您正在突破处理器的极限。由于这可能对其他人有帮助,因此我将其分解。这是将整数转换为字节的循环:

    for(int i = 0; i < input.length; i++) {
output[i*4] = (byte)(input[i] & 0xFF);
output[i*4 + 1] = (byte)((input[i] & 0xFF00) >>> 8);
output[i*4 + 2] = (byte)((input[i] & 0xFF0000) >>> 16);
output[i*4 + 3] = (byte)((input[i] & 0xFF000000) >>> 24);
}

这个循环执行了 500,000 次。您的 600Mhz 处理器每秒可以处理大约 600,000,000 次操作。因此,对于每个操作,循环的每次迭代将消耗大约 1/1200 秒。

同样,使用非常粗略的数字(我不知道 ARM 指令集,所以每个操作可能或多或少),这是一个操作计数:

  • 测试/分支:5(检索计数器、检索数组长度、比较、分支、递增计数器)
  • 掩码和移位:10 x 4(检索计数器、检索输入数组基数、加法、检索掩码,以及、移位、乘以计数器、加偏移量、加到输出基数、存储)

好吧,粗略计算,此循环最多 55/1200 秒,或 0.04 秒。但是,您不是在处理最佳情况。一方面,对于这么大的数组,您不会从处理器缓存中受益,因此您将在每个数组存储和加载中引入等待状态。

另外,我描述的基本操作可能会或可能不会直接转换为机器代码。如果不是(我怀疑不是),循环的成本将比我描述的要高。

最后,如果您真的不走运,JVM 没有对您的代码进行 JIT,因此对于循环的某些部分(或全部),它正在解释字节码而不是执行 native 指令。我对 Dalvik 了解不够,无法对此发表评论。

关于java - 在 Java 中通过套接字有效地发送大的 int[],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12320000/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com