Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 10.07.2014, 23:52
Профессор
Отправить личное сообщение для l-liava-l Посмотреть профиль Найти все сообщения от l-liava-l
 
Регистрация: 14.03.2012
Сообщений: 1,808

Откуда лаги?
Доброго времени суток.

Я чесна не вдупляю откуда лаги, вот обьясните, может алгоритм кривой или что то не учел (все еще бесконечный скроллинг)


Кода много, поэтому опишу архитектуру



Сервер отдает обьявления заданным числом по запросу. Висит бесконечный скроллинг ionic фреймоврка, и когда доскроливаем до конца делается запрос.

2 директивы

1) watch-ем следит за изменением длинны массива jsono-в обьявлений, каждый раз при срабатывании (пришли данные с сервера) из полученного генерируется html шаблон, компилится ангуляром,вставляется в dom, узнаем его высоту и даем абсолютную позицию и display none. Устанавливаем ему top относительно предыдущего обьявления (высота + позиция).

Все, эта директива срабатывает только 1 раз при загрузке обяьвлений и особо не грузит.

На выходе из нее получаем два массива в контроллере
1) Все вставленные обьявления (дом элементы)
2) и массив с координатами низа и верха обьявлений

ЗЫ
тоесть, все обьявления парсятся, добавляются в дом скрытыми, а потом мы уже оперируем только с массивами ссылок на эти элементы и их позициями (которые фиксированы и скрытые элементы лежат там где нужно)

2) директива уже вызывается с завидным постоянством
requestanimationframe, следим за скроллингом, если был скролл то вызываем функцию, которой отдаем верхнюю и нижнюю точку экрана. боунд клиент ректом

В этой функции мы перебираем массив (его вернула 1 директива) с элементами и проверяем какой из них попадает в зону видимости
for advertId of buffer
          if (top - bufferZone) <= marginBottom[advertId] <= (bottom + bufferZone) or
             (top - bufferZone) <= marginTop[advertId] <= (bottom + bufferZone)
             visible.push advertId

Отслеживаю верхнюю и нижнюю часть обьявлений попадающих под видимость экрана и буферную зону (чтобы обьявления успевали гененрироваться)

Кстати, чтобы не ловить лагов при переборе огромного кол-ва элементов в массиве dom-элементов, я слайсом копирую часть огромного массива, где находится пользователь +- один элемент, в общем перебор ведется не по 200 элементному а по 6.

Все видимые айдишники элементов добавляются в массив visible, и запускается функция, которая перебирает этот массив (обычно 2 - 3 элемента) и дает им всем (получае доступ по ид из главного большого массива) display inline.

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

зы
я конечно могу замутить оптимизацию, чтобы скроллинг угадывал куда собирается скроллить пользователь. Это не сложно, но не думаю что сильно изменится производительнсоть


зы зы
Спааасииити погибаю! 2 недели пилю эту хрень уже столько способов перепробовал.

Находил вот это
http://habrahabr.ru/post/204350/
Но у него работает всего лишь на 400 сотнях, текстовых нод

А мне нужно хотя бы на 400 обьявлений с слайдерами (которые автоматом крутятся иногда) и текстом (а лагает и без слайдеров) Да еще и на телефонах
__________________
Научу себя плохому

Последний раз редактировалось l-liava-l, 11.07.2014 в 00:05.
Ответить с цитированием
  #2 (permalink)  
Старый 11.07.2014, 10:14
Профессор
Отправить личное сообщение для DjDiablo Посмотреть профиль Найти все сообщения от DjDiablo
 
Регистрация: 04.02.2011
Сообщений: 1,815

Покажи исходники и пример того что должно получиться. Хотя бы скрин с того что есть.

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

Очень интересно что происходит с невидимыми слайдерами в частности отключаются ли они после скрытия.
__________________
Лучше калымить в гандурасе чем гандурасить на колыме

Последний раз редактировалось DjDiablo, 11.07.2014 в 10:51.
Ответить с цитированием
  #3 (permalink)  
Старый 11.07.2014, 15:46
Профессор
Отправить личное сообщение для l-liava-l Посмотреть профиль Найти все сообщения от l-liava-l
 
