2009-08-20 30 views
0

我正在制作一个数据密集型Web应用程序,我正试图优化。我听说过分叉和线程化,但我不知道它们是否适用于我正在尝试做的事情,以及如何实现它们。我的代码如下所示:如何加快我的Ruby应用程序?

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 

所以,基本上我有什么是检索来自eBay和亚马逊的数据,并在此解析它两个动作。我该如何让这两个动作同时运行?叉子或线程与我想要完成的事情有什么关系?


这会将API时间缩短一半,但我不知道如何返回结果。在返回API结果之前加载后续视图....但是,它正在返回数据。当我在代码

puts @all_books 

内线程结果显示在控制台。但是,线程之外,结果不会返回。

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 

我在正确的轨道上吗?我怎样才能从线程内返回结果?它是只能在线程中访问的变量,还是问题在于程序在返回结果之前进行的事实?


不幸的是,应用程序需要实时用户输入来查询API。返回的数据必须是新鲜的,因为它与市场中的产品定价有关......例如,用户将进入SKU,并且通过该信息该程序将向适用的网站(亚马逊和eBay在这种情况下。)目前,它向亚马逊提出请求,解析数据,格式化数据,然后转向eBay,分析数据并格式化数据。然后格式化的数据显示在视图中。

我的想法是,如果我可以同时进行这些API调用(在不同的线程上),它可以节省Web服务端的时间,因为所有需要的是解析返回的数据并正确格式化。 (我可能也可以加快......)

回答

1

是的,我仍然认为在这种情况下,您最好带一份工作调度程序。像这样的一个动作可以执行的绝对最快的是两个API请求的较慢的 ---并且您对网络延迟,对远程API的负载等没有保证。另一方面,您将不得不实施一些Javascript代码可以定期轮询以检测作业完成情况并通知用户结果。

此外,在ruby 1.8中的线程行为有时会有些时髦,特别是在规模上,所以要小心。

0

很难说没有更多信息,但我怀疑是等待API响应是大部分时间花费在哪里。

尝试一种不同的方法,其中API响应的请求和处理是在与Web服务进程不同的进程中处理的。前端代码可能必须定期轮询结果,并将操作结果注入页面。但胜利是整个请求没有得到支持,等待亚马逊和Ebay做他们的胜利。

有几个插件可以帮助,delayed_job是一个很好的开始。

0

您也可以看看EventMachine,它允许您以非阻塞方式执行出站网络呼叫。如果您可以将第一个结果返回给用户,那么通过ajax获得最终结果,用户交互感觉会更快。

这与Kayak.com的实时航班搜索功能类似。

您也可以考虑缓存结果,将这些结果快速返回给用户,然后通过ajax填充更新后的结果(即加载的异步)。 (你必须找出正确的用户界面,也许只是把“流行”的结果放在折线之上,然后在折线下面或最近的更新)

* EventMachine很复杂

相关问题