Показать сообщение отдельно
Старый 15.12.2014, 13:25   #2
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений
(для 886 пользователей)
Ответ: Смесь: Неочевидное + Оптимизация

0. Для справки

Внутренние объекты java при дефолтном создании:

* Vector - элементы хранятся в массиве.
v = new Vector() - выделяется память под 10 элементов, при выходе за границы внутренний массив вектора пересоздаётся, расширяясь вдвое (могу наврать тут, может и не в 2)

* Hashtable
h = new Hashtable() - размерность таблицы равна 11, хз почему так

* StringBuffer - данные хранятся во внутреннем массиве chars[]
sb = new StringBuffer() - размерность равна 16


1. Коннект и реконнект к чат-серверу

Раньше
при каждом подключении или переподключении создавался новый поток, в котором новый сокет.

Теперь
есть всего 1 бесконечный сетевой поток, внутри которого могут много раз пересоздаваться объекты типа сокет.
вынес всю логику переподключения в класс сетевого потока, так что в логике приложения просто делаем коннект и забываем о нём, и если произойдёт разрыв сокета, то он автоматически будет пытаться восстановить коннект


2. Загрузка ресурсов по http

Раньше
а) на каждый запрос картинки создавался отдельный поток в лоадере
б) для каждой загрузки страницы создавался новый лоадер + поток в нём

Теперь
есть всего 1 бесконечный поток лоадера, внутрь которого вкидываются задачи на загрузку ресурсов.
Пока остаётся под вопросом реализация ajax-запросов, наверное для аякса придётся мастерить отдельный поток, чтобы отклик не зависел от текущих запросов на загрузку других ресурсов.


3. LinkedList vs Vector

Стараюсь по возможности заменить использование Vector на LinkedList, чтобы не тратились ресурсы при расширении размерности вектора.
* LinkedList - мой самодельный двунаправленный список, ибо в комплекте j2me списков нет.
Vector хорош, когда нужен произвольный доступ к элементам по индексу в массиве.


4. Шрифты

Используются рисованные шрифты. При загрузке красятся в несколько цветов.
Для кнопочной версии приложения красим, подменяя цвета в палитре, для сенсорной версии переводим картинку в rgba[], красим через hsv преобразование, и далее создаём из полученных new_rgba[] новую картинку.

Раньше
для каждого шрифта грузились все данные, картинки + описательные структуры данных, массивы смещений символов и массивы ширин букв и прочее

Теперь
для одинаковых шрифтов, различающихся только цветом, грузим описательные структуры только 1 раз, остальным шрифтам присваиваем указатели на эти структуры.
В частности, в шрифте есть массивы
* private int arrWidth[];
* private int arrBlock[];
* private int arrOffset[];
Количество символов = 337. На 1 шрифт приходится 337*3*4 = 4044 байта. Умножим это на 5 крашенных вариантов и получим 20,2 кб. гуд!



5. Смайлы, ч1

Раньше мы использовали анимированные смайлы.
Пришлось для хранения смайла использовать класс View, который умеет проигрывать анимацию.
View содержит набор Pic
Pic содержит ImageObject
ImageObject содержит Image (это джавовская картинка)
* ImageObject - обёртка над стандартной картинкой, хранить ключ-url и саму картинку, и немного служебной инфы

Раньше
каждый смайл имел тип View

Теперь
каждый смайл имеет тип ImageObject
Это позволило съэконосить 70 кб памяти!
В любом случае, буду делать рефактор классов View и Pic.


6. Смайлы, ч2
В данный момент пытаюсь улучшить функцию разбивки текста на текст и смайлы.
RegExp'ов в j2me нет, да они и оперативы жрут скорее всего больше доступного.
Всего есть 76 текстовых вариантов смайлов.

Сейчас
1. проходим по всем смайлам, ищём их в строке, запоминаем самый ближний к началу строки
2. делим строку на текст до смайла (если есть), сам смайл (если есть) и остаток строки снова подаём на вход пункта 1.

Пока что сделал предварительную проверку по 4 символам, которые уникальны для смайлов - : ; % ) и др.
Для строк без смайлов это даёт прирост скорости раз в 7. Со смайлами - замедляет, но не сильно, т.к. джавовский string.IndexOf() работает очень шустро.


Сложение строк

На днях я обнаружил опасность.
При сложении строк компилятор подставляет туда StringBuffer.
s = s+"1024"; превратится в
s = new StringBuffer().append(s).append(1024).toString();

Bроде всё круто, но при этом StringBuffer будет пересоздавать/расширять внутренний массив, и мы получаем в оперативке массив, почти вдвое больший чем сумма наших исходных строк!

В джаве строки - это структуры со ссылкой на массив chars[] и переменными start и len.

Если текст жирный, например 10+ кб, как браузерная страница, то прибавлением к строке любого символа расширит строку до двукратного размера.

Можно обрезать лишние символы в оперативке через
s = new String(s)
если на них больше никто не ссылается, но они всё равно будут живы до очередного вызова сборщика мусора.


Продолжение следует.
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо Жека за это полезное сообщение:
Randomize (16.12.2014), St_AnGer (16.12.2014)