Подтвердить что ты не робот

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

У меня есть массив ключей, которые приводят к публикации объектов для моей социальной сети, например,/posts/id/(информация о публикации)

Когда я загружаю посты, я загружаю /posts/0, а затем /posts/1 и т.д., Используя метод observeSingleEventOfType(.Value).

Я использую lazyTableView для загрузки 30 одновременно, и это довольно медленно. Есть ли способ, которым я могу использовать один из методов запроса или другой способ сделать это быстрее, даже если мне придется реструктурировать данные в моем дереве JSON.

Я прихожу из Parse, повторно внедряю свое приложение, и пока опыт был довольно хорошим. Только одна вещь, на которой я немного застрял. Заранее спасибо за помощь!

РЕДАКТИРОВАТЬ:

func loadNext(i: Int) { 

    // check if exhists
    let ideaPostsRef = Firebase(url: "https://APPURL")

    ideaPostsRef.childByAppendingPath(i.description).observeSingleEventOfType(.Value, withBlock: {
        (snapshot) in

        if i % 29 == 0 && i != 0 && !self.hitNull { return }
            // false if nil
            // true if not nil
        if !(snapshot.value is NSNull) {
            let postJSON  = snapshot.value as! [String: AnyObject]
            print("GOT VALID \(postJSON)")
            let post = IdeaPost(message: postJSON["message"] as! String, byUser: postJSON["user"] as! String, withId: i.description)
            post.upvotes = postJSON["upvotes"] as! Int
            self.ideaPostDataSource.append(post)
            self.loadNext(i + 1)
        } else {
            // doesn't exhist
            print("GOT NULL RETURNING AT \(i)")
            self.doneLoading = true
            self.hitNull = true
            return
        }
    }
}

Эта рекурсивная функция, по сути, запускает получение значения для ключа номер я из firebase. Если это NSNULL, он знает, что это последний возможный пост для загрузки, и никогда не делает снова. Если NSNULL не получен, но i % 29 == 0 он возвращается в качестве базового варианта, поэтому одновременно загружаются только 30 сообщений (индексировано 0). Когда я устанавливаю doneLoading в true, tableView.reloadData() вызывается с помощью наблюдателя свойства.

Вот пример того, как выглядит массив, который я выбираю

"ideaPosts" : [ {
    "id" : 0,
    "message" : "Test",
    "upvotes" : 1,
    "user" : "Anonymous"
  }, {
    "id" : 1,
    "message" : "Test2",
    "upvotes" : 1,
    "user" : "Anonymous"
  } ]
4b9b3361

Ответ 1

Обновление: теперь мы также рассматриваем этот вопрос в эпизоде ​​AskFirebase.

Загрузка многих элементов из Firebase не должна быть медленной, поскольку вы можете конвейерно запросить запросы. Но ваш код делает это невозможным, что действительно приведет к субоптимальной производительности.

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

Your app                     Firebase 
                             Database

        -- request item 1 -->
                               S  L
                               e  o
                               r  a
                               v  d
                               e  i
        <-  return item  1 --  r  n
                                  g
        -- request item 2 -->
                               S  L
                               e  o
                               r  a
                               v  d
                               e  i
                               r  n
        <-  return item  2 --     g
        -- request item 3 -->
                 .
                 .
                 .
        -- request item 30-->
                               S  L
                               e  o
                               r  a
                               v  d
                               e  i
                               r  n
                                  g
        <-  return item 30 --

В этом сценарии вы ожидаете 30-кратного времени вашего перехвата времени + 30 раз больше времени, необходимого для загрузки данных с диска. Если (для простоты) мы говорим, что roundtrips занимают 1 секунду, а загрузка элемента с диска также занимает одну секунду, что меньше 30 * (1 + 1) = 60 секунд.

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

Your app                     Firebase 
                             Database

        -- request item 1 -->
        -- request item 2 -->  S  L
        -- request item 3 -->  e  o
                 .             r  a
                 .             v  d
                 .             e  i
        -- request item 30-->  r  n
                                  g
        <-  return item  1 --     
        <-  return item  2 --      
        <-  return item  3 --
                 .
                 .
                 .
        <-  return item 30 --

Если мы снова возьмем 1-секундный кругооборот и 1 секунду загрузки, вы ждете 30 * 1 + 1 = 31 секунд.

Итак: все запросы проходят через одно и то же соединение. Учитывая это, единственная разница между get(1), get(2), get(3) и getAll([1,2,3]) - это некоторые издержки для фреймов.

Я установил jsbin, чтобы продемонстрировать поведение. Модель данных очень проста, но это показывает разницу.

function loadVideosSequential(videoIds) {
  if (videoIds.length > 0) {
    db.child('videos').child(videoIds[0]).once('value', snapshot => {
      if (videoIds.length > 1) {
        loadVideosSequential(videoIds.splice(1), callback)
      }
    });
  }
}

function loadVideosParallel(videoIds) {
  Promise.all(
    videoIds.map(id => db.child('videos').child(id).once('value'))
  );
}

Для сравнения: последовательная загрузка 64 элементов занимает 3,8 секунды в моей системе, а при загрузке их конвейерно (так как клиент Firebase выполняется изначально) требуется 600 мс. Точные цифры будут зависеть от вашего соединения (латентность и пропускная способность), но конвейерная версия всегда должна быть значительно быстрее.