2013-11-04 44 views
0

我有一個iPad應用程序,它連續記錄手指位置(每秒多達30次),如果它在屏幕上並將「樣本」對象保存到每個數據集的核心數據記錄。過了一段時間,也許兩三分鐘,這個過程或至少用戶的反饋變得非常慢。如果我關閉應用程序並重新啓動,它從一開始就很慢,但刪除持久存儲區有助於恢復其原始性能。因此我認爲這個問題應該與數據存儲有關。使用一對多關係的CoreData性能

我試圖用時間分析器來檢測問題,但大部分時間都是由系統庫和非Objective-C代碼消耗的。如果我關閉它們的分析,剩下最耗時的方法是樣品對象的初始化:

@implementation Sample (Create) 
+(Sample *)sampleWithTime:(double)time 
      xValue:(double)x 
      yValue:(double)y 
      eventType:(EventType)event 
     chillStatus:(BOOL)chill 
     participant:(Participant *)whoListened 
       track:(Track *)whichTrack 
inManagedObjectContext:(NSManagedObjectContext *)context 
{ 
    Sample *sample; 
    if (!sample) { 
    sample = [NSEntityDescription insertNewObjectForEntityForName:@"Sample" inManagedObjectContext:context]; 
    sample.time = time; 
    sample.x = x; 
    sample.y = y; 
    sample.event = event; 
    sample.chillStatus = chill; 
    sample.whichTrack = whichTrack; 
    sample.whoListened = whoListened; 
    } 
    return sample; 
} 

sample.whichTrack =哪個軌道;建立與該方法給出的跟蹤對象(ManagedObject子類,指正在播放的音樂)的關係。這是一個一對多的關係,因爲每個樣本只有一個軌道,但每個軌道有很多樣本。這條線然後消耗整個方法的87%的時間,即使下一條線正在做相同並且與此相比幾乎不需要任何東西。

這是否有任何意義在這裏尋找問題?數據庫可以慢得多,因爲關係中的一組對象變得更大,並且必須被複制來添加一個對象或類似的東西?有什麼我可以做的改善表現?數據庫作爲一個文件根本不會變大,它仍然不到1 MB。

+0

您是否在每個樣品之​​後保存?是在這3分鐘內爲同一個「Track」完成的樣本? –

+0

是的,當我爲了一個「軌道」而需要很多「樣本」時,速度會變慢。如果我爲另一個「音軌」錄製某些內容,它會很快開始並在一段時間後放慢速度。錄製時我沒有做任何明確的保存,只是在最後。 我想知道如果在關係中添加一個'Sample'會花費很多時間,因爲集合越來越大,每次添加內容時都必須在後臺複製。這對於與'參與者'(='whoListened')的其他關係來說是有意義的,因爲我往往會經常改變這個數量。 – user2953959

回答

1

它在那裏搜索問題很有意義。

我假設你設定whichTrack(一對一)的關係與反samplesTrack對象(一對多)的關係。

你拿30 Sample s/sec ==> 3min的採樣在同一個Track上將保持:5400個對象處於多對多關係。這種關係在兩端都得到維護,這意味着無論何時插入一個新的樣本,都必須從商店獲取整個對象集合(至少它們的錯誤)(如果尚未出現故障的話)。
如果您在每個新的Sample後保存並釋放上下文(重置或刷新Track對象),則在下次訪問Track項目時,需要重新獲取多對多關係中的所有現有項目。

我會嘗試首先刪除反向關係(Track實體的多對一側)並查看其行爲。
小心,因爲這將消除Track刪除(的Sample對象)的任何級聯。

如果您仍然需要在Track級聯刪除,你可以自己添加一個prepareForDeletion實現你的Track實體添加。

另一個解決方案(更優雅)是將您的樣本分成SampleContainer對象。
A Track對象將與SampleContainer有多對多的關係。
每個容器將被限制爲'N'個樣品。
裝滿容器時,請將新容器添加到Track

除此之外:
您只能在每個'T'時間間隔內執行一次保存。這將進一步減少商店訪問(保存),但這可能不適合你,因爲如果用戶在兩次保存之間終止應用程序(在進入後臺之前始終可以保存),則可能會鬆動。

+0

謝謝你的回答。我現在嘗試了第一種方法,它看起來工作得很好,而且速度非常快,但是當我找到一些時間時,我可能會去找對象的容器,因爲我同意這會更加優雅。 我讀過很多反對使用非逆關係的論點。那麼,我只需要將「逆向」更改爲「無反向關係」,還是應該對目標或刪除規則進行任何操作?或者我可以阻止訪問代碼中的一對多關係,因爲現在我完全停止了它的設置。 – user2953959

+0

關於添加:除了在viewWillDisappear左右,我沒有做任何明確的保存。 e。 G。調用'insertNewObjectForEntityForName:'方法已經引發了一個保存操作?我認爲系統每隔一段時間就自動保存一次,所以我只需要確保它最終發生,而且我從來沒有遇到任何問題。 – user2953959

+0

這可能也是一個問題。上下文中沒有默認保存調用,您必須自己觸發它。設備上一次性保存5000個對象可能需要一分多鐘。 –