Форум программистов, компьютерный форум CyberForum.ru

Программирование Android

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 16, средняя оценка - 4.94
MonStar
19 / 19 / 3
Регистрация: 10.04.2011
Сообщений: 225
#1

Оптимизация приложения. Слишком часто вызывается GC - Android

16.07.2013, 15:30. Просмотров 2058. Ответов 28
Метки нет (Все метки)

Требуются некоторые разъяснения по работе GC и некоторая помощь в оптимизации.

Есть два проблемных места, в обоих очень часто создаются модели JSON.

Дело в том что постоянно через WebSocket идет непрерывный поток примерно 10Кб\с. Для каждого сообщения создается JSON, парсится, обрабатывается и когда приходит следующее сообщение старый JSON теряет ссылку и подбирается GC (мне кажется что всё происходит именно так).

В результате на момент работы GC приложение приостанавливается и появляются задержки.
Меня интересует, правда ли что GC_CONCURRENT полностью блокирует приложение на время своей работы (хотя он должен работать синхронно с приложением). По логам видно, что утечек памяти нет, но вызовы GC очень частые, иногда чаще чем раз в 10 секунд.

07-16 14:21:38.403: D/dalvikvm(16883): GC_CONCURRENT freed 1427K, 23% free 13244K/17112K, paused 105ms+7ms, total 168ms
07-16 14:21:43.578: D/dalvikvm(16883): GC_CONCURRENT freed 1807K, 22% free 13483K/17112K, paused 10ms+24ms, total 162ms
07-16 14:21:51.842: D/dalvikvm(16883): GC_CONCURRENT freed 1890K, 21% free 13539K/17112K, paused 59ms+19ms, total 156ms
07-16 14:22:02.282: D/dalvikvm(16883): GC_CONCURRENT freed 1941K, 21% free 13551K/17112K, paused 19ms+16ms, total 138ms
07-16 14:22:06.276: D/dalvikvm(16883): GC_CONCURRENT freed 2001K, 22% free 13500K/17112K, paused 6ms+4ms, total 91ms
07-16 14:22:17.287: D/dalvikvm(16883): GC_CONCURRENT freed 1878K, 21% free 13561K/17112K, paused 12ms+6ms, total 97ms
07-16 14:22:28.138: D/dalvikvm(16883): GC_CONCURRENT freed 1936K, 21% free 13562K/17112K, paused 6ms+20ms, total 104ms
07-16 14:22:35.194: D/dalvikvm(16883): GC_CONCURRENT freed 1926K, 21% free 13557K/17112K, paused 3ms+11ms, total 64ms
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.07.2013, 15:30     Оптимизация приложения. Слишком часто вызывается GC
Посмотрите здесь:

Не вызывается событие onConfigurationChanged Android
Android Не вызывается клавиатура внутри PopupWindow
Не вызывается onDestroy при принудительно остановке приложения Android
Android Ищу сотоварища для разработки не слишком сложного приложения
Оптимизация приложения Android
Почему вызывается onDismiss Android
Оптимизация приложения Android
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Wenceslaus
Android Developer
129 / 129 / 4
Регистрация: 05.07.2013
Сообщений: 205
16.07.2013, 15:56     Оптимизация приложения. Слишком часто вызывается GC #2
Да, при каждом создании модели/объекта JSON выделяется память, когда её начинает не хватать, то вызывается GC и блокирует все потоки в приложении (порядка 200мс). При чём, если я не ошибаюсь, под приложение выделяется что-то около 10мб памяти. Так что в вашем случае я бы смотрел на оптимизацию создания/парсинга JSON модели.
MonStar
19 / 19 / 3
Регистрация: 10.04.2011
Сообщений: 225
16.07.2013, 16:02  [ТС]     Оптимизация приложения. Слишком часто вызывается GC #3
Хотелось бы найти альтернативу. Возможно ли как-то переиспользовать JSON объекты по несколько раз, что бы они не очищались мусорщиком? Я не нашел возможности заменить String готового объекта JSON, что бы он после этого заново её распарсил, кроме создания нового объекта.
Может есть библиотека с другим парсером позволяющая подобное?
Wenceslaus
Android Developer
129 / 129 / 4
Регистрация: 05.07.2013
Сообщений: 205
16.07.2013, 16:20     Оптимизация приложения. Слишком часто вызывается GC #4
А вы пользуетесь GSON'ом? Если так, то jackson быстрее будет. Но насколько это решит проблему с GC я не знаю.
Может быть я что-то подскажу, если увижу код получения/парсинга JSON'а, но не факт..
MonStar
19 / 19 / 3
Регистрация: 10.04.2011
Сообщений: 225
16.07.2013, 16:24  [ТС]     Оптимизация приложения. Слишком часто вызывается GC #5
В данном случае используется обычный парсер Android, и т.к. парсинг выполняется в другом потоке проблем с задержками из-за этого не возникает.

