Android: медленное чтение txt-файла и утечка памяти при вставке данных в trie (неправильное использование hashmap)? - PullRequest
1 голос
/ 05 октября 2011

Я пытаюсь прочитать текстовый файл размером 816 КБ (70 000 строк) в моем приложении для Android, которое находится в папке res / raw. Это соответствующий фрагмент кода:

            InputStream raw = context.getResources().openRawResource(R.raw.alpha);
            InputStreamReader inputreader = new InputStreamReader(raw);
            BufferedReader r = new BufferedReader(inputreader);
            String line;

            int j = 0;
            while ((line = r.readLine()) != null && j < 90000){
                theTrie.insert(line);
                j++;
            }

«Контекст» задается с помощью параметра: Main.readDatabase (getApplication ());

Эта версия аварийно завершает работу со следующим журналом:

10-04 21:14:26.096: INFO/dalvikvm(1327):   | group="main" sCount=0 dsCount=0 obj=0x4001f1a8 self=0xce48
10-04 21:14:26.096: INFO/dalvikvm(1327):   | sysTid=1327 nice=0 sched=0/0 cgrp=default handle=-1345006528
10-04 21:14:26.096: INFO/dalvikvm(1327):   | schedstat=( 3112456663 436561269 431 )
10-04 21:14:26.096: INFO/dalvikvm(1327):   at java.lang.Throwable.nativeFillInStackTrace(Native Method)
10-04 21:14:26.096: INFO/dalvikvm(1327):   at java.lang.Throwable.fillInStackTrace(Throwable.java:135)
10-04 21:14:26.096: INFO/dalvikvm(1327):   at java.lang.Throwable.<init>(Throwable.java:74)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at java.lang.Error.<init>(Error.java:38)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at java.lang.VirtualMachineError.<init>(VirtualMachineError.java:36)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at java.lang.OutOfMemoryError.<init>(OutOfMemoryError.java:34)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at java.util.HashMap.makeTable(HashMap.java:-1)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at java.util.HashMap.<init>(HashMap.java:162)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at snappy.keyboard.TrieNode.<init>(TrieNode.java:21)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at snappy.keyboard.Trie.insert(Trie.java:27)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at snappy.keyboard.Main.readDatabase(Main.java:356)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at snappy.keyboard.SoftKeyboard.onCreate(SoftKeyboard.java:89)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at android.app.ActivityThread.handleCreateService(ActivityThread.java:1920)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at android.app.ActivityThread.access$2500(ActivityThread.java:117)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:982)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at android.os.Handler.dispatchMessage(Handler.java:99)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at android.os.Looper.loop(Looper.java:123)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at android.app.ActivityThread.main(ActivityThread.java:3647)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at java.lang.reflect.Method.invokeNative(Native Method)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at java.lang.reflect.Method.invoke(Method.java:507)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
10-04 21:14:26.106: INFO/dalvikvm(1327):   at dalvik.system.NativeStart.main(Native Method)
10-04 21:14:26.196: WARN/dalvikvm(1327): Exception thrown (Ljava/lang/OutOfMemoryError;) while throwing internal exception (Ljava/lang/OutOfMemoryError;)
10-04 21:14:26.326: INFO/dalvikvm-heap(1327): Clamp target GC heap from 25.881MB to 24.000MB
10-04 21:14:26.326: DEBUG/dalvikvm(1327): GC_CONCURRENT freed <1K, 13% free 20224K/22983K, external 1625K/2137K, paused 2ms+3ms
10-04 21:14:26.446: INFO/dalvikvm-heap(1327): Clamp target GC heap from 25.856MB to 24.000MB
10-04 21:14:26.446: DEBUG/dalvikvm(1327): GC_FOR_MALLOC freed 25K, 13% free 20198K/22983K, external 1625K/2137K, paused 123ms
10-04 21:14:26.446: DEBUG/AndroidRuntime(1327): Shutting down VM

Если я не запускаю этот код (слегка измененный из-за чтения файлов) в эмуляторе, но в обычном Java-приложении он работает без проблем, но на Android, похоже, есть утечка памяти? У кого-нибудь есть идеи, в чем может быть проблема? Даже если я удалю строку "theTrie.insert (line);" так что цикл while (почти) пуст, приложению требуется 2,1 секунды для «повторного выравнивания» 800 кб. Это не может быть нормальным, верно? Где моя ошибка?

Заранее спасибо!

Обновление: Я записал в кучу файл с DDMS и проанализировал его с помощью MAT. Это говорит: класс [в вопросе], загруженный "dalvik.system.PathClassLoader @ 0x4051d5e8", занимает 23.951.808 (91,76%) байтов. Память накапливается в одном экземпляре "java.util.HashMap $ HashMapEntry []", загруженном "". Гистограмма перечисляет java.util.HashMap $ HashMapEntry [], java.util.HashMap и java.util.HashMap $ HashMapEntry в качестве трех объектов с самой большой мелкой кучей.

Вот мой код, касающийся использования хэш-карты (в классе, определяющем узел дерева):

public Map<Character, TrieNode> children;

public TrieNode(char letter) {
    this.letter = letter;
    children = new HashMap<Character, TrieNode>(26);
}

Что вызывает утечку памяти?

1 Ответ

2 голосов
/ 05 октября 2011

Иногда эмулятор не настолько точен, как хотелось бы некоторым . Иногда какой-то процесс, который хорошо работает в терминале, работает медленно в эмуляторе.

Попробуйте сделать это с помощью телефона Android, а затем не забудьте рассказать нам о своем опыте.

-------------------------------------------- ИЗМЕНИТЬ

Попробуйте это:

        BufferedReader r = new BufferedReader(new InputStreamReader(context.getResources().openRawResource(R.raw.alpha)));
        String line = null;

        int j = 0;
        while ((line = r.readLine()) != null && j < 90000){
            theTrie.insert(line);
            j++;
        }

А потом посмотрите, сколько раз вы вызываете эту функцию, может быть, в этом проблема.

Но, подумав и увидев три-карту, я могу сказать, что вы тоже инвестируете в то, что вы читаете, возможно, строки слишком длинные .

-------------------------------------------- MODIFY 2

Я думаю, что лучшее, что вы можете сделать, это изменить точку зрения и попытаться использовать базу данных SQLite, чтобы иметь так много информации и без проблем с памятью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...