Как мне ускорить работу моего приложения на Ruby? - PullRequest
0 голосов
/ 20 августа 2009

Я делаю веб-приложение с интенсивным использованием данных, которое пытаюсь оптимизировать. Я слышал о разветвлении и потоке, но не знаю, применимы ли они к тому, что я пытаюсь сделать, и если да, то как их реализовать. Мой код выглядит так:

  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 и Amazon и анализируют их здесь. Как я могу заставить оба этих действия выполняться одновременно? Есть ли какое-либо отношение между форком или нитью к тому, чего я пытаюсь достичь?


Это сокращает время 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, и с этой информацией программа делает запрос на соответствующие сайты (в данном случае Amazon и eBay). .) В настоящее время он отправляет запрос в Amazon, анализирует данные, форматирует их, а затем переходит на eBay, анализирует данные и форматирует их. Затем отформатированные данные отображаются в виде.

Я подумал, что если бы я мог выполнять эти вызовы API одновременно (в разных потоках?), Это сэкономило бы время на конце веб-обслуживания, поскольку все, что требовалось бы, - это проанализировать возвращенные данные и правильно отформатировать их. (Что я также мог бы ускорить ...)

Ответы [ 3 ]

1 голос
/ 21 августа 2009

Да, я все еще думаю, что в этом случае вам лучше работать с планировщиком работы. Самое быстрое, что может выполнить подобное действие - это медленнее из двух запросов API - и у вас нет никаких гарантий относительно задержки в сети, загрузки удаленного API и т. Д. Придется реализовать код Javascript для периодического опроса, чтобы определить завершение работы и сообщить пользователю о результатах.

Кроме того, поведение потоков в ruby ​​1.8 иногда может быть довольно забавным, особенно в масштабе, так что будьте осторожны.

0 голосов
/ 15 декабря 2011

Вы также можете заглянуть в EventMachine, который позволяет выполнять исходящие сетевые вызовы неблокирующим способом. Если бы вы могли вернуть первый результат пользователю, получив окончательный результат через ajax, взаимодействие с пользователем будет происходить быстрее.

Это похоже на то, что делает Kayak.com при поиске рейсов в реальном времени.

Вы можете также рассмотреть возможность кэширования результатов, их быстрого возврата пользователю, а затем заполнения обновленных результатов (которые вы загрузили асинхронно) через ajax. (для этого вам нужно найти подходящий пользовательский интерфейс, возможно, просто поместите «популярные» результаты выше сгиба, а затем последние обновления ниже сгиба или еще что-то)

* EventMachine сложен

0 голосов
/ 20 августа 2009

Трудно сказать без дополнительной информации, но я подозреваю, что ожидание ответов API - это то, на что тратится большая часть времени.

Попробуйте другой подход, когда запрос и обработка ответа API обрабатываются не так, как процесс веб-обслуживания. Код переднего плана, скорее всего, будет периодически запрашивать результаты и вставлять результаты операции на страницу. Но победа в том, что весь запрос не будет поддержан в ожидании, пока Amazon и Ebay выполнят свою работу.

Есть несколько плагинов, которые могут помочь, delayed_job - хорошее место для начала.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...