Java
1
2
3
4
5
6
7
8
9
10
11
12
    @Override
    public void onMessage(String message) {
        try {
            jsonArray = new JSONArray(message);
            int lenght = jsonArray.length();
            for (int i = 0; i < lenght; i++) {
                model = new TickerInstrumentModel(jsonArray.getJSONObject(i).toString());
                tickerContent.updateContent(model);
            }
        } catch (Exception e) {
        }
    }

В этот метод приходит по несколько сообщений в секунду. В результате я получаю модель, которую складываю в Map, а когда данные обновились просто заменяю на новую. И т.к. обновляется она очень часто, около 50 моделей за одну секунду, то они очищаются
Wenceslaus
Android Developer
129 / 129 / 4
Регистрация: 05.07.2013
Сообщений: 205
16.07.2013, 18:07     Оптимизация приложения. Слишком часто вызывается GC #6
О jackson'е я только слышал, а вот GSON использую часто. Так вот фича в том, что GSON не создаёт промежуточные объекты и парсит строку уже в готовую модель, не могу сказать, что это полностью решит проблему, но по крайней мере уменьшит количество создаваемых объектов и преобразований.. Попробуйте..
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
17.07.2013, 00:07     Оптимизация приложения. Слишком часто вызывается GC #7
у меня GC никогда не вызывал никаких задержек.
MonStar
19 / 19 / 3
Регистрация: 10.04.2011
Сообщений: 225
17.07.2013, 00:09  [ТС]     Оптимизация приложения. Слишком часто вызывается GC #8
Цитата Сообщение от MonStar Посмотреть сообщение
paused 105ms+7ms
В любых источниках описано, что это означает, что в начале свой работы GC останавливает приложение на 105ms, а под конец на 7ms. Это и вызывает подвисания
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
17.07.2013, 00:12     Оптимизация приложения. Слишком часто вызывается GC #9
имел ввиду на практике никогда GC не был причиной тормозов в приложении.
MonStar
19 / 19 / 3
Регистрация: 10.04.2011
Сообщений: 225
17.07.2013, 00:16  [ТС]     Оптимизация приложения. Слишком часто вызывается GC #10
Цитата Сообщение от V0v1k Посмотреть сообщение
имел ввиду на практике никогда GC не был причиной тормозов в приложении.
Не уверен, что кто-то вообще знает, в какой момент времени вызывается GC, ибо он совершенно непредсказуем. Но в моем приложении, как видно по логам вызывается часто. И предположение почему это происходит я тоже пытался описать. Вот только не знаю как с ним бороться
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
17.07.2013, 00:26     Оптимизация приложения. Слишком часто вызывается GC #11
вроде до 200мс не должно быть заметно для пользователя.
MonStar
19 / 19 / 3
Регистрация: 10.04.2011
Сообщений: 225
17.07.2013, 00:28  [ТС]     Оптимизация приложения. Слишком часто вызывается GC #12
Вот маленький сэмпл. По таймеру создается около 50 объектов в секунду. И переодически в логе можно увидеть как вызывается GC.
В моем приложении такая же ситуация, вот только размеры объектов и количество может быть гораздо больше. А вместо String у меня JSON

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class MainActivity extends Activity {
 
    private TextView textView;
    private int count = 0;
    private Handler handler;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text);
        Timer timer = new Timer();
        handler = new Handler();
        TimerTask task = new TimerTask() {
            
            @Override
            public void run() {
                handler.post(new Runnable() {
                    
                    @Override
                    public void run() {
                        textView.setText("COUNT : " + count++);
                        String s = new String();
                    }
                });
            }
        };
        timer.schedule(task, 20, 20);
    }
}
Добавлено через 1 минуту
Цитата Сообщение от V0v1k Посмотреть сообщение
вроде до 200мс не должно быть заметно для пользователя.
Как я уже писал, для меня критично даже 10ms. Т.к. идет бегущая строка, которая не должна подрагивать из-за таких мелких вызовов. А они очень частые и легко достигают 50ms
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
17.07.2013, 00:34     Оптимизация приложения. Слишком часто вызывается GC #13
ну так я и говорю, не должно быть заметно никаких подрагивань если задержка меньше 200мс.