Регистрация: 14.03.2012
Сообщений: 1,808

DjDiablo,
Чуть попозже покажу, сейчас не удобно.

Кстати, ангуляр же каждый раз когда происходит событие заного компилит дом, а точнее делает хэш, сравнивает с предыдущим и если отличаются то компилит да?
__________________
Научу себя плохому
Ответить с цитированием
  #4 (permalink)  
Старый 11.07.2014, 16:04
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Сообщение от l-liava-l
Кстати, ангуляр же каждый раз когда происходит событие заного компилит дом, а точнее делает хэш, сравнивает с предыдущим и если отличаются то компилит да?
нет
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #5 (permalink)  
Старый 12.07.2014, 13:39
Профессор
Отправить личное сообщение для DjDiablo Посмотреть профиль Найти все сообщения от DjDiablo
 
Регистрация: 04.02.2011
Сообщений: 1,815

Я тут поразмышлял на досуге на твоей задачей и запилил с нуля эксперимент. В принципе сейчас в хроме скролятся 40 000 директив с таймерами без каких либо ощутимых проблем

вот что получилось.

1) Во первых я прикинул что если я скрою 20000 элементов какой либо директивой типо ng-show то у меня будет 20 000 watch которые будут наблюдать за тем не изменилось ли значение в ng-show, а это гарантированные тормоза. Такая перспектива меня совсем не улыбала и Я реализовал подход в котором добавляются и компилируются только элементы которые были невидимы но стали видимы после смещения скролла, элементы выходящие за границы видимости удаляются. А те элементы которые были видимы раньше и остались видимы после смещения скролла ни как не изменяются. То есть я минимизировал количество манипуляций с DOM и компиляций выполнив их все вручную отказавшись от использования шаблонизатора.

2) Шага один оказалось недостаточно и на большом количестве элементов появились тормоза. Как выяснилось после удаления остался работать таймер в удаленных директивах (о чем кстатии недвухсмысленно предупреждают в документации). Встал вопрос о том как убить таймер. В итоге каждую директиву я научил определять не вышла ли она за границы видимой зоны и если вышла то останавливать таймер и все watch. Я хотел сделать чтобы при выходе за границы директива еще сама и себя удаляла, но watch в директиве работает с опозданием и директивы при скролинге не успевают удаляться вовремя.


Удаление и вставка элементов вероятно является не обязательной и достаточно будет просто чтобы скрытый элемент заглушил таймер и все watch, напротив при появлении в видимой зоне все таймеры и наблюдатели должны ожить. Тобишь функция которая оживит watch и таймеры должна быть запущена infinityScroll'ом но ни как не watche'ром в самой директиве ибо мы опять получим тысячи тормозных watch.

Резюмируя результаты эксперимента могу сказать что
1) ключом к успеху является отписывание от событий/таймеров/наблюдений элементов вышедших за пределы видимой зоны. То есть это задача больше вставленной в infinityScroll директивы чем самого infinityScroll.
2) Еще важный момент в том чтобы не допустить в шаблонизаторе десятков тысяч одновременно работающих ng-if/ng-show и т.п. поскольку каждая такая директива использует дорогой $scope.$watch.
3) Следует избегать полной перегенерации dom при небольшом смещении скролла (но это не самый критичный момент)

Пощупать опыт можно здесь.
для генерации кучи записей кликните на скролл и удерживайте pageDown
<iframe width="100%" height="750" src="http://jsfiddle.net/5hAy2/3/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>


В данный момент снижается гладкость скроллинга при очень большом количестве записей. Это связано с перебором массива items целиком но это можно исправить через оптимизацию поиска в массиве items элементов которые должны быть видимы , удаляемые же элементы можно найти просто перебрав кэш.

P.S. Код эксперементальный на скорую руку как следствие грязный но надеюсь что этого будет достаточно чтобы понять смысл.

