2012-10-03 151 views
1

我正在使用ASP.NET 4.0構建一個應用程序。存儲Facebook喜歡本地 - 喜歡性能問題的數量

我有一個表稱爲條目。參賽作品可以通過Facebook獲得。我想實現通過喜歡排序的能力,所以我正在採取爲每個條目存儲喜歡數量並使用該列進行排序的方法。問題是獲得喜歡數量的開銷。我認爲我現在使用的方法可以改進,因爲只有13個條目的數據只需要4秒鐘,這太長了。

我使用FB圖api和JSON.NET來解析響應。在下面的代碼中,我有一個Entry類型的列表,我使用與條目id結合的應用程序設置獲取條目的URL。 這是我在做什麼:

foreach (Entry entry in entries) 
     { 
      int likes; 
      try 
      { 
       // the url that is tied to the entry 
       string url = "http://graph.facebook.com/?ids=" + Properties.Settings.Default.likeUrl + "?id=" + entry.EntryId; 
       //open a WebClient and get the results of the url 
       WebClient client = new WebClient(); 

      Stream data = client.OpenRead(url); 
      StreamReader reader = new StreamReader(data); 
      string s = reader.ReadToEnd(); 
      //parse out the response 
      var json = JObject.Parse(s); 
      //shares are how many likes the entry has 
      likes = Convert.ToInt32(json.First.First.SelectToken("shares").ToString()); 

     } 
     catch (Exception ex) 
     { 
      likes = 0; 
     } 

    } 

正如我所說的這個方法是非常昂貴的。如果有人可以建議一個更好的方式來做我在這裏嘗試的東西,我會非常感激這個幫助。非常感謝!

+0

呃..你必須至少得到一次喜歡的次數,這樣做是異步的,同時你將有一個響應式UI。之後,你可以緩存它,只要你喜歡。問題是什麼? – Robert

+0

嗨。主要問題是它非常緩慢且耗時。正如我所說,13個條目需要4秒鐘。將有大約500個參賽作品,超過兩分鐘。我希望找到一個更有效的方法來做到這一點。 – TheMethod

+0

已經做出了基準?哪一部分需要這麼長時間? –

回答

1

由於發出網絡請求的開銷,對循環中的每個項目執行單獨的API調用將會很慢。你有沒有考慮過將所有13個項目的查詢分配到一個API調用中?我不知道它是否適用於您正在運行的查詢,但我知道Facebook API支持批量查詢方法。您可以運行批處理,以便輸出到同一批次中的其他查詢。您可能必須切換到通過Graph API進行FQL查詢。

您可能還會考慮將API調用移動到客戶端,並使用javascript API實現它們。這會將API工作卸載到用戶的瀏覽器上,這會讓您的應用程序更好地擴展。如果你不這樣做,你至少應該考慮Robert提出的異步撥打電話的建議。

+0

這就是我最終要做的事情,批量查詢比單個查詢要快得多。 – TheMethod

2

方法

您不會處置您的流或流讀取器。這對個人表現可能沒有幫助,但是稍後可能會出現減速......也嘗試使用parallel extentions,這需要在處理變量時多加小心。這只是一個例子:

編輯:我忘了webclient也是一次性的。這需要每次處理,否則它將暫時掛在連接上。這實際上可能會有所幫助。

private object locker; 
private int _likes = 0; 

private int Likes 
{ 
    get 
    { 
     lock(locker) 
     { 
      return _likes; 
     } 
    } 
    set 
    { 
     lock(locker) 
     { 
      _likes = value; 
     } 
    } 
} 


void MyMethod() 
{ 
    Parallel.ForEach(entries, entry => 
    { 
     using(WebClient client = new WebClient()) 
     using(Stream data = client.OpenRead(url)) 
     using(StreamReader reader = new StreamReader(data)) 
     { 
     .... 
     } 
    } 
}