나는 그렇게 / 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 개). 내가 설정 한 경우 doneLoading
에 true
, 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가 걸립니다. 정확한 숫자는 연결 (대기 시간 및 대역폭)에 따라 다르지만 파이프 라인 버전은 항상 훨씬 더 빠릅니다.