Добавлено через 28 секунд
или вы думаете что это строка обновляется каждые 10мс?

Добавлено через 3 минуты
Цитата Сообщение от MonStar Посмотреть сообщение
По таймеру создается около 50 объектов в секунду. И переодически в логе можно увидеть как вызывается GC.
В моем приложении такая же ситуация, вот только размеры объектов и количество может быть гораздо больше.
и зачем же столько объектов плодить?
MonStar
19 / 19 / 3
Регистрация: 10.04.2011
Сообщений: 225
17.07.2013, 00:36  [ТС]     Оптимизация приложения. Слишком часто вызывается GC #14
Цитата Сообщение от V0v1k Посмотреть сообщение
ну так я и говорю, не должно быть заметно никаких подрагивань если задержка меньше 200мс.
Тем не менее подрагивания есть и они заметны.

Цитата Сообщение от V0v1k Посмотреть сообщение
или вы думаете что это строка обновляется каждые 10мс?
Каждую секунду мне приходит около 10кб данных. Мне нужно создать JSON объект, распарсить его, сложить все данные, а уже через несколько секунд, если оне не нужны заменить их такими же, но уже свежими. Так вот с таким большим потоком данных все неиспользованные объекты убирает GC. В итоге я получаю то что получаю - задержки в приложении. В секунду получается не менее 50 JSON объектов

Добавлено через 1 минуту
Цитата Сообщение от V0v1k Посмотреть сообщение
и зачем же столько объектов плодить?
Я вынужден хранить всё, что бы в нужный момент отобразить, а не ждать когда мне снова они придут
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
17.07.2013, 00:39     Оптимизация приложения. Слишком часто вызывается GC #15
может храните в нераспарсеном виде и парсьте когда нужно отобразить...

еще покажите что делает updateContent, может кто подскажет как оптимизировать чтобы меньше объектов плодилось.
MonStar
19 / 19 / 3
Регистрация: 10.04.2011
Сообщений: 225
17.07.2013, 00:44  [ТС]     Оптимизация приложения. Слишком часто вызывается GC #16
Цитата Сообщение от V0v1k Посмотреть сообщение
может храните в нераспарсеном виде и парсьте когда нужно отобразить...
Не думаю что подойдет, данные приходят в виде JsonArray, при чем если один раз придет [a,b,d], то второй раз может прийти [b,d,c], а третий [a,d,c].
Да и стринги тоже объекты, они тоже будут очищаться
Цитата Сообщение от V0v1k Посмотреть сообщение
еще покажите что делает updateContent, может кто подскажет как оптимизировать чтобы меньше объектов плодилось
Он просто складывает распарсеные данные в Map и достает их, когда нужно отобразить на экран. В результате всегда имеем 100% свежие данные
Java
1
2
3
4
5
6
    public void updateContent(TickerInstrumentModel model) {
        String instrument = model.getInstrument();
        if (isNeeded(instrument)) {
            models.put(instrument, model);
        }
    }
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
17.07.2013, 00:48     Оптимизация приложения. Слишком часто вызывается GC #17
не понял почему бы просто не хранить последний JsonArray, а когда нужно будет отобразить, тогда и парсить.
или даже не JsonArray, а просто String c всем джейсоном.
MonStar
19 / 19 / 3
Регистрация: 10.04.2011
Сообщений: 225
17.07.2013, 00:51  [ТС]     Оптимизация приложения. Слишком часто вызывается GC #18
Цитата Сообщение от V0v1k Посмотреть сообщение
не понял почему бы просто не хранить последний JsonArray, а когда нужно будет отобразить, тогда и парсить.
или даже не JsonArray, а просто String c всем джейсоном.
Я думал, что ответил на этот вопрос в предыдущем сообщении
JsonArray содержит данные вразнобой. Если у меня например 10 видов данных, то в одном массиве может прийти 1,2,5 а в другом 7,8,10. А какой из них мне нужно решаю уже внутри приложения. Следовательно нужно парсить, что бы посмотреть что внутри

