我需要在启动Android应用程序时快速加载大约2MB的数据。 我真的需要在内存中所有这些数据,所以像SQLite等不能替代它。
数据包含大约3000个int[][]
数组。数组维数平均约为[7] [7]。
我首先在桌面上实现了一些原型,并将其移植到了android。在桌面上,我只使用了Java(de)序列化。在我的桌面计算机上反序列化该数据大约需要90毫秒。
然而,在Android 2.2.1上,同样的过程在我的HTC Magic上大约需要15秒(!)。它是如此之慢,如果我不在单独的thred中反序列化,我的应用程序将被杀死。总而言之,这是令人无法接受的缓慢。
我做错了什么?我应该
int[][]
数组?!答案 0 :(得分:4)
为什么不绕过内置的反序列化,并使用直接二进制I / O? 当速度是你最关心的问题,不一定是编程的简易性,你就无法击败它。
对于输出,伪代码看起来像这样:
write number of arrays
for each array
write n,m array sizes
for each element of array
write array element
对于输入,伪代码为:
read number of arrays
for each array
read n,m array sizes
allocate the array
for each element of array
read array element
当您以二进制读取/写入数字时,可以绕过二进制和字符之间的所有转换。 速度应仅受文件存储介质的数据传输速率限制。
答案 1 :(得分:1)
import java.io.*;
public static int[][][] readBinaryInt(String filename) throws IOException {
DataInputStream in = new DataInputStream(
new BufferedInputStream(new FileInputStream(filename)));
int dimOfData = in.readInt();
int[][][] patternijk = new int[dimofData][][];
for(int i=0;i<dimofData;i++) {
int dimStrokes = in.readInt();
int[][] patternjk = new int[dimStrokes][];
for(int j=0;j<dimStrokes;j++) {
int dimPoints = in.readInt();
int[] patternk = new int[dimPoints];
for(int k=0;k<dimPoints;k++) {
patternk[k] = in.readInt();
}
patternjk[j] = patternk;
}
patternijk[i] = patternjk;
}
in.close();
return patternijk;
}
答案 2 :(得分:0)
几个月前我在一个项目上遇到了同样的问题。我认为你应该将文件分成不同的部分,并且只根据用户的选择加载相关的部分。 希望它会有所帮助!
答案 3 :(得分:-1)
我不知道您的数据,但如果您优化循环,则会令人难以置信地影响反序列化时间。
如果你看下面的例子
computeRecursively(30); computeRecursivelyWithLoop(30); // 270 milisecond computeIteratively(30); // 1 milisecond computeRecursivelyFasterUsingBigInteger(30); // about twice s fast as before version computeRecursivelyFasterUsingBigIntegerAllocations(50000); // only 1.3 Second !!!
public class Fibo {
public static void main(String[] args) {
// try the methods
}
public static long computeRecursively(int n) {
if (n > 1) {
System.out.println(computeRecursively(n - 2)
+ computeRecursively(n - 1));
return computeRecursively(n - 2) + computeRecursively(n - 1);
}
return n;
}
public static long computeRecursivelyWithLoop(int n) {
if (n > 1) {
long result = 1;
do {
result += computeRecursivelyWithLoop(n - 2);
n--;
} while (n > 1);
System.out.println(result);
return result;
}
return n;
}
public static long computeIteratively(int n) {
if (n > 1) {
long a = 0, b = 1;
do {
long tmp = b;
b += a;
a = tmp;
System.out.println(a);
} while (--n > 1);
System.out.println(b);
return b;
}
return n;
}
public static BigInteger computeRecursivelyFasterUsingBigInteger(int n) {
if (n > 1) {
int m = (n / 2) + (n & 1); // not obvious at first – wouldn’t it be
// great to have a better comment here?
BigInteger fM = computeRecursivelyFasterUsingBigInteger(m);
BigInteger fM_1 = computeRecursivelyFasterUsingBigInteger(m - 1);
if ((n & 1) == 1) {
// F(m)^2 + F(m-1)^2
System.out.println(fM.pow(2).add(fM_1.pow(2)));
return fM.pow(2).add(fM_1.pow(2)); // three BigInteger objects
// created
} else {
// (2*F(m-1) + F(m)) * F(m)
System.out.println( fM_1.shiftLeft(1).add(fM).multiply(fM));
return fM_1.shiftLeft(1).add(fM).multiply(fM); // three
// BigInteger
// objects
// created
}
}
return (n == 0) ? BigInteger.ZERO : BigInteger.ONE; // no BigInteger
// object created
}
public static long computeRecursivelyFasterUsingBigIntegerAllocations(int n) {
long allocations = 0;
if (n > 1) {
int m = (n / 2) + (n & 1);
allocations += computeRecursivelyFasterUsingBigIntegerAllocations(m);
allocations += computeRecursivelyFasterUsingBigIntegerAllocations(m - 1);
// 3 more BigInteger objects allocated
allocations += 3;
System.out.println(allocations);
}
return allocations; // approximate number of BigInteger objects
// allocated when
// computeRecursivelyFasterUsingBigInteger(n) is
// called
}
}