我正在开发一个 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/