String хранить не вижу смысла по той причине, что он в конце концов тоже будет очищаться и забираться GC, по сути тоже самое, только объект поменьше
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
17.07.2013, 01:01     Оптимизация приложения. Слишком часто вызывается GC #19
Цитата Сообщение от MonStar Посмотреть сообщение
String хранить не вижу смысла по той причине, что он в конце концов тоже будет очищаться и забираться GC, по сути тоже самое, только объект поменьше
ну, 1 объект лучше чем 100.
Цитата Сообщение от MonStar Посмотреть сообщение
JsonArray содержит данные вразнобой. Если у меня например 10 видов данных, то в одном массиве может прийти 1,2,5 а в другом 7,8,10. А какой из них мне нужно решаю уже внутри приложения. Следовательно нужно парсить, что бы посмотреть что внутри
ну так храните 10 объектов, вам же не нужно полностью пропарсить объект чтобы узнать его тип?
так где конкретно парсинг происходит покажите?

Добавлено через 2 минуты
а то написали в теме "Оптимизация приложения", а код этого приложения не показываете.
друдно что-то советовать если не видно полной картины.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.07.2013, 01:13     Оптимизация приложения. Слишком часто вызывается GC
Еще ссылки по теме:

Когда вызывается конструктор дописанного view? Android
Android После засыпания вызывается onCreate и onRestoreInstanceState
OnCreate вызывается дважды Android
Android C# оптимизация приложения под разные экраны(не GUI)
Android Подскажите - не вызывается метод в потоке

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
MonStar
19 / 19 / 3
Регистрация: 10.04.2011
Сообщений: 225
17.07.2013, 01:13  [ТС]     Оптимизация приложения. Слишком часто вызывается GC #20
Цитата Сообщение от V0v1k Посмотреть сообщение
а то написали в теме "Оптимизация приложения", а код этого приложения не показываете.
друдно что-то советовать если не видно полной картины.
Сомневаюсь, что поможет лишняя сотня классов, которая затрагивает другие части приложения. По возможности могу показать, что где происходит конечно.

Метод ниже подключается к непрерывному потоку WebSocket'а и постоянно получает строки в виде JsonArray
Java
1
2
3
4
5
6
7
8
9
10
11
public void onMessage(String message) {
        try {
            jsonArray = new JSONArray(message);
            int lenght = jsonArray.length();
            for (int i = 0; i < lenght; i++) {
                model = new TickerInstrumentModel(jsonArray.getJSONObject(i));
                tickerContent.updateContent(model);
            }
        } catch (Exception e) {
        }
    }
Сначала парсится весь Array, а потом каждый объект в отдельности. Как я сказал по задумке встроенного JSON в Android это происходит в момент создания объекта. TickerInstrumentModel - это наследник JsonObject.

Потом модель передается в управление контентом, где метод isNeeded(instrument) решает, нужно нам это или нет. Если нет то он просто отпадает, если да, то сохраняется в Map. В итоге Map хранит 50 различных объектов (ключ всегда одинаковый), но с разными данными.
Java
1
2
3
4
5
6
7
8
9
    
private Map<String, TickerInstrumentModel> models;
 
public void updateContent(TickerInstrumentModel model) {
        String instrument = model.getInstrument();
        if (isNeeded(instrument)) {
            models.put(instrument, model);
        }
    }

Затем в момент, когда потребовалось получить все данные (предыдущие закончились) вызывается такой метод
Java
1
2
3
    public void requestContent(final IContentBuildCallback callback) {
        contentBuilder.build(models, settings, callback);
    }
Он отдает Map наверх в UI и я его отображаю в виде бегущей строки.

Добавлено через 1 минуту
Цитата Сообщение от V0v1k Посмотреть сообщение
ну так храните 10 объектов, вам же не нужно полностью пропарсить объект чтобы узнать его тип?
Нужно полностью парсить обязательно, иначе не узнать что внутри


Пока писал, что-то упустил. JSON парсится в момент создания объекта на сколько я знаю. Это
Java
1
new JSONArray(message);
и
Java
1
new TickerInstrumentModel(jsonArray.getJSONObject(i));
Yandex
Объявления
17.07.2013, 01:13     Оптимизация приложения. Слишком часто вызывается GC
Ответ Создать тему
Опции темы

Текущее время: 16:42. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru