2009-08-20 14 views
0

Ich mache eine datenintensive Webanwendung, die ich zu optimieren versuche. Ich habe von Forking und Threading gehört, aber ich habe keine Ahnung, ob sie auf das anwendbar sind, was ich versuche, und wenn ja, wie sie umgesetzt werden. Mein Code sieht wie folgt aus:Wie beschleunige ich meine Ruby-Anwendung?

def search 
     @amazon_data=Hash.from_xml(item.retrieve_amazon(params[:sku])) 
     unless @amazon_data['results'] == nil 
      @amazon_data['results']['item'].size.times do |i| 
      @all_books << { :vendor => 'Amazon.com', 
          :price => @amazon_data['results']['item'][i]['price'].to_f, 
          :shipping => @amazon_data['results']['item'][i]['ship'].to_f, 
          :condition => @amazon_data['results']['item'][i]['condition'], 
          :total => @amazon_data['results']['item'][i]['price'].to_f + @amazon_data['results']['item'][i]['ship'].to_f, 
          :availability => 'In Stock', 
          :link_text => 'Go to Amazon.com', 
          :link_url => "http://www.amazon.com/gp/offer-listing/#{params[:isbn]}" 
      } 
     end 
     end 
     @ebay_data=Hash.from_xml(Book.retrieve_ebay(params[:sku])) 
     unless @ebay_data['results'] == nil 
      @ebay_data['results']['item'].size.times do |i| 
      @all_books << { :vendor => 'eBay', 
          :price => @ebay_data['results']['item'][i]['price'].to_f, 
          :shipping => @ebay_data['results']['item'][i]['ship'].to_f, 
          :condition => 'Used', 
          :total => @ebay_data['results']['item'][i]['price'].to_f + @ebay_data['results']['item'][i]['ship'].to_f, 
          :availability => 'In Stock', 
          :link_text => 'Go to eBay', 
          :link_url => "http://www.amazon.com/gp/offer-listing/#{params[:sku]}" 
      } 
     end 
    end 
    end 

Also, im Grunde, was ich habe, sind zwei Aktionen, die Daten von eBay und Amazon abrufen und hier analysieren. Wie kann ich beide Aktionen gleichzeitig ausführen? Haben Fork oder Thread irgendetwas damit zu tun, was ich erreichen will?


Dies schneidet die API-Zeit in zwei Hälften, aber ich weiß nicht, wie Sie die Ergebnisse zurückgeben. Die nachfolgende Ansicht wird geladen, bevor die API-Ergebnisse zurückgegeben werden .... Es werden jedoch Daten zurückgegeben. Wenn ich Code in

puts @all_books 

innerhalb der Thread-Ergebnisse in der Konsole angezeigt werden. Außerhalb des Threads werden jedoch keine Ergebnisse zurückgegeben.

def search 
    Thread.new do 
     @amazon_data=Hash.from_xml(item.retrieve_amazon(params[:sku])) 
     unless @amazon_data['results'] == nil 
      @amazon_data['results']['item'].size.times do |i| 
      @all_books << { :vendor => 'Amazon.com', 
          :price => @amazon_data['results']['item'][i]['price'].to_f, 
          :shipping => @amazon_data['results']['item'][i]['ship'].to_f, 
          :condition => @amazon_data['results']['item'][i]['condition'], 
          :total => @amazon_data['results']['item'][i]['price'].to_f + @amazon_data['results']['item'][i]['ship'].to_f, 
          :availability => 'In Stock', 
          :link_text => 'Go to Amazon.com', 
          :link_url => "http://www.amazon.com/gp/offer-listing/#{params[:isbn]}" 
      } 
     end 
     end 
    end 
    Thread.new do 
     @ebay_data=Hash.from_xml(Book.retrieve_ebay(params[:sku])) 
     unless @ebay_data['results'] == nil 
      @ebay_data['results']['item'].size.times do |i| 
      @all_books << { :vendor => 'eBay', 
          :price => @ebay_data['results']['item'][i]['price'].to_f, 
          :shipping => @ebay_data['results']['item'][i]['ship'].to_f, 
          :condition => 'Used', 
          :total => @ebay_data['results']['item'][i]['price'].to_f + @ebay_data['results']['item'][i]['ship'].to_f, 
          :availability => 'In Stock', 
          :link_text => 'Go to eBay', 
          :link_url => "http://www.amazon.com/gp/offer-listing/#{params[:sku]}" 
      } 
     end 
     end 
    end 
    end 

Bin ich auf dem richtigen Weg? Wie kann ich die Ergebnisse aus dem Thread zurückgeben? Ist die Variable nur innerhalb des Threads zugänglich, oder besteht das Problem darin, dass das Programm fortschreitet, bevor die Ergebnisse zurückgegeben werden?


Leider erfordert die Anwendung Echtzeit-Benutzereingabe, um die APIs abzufragen. Die zurückgegebenen Daten müssen neu sein, da es sich um Produktpreise auf Marktplätzen handelt ... Zum Beispiel würde ein Benutzer eine SKU eingeben und mit diesen Informationen würde das Programm eine Anfrage an die entsprechenden Websites stellen (in diesem Fall Amazon und eBay) .) Derzeit macht es die Anfrage an Amazon, analysiert die Daten, formatiert sie und geht dann zu eBay, analysiert die Daten und formatiert diese. Dann werden die formatierten Daten in der Ansicht angezeigt.

Mein Gedanke war, wenn ich diese API-Aufrufe zur gleichen Zeit (auf verschiedenen Threads) machen könnte, würde es Zeit auf dem Web-Server-Ende sparen, da alles erforderlich wäre, die zurückgegebenen Daten zu analysieren und korrekt zu formatieren. (Was ich vielleicht auch beschleunigen könnte ...)

Antwort

1

Ja, ich denke immer noch, dass Sie in diesem Fall mit einem Job Scheduler besser dran wären. Die absolut schnellste, die eine solche Aktion ausführen kann, ist die langsamer der zwei API-Anfragen --- und Sie haben keine Garantien über Netzwerk-Latenz, laden auf der Remote-API, etc. Andere müssen Sie implementieren etwas Javascript-Code, der regelmäßig abfragt, um den Abschluss des Jobs zu erkennen und den Benutzer über die Ergebnisse zu informieren.

Auch kann das Verhalten des Fadens in Ruby 1.8 manchmal etwas funky sein, besonders im Maßstab, also Vorsicht.

0

Es ist schwer ohne weitere Informationen zu sagen, aber mein Verdacht ist, dass das Warten auf die API-Antworten, wo die meiste Zeit verbracht wird.

Versuchen Sie einen anderen Ansatz, bei dem die Anfrage und Verarbeitung der API-Antwort in einem anderen Prozess als der Web-Serving-Prozess behandelt wird. Der Front-End-Code muss wahrscheinlich regelmäßig nach Ergebnissen suchen und die Ergebnisse der Operation in die Seite einfügen. Aber gewinnen ist, dass die ganze Anfrage nicht gesichert wird, auf Amazon und Ebay zu warten, um ihr Ding zu tun.

Es gibt mehrere Plugins, die helfen können, delayed_job ist ein guter Ausgangspunkt.

0

Sie können sich auch EventMachine ansehen, mit der Sie Ihre ausgehenden Netzwerkanrufe auf nicht blockierende Weise ausführen können. Wenn Sie das erste Ergebnis an den Benutzer zurückgeben können, um das Endergebnis über Ajax zu erhalten, wird sich die Benutzerinteraktion schneller anfühlen.

Dies ist ähnlich wie bei Kayak.com mit seiner Echtzeit-Flugsuche.

Sie könnten auch Caching-Ergebnisse in Betracht ziehen, diese schnell an den Benutzer zurückgeben und dann die aktualisierten Ergebnisse (die Sie async geladen haben) über Ajax auffüllen. (Sie müssen herausfinden, die richtige Benutzeroberfläche für das, vielleicht nur "populäre" Ergebnisse über die Falte, und dann die neuesten Updates unter der Falte oder etwas)

* EventMachine ist kompliziert

Verwandte Themen