0

Android アプリケーションの起動時に、約 2MB のデータをすばやくロードする必要があります。このすべてのデータをメモリに保存する必要があるため、SQLite などは代替手段ではありません。

データは約 3000 のint[][]配列で構成されています。配列の次元は平均で [7][7] 前後です。

最初にデスクトップにいくつかのプロトタイプを実装し、それを Android に移植しました。デスクトップでは、単純に Java の (デ) シリアル化を使用しました。そのデータの逆シリアル化には、デスクトップ コンピューターで約 90 ミリ秒かかります。

ただし、Android 2.2.1 では、HTC Magic で同じプロセスに約 15 秒 (!) かかります。非常に遅いため、別のスレッドで逆シリアル化しないと、アプリが強制終了されます。全体として、これは容認できないほど遅いです。

私は何を間違っていますか?するべきか

  • プロトコルバッファのようなものに切り替えますか? それは実際にいくつかの大きさの逆シリアル化のプロセスをスピードアップするでしょうか?結局、私が逆シリアル化しているのは複雑なオブジェクトではなく、int[][]配列だけですか?!
  • 独自のカスタム バイナリ ファイル形式を設計する 私はそれをやったことがなく、どこから始めればいいのかわからない
  • 何か他のことをしますか?
4

4 に答える 4

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

バイナリで数値を読み書きすると、バイナリと文字の間のすべての変換がバイパスされます。速度は、ファイル ストレージ メディアのデータ転送速度によってのみ制限されます。

于 2012-12-27T19:11:08.987 に答える
1

Mike Dunlavey が提案したように、いくつかのことを試した後、ダイレクト バイナリ I/O が最速のようでした。私はほぼそのまま彼のスケッチ版を使用しました。ただし、完全を期すために、他の誰かが試してみたい場合は、ここに完全なコードを投稿します。それは非常に基本的なものであり、健全性チェックは一切ありません。これは、そのようなバイナリ ストリームを読み取るためのものです。書くことは完全に類似しています。

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;  
}
于 2013-02-03T17:56:56.233 に答える
0

私は数ヶ月前にプロジェクトで同じ種類の問題を抱えていました. ファイルをさまざまな部分に分割し、たとえばユーザーの選択に従って関連部分のみをロードする必要があると思います。それが役立つことを願っています!

于 2012-12-27T18:45:46.890 に答える
-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
    }
}
于 2012-12-27T19:26:32.493 に答える