P.P.S Потом если будет время то я еще по экспериментирую с шаблонизатором. Думаю если написать умный аналог ng-repeat который возьмет на себя задачу с минимизацией манипуляциями dom то этого будет вполне достаточно чтобы заменить Render и RenderItem шаблонизацией. В принципе на умный ng-repeat можно повесить и задачу информирования удаляемых элементов об их удалении (если не найду другой приемлемый способ(UPD: уже найден)) чтобы те могли остановить таймеры. Вместо удаления также можно попробовать сваять умный ng-repeat заточенный под скрытие элементов вместо удаления и информирующий детей о скрытии и наоборот о появлении что те могли остановить таймер. Нужно еще попробывать запись item in items track by $id(item.id) чото я ее непомню может ее раньше небыло. В общем пока что я пребываю в размышлениях обо всем этом.

P.P.P.S пожалуй стоит еще с $scope.$on('$destroy',function(){}); поэксперементировать. (UPD: выбрал element.$on("$destroy",..))
__________________
Лучше калымить в гандурасе чем гандурасить на колыме

Последний раз редактировалось DjDiablo, 12.07.2014 в 18:15.
Ответить с цитированием
  #6 (permalink)  
Старый 12.07.2014, 17:35
Профессор
Отправить личное сообщение для DjDiablo Посмотреть профиль Найти все сообщения от DjDiablo
 
Регистрация: 04.02.2011
Сообщений: 1,815

Немного переписанный вариант с использованием element.on("$destroy",function(){}); вместо отслеживания директивой выхода за границы видимой области, генерации событий из вне и прочей фигни.

ссылка на fiddle http://jsfiddle.net/5hAy2/6/
__________________
Лучше калымить в гандурасе чем гандурасить на колыме

Последний раз редактировалось DjDiablo, 12.07.2014 в 18:02.
Ответить с цитированием
  #7 (permalink)  
Старый 14.07.2014, 01:02
Профессор
Отправить личное сообщение для l-liava-l Посмотреть профиль Найти все сообщения от l-liava-l
 
Регистрация: 14.03.2012
Сообщений: 1,808

DjDiablo,
Я тебя люблю... так заботишься


Цитата:
Немного переписанный вариант с использованием element.on("$destroy",function(){}); вместо отслеживания директивой выхода за границы видимой области, генерации событий из вне и прочей фигни.
Столько пробелм потому что ему нельзя запретить рэндерить шаблон....
__________________
Научу себя плохому

Последний раз редактировалось l-liava-l, 14.07.2014 в 01:09.
Ответить с цитированием
  #8 (permalink)  
Старый 14.07.2014, 01:04
Профессор
Отправить личное сообщение для l-liava-l Посмотреть профиль Найти все сообщения от l-liava-l
 
Регистрация: 14.03.2012
Сообщений: 1,808

nerv_,
Тогда че меня путали мануалы из сети??? Ты хочешь сказать оно хэш не делает? а тупо идет парсить сразу?
адддд
__________________
Научу себя плохому

Последний раз редактировалось l-liava-l, 14.07.2014 в 01:16.
Ответить с цитированием
  #9 (permalink)  
Старый 15.07.2014, 02:35
Профессор
Отправить личное сообщение для l-liava-l Посмотреть профиль Найти все сообщения от l-liava-l
 
Регистрация: 14.03.2012
Сообщений: 1,808

http://habrahabr.ru/post/215607/
__________________
Научу себя плохому
Ответить с цитированием
  #10 (permalink)  
Старый 16.07.2014, 16:15
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Сообщение от l-liava-l
Ты хочешь сказать оно хэш не делает?
хэш для чего? Для модели делает, для dom нет.
про возможные оптимизации есть тема, линк я давал.
Т.е. эту тему можно было не создавать, а перечитать тему про оптимизацию.
А создавать тему без кода... Лаги оттуда)
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Подмена класса при скроллинге (лаги) fAmOus Элементы интерфейса 5 26.03.2014 02:34
откуда скачать ScriptJava фреймворк Alisher Библиотеки/Тулкиты/Фреймворки 4 01.02.2012 16:08
Имитация селектов: огромный отступ непонятно откуда exec jQuery 0 23.06.2010 21:20
Как проверить откуда пришел пользователь! toxiz77 Общие вопросы Javascript 2 27.10.2009 20:55
откуда берется промежуток? (DOCTYPE виноват) mister_maxim (X)HTML/CSS 5 27.03.2009 02:11