태그 보관물: firebase

firebase

단일 이벤트를 반복적으로 관찰하는 대신 쿼리를 사용하여 내 소셜 네트워크 앱의 게시물 가져 오기 속도를 높입니다. 0 && !self.hitNull {

나는 그렇게 / posts / id / (post info)와 같은 내 소셜 네트워크에 대한 게시 개체로 이어지는 일련의 키를 가지고 있습니다.

게시물을로드 할 때 observeSingleEventOfType(.Value)메소드를 사용하여 / posts / 0을로드 한 다음 / posts / 1 등을로드합니다 .

나는 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에서 키 번호 i의 값을 가져 오는 데 실행됩니다. NSNULL이면로드 할 수있는 마지막 게시물임을 알고 다시는 수행하지 않습니다. NSNULL이 적중되지 않으면 i % 29 == 0기본 케이스로 반환되므로 한 번에 30 개의 게시물 만로드됩니다 (인덱싱 된 0 개). 내가 설정 한 경우 doneLoadingtrue, tableView.reloadData()속성 관찰자를 사용하여 호출한다.

다음은 내가 가져 오는 배열의 샘플입니다.

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



답변

업데이트 : 이제 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 배를 기다리고 있습니다. (간단 함을 위해) 왕복에 1 초가 걸리고 디스크에서 항목을로드하는데도 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 클라이언트가 기본적으로 수행하는 것처럼) 600ms가 걸립니다. 정확한 숫자는 연결 (대기 시간 및 대역폭)에 따라 다르지만 파이프 라인 버전은 항상 훨씬 더 빠릅니다.


답변