Я использую Rails 3.0.0 + passenger + apache2, работающий на Ruby 1.9.2p290 на экземпляре ec2.
Соответствующие настройки Пассажира (я с ними много не играл):
PassengerMaxPoolSize 30
PassengerPoolIdleTime 0
PassengerMinInstances 10
Кроме того, я подтвердил, что НЕ связан с памятью или процессором ...
Я провел несколько тестов и очень смущен результатами. У меня есть вызов, который делает довольно сложный запрос, который объединяет 5 различных предложений .where (). (Другими словами, он использует AREL совсем немного.)
Когда я запускаю Apache Bench с 1000 вызовами БЕЗ ИСТОРИИ (например, ab -n 1000 -c 1), я получаю следующее:
Concurrency Level: 1
Time taken for tests: 222.799 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 489000 bytes
HTML transferred: 16000 bytes
Requests per second: 4.49 [#/sec] (mean)
Time per request: 222.799 [ms] (mean)
Time per request: 222.799 [ms] (mean, across all concurrent requests)
Transfer rate: 2.14 [Kbytes/sec] received
Теперь, когда я запускаю его с параллелизмом, установленным на 10 (например, ab -n 1000 -c 10), я получаю следующее:
Concurrency Level: 10
Time taken for tests: 213.957 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 489001 bytes
HTML transferred: 16000 bytes
Requests per second: 4.67 [#/sec] (mean)
Time per request: 2139.567 [ms] (mean)
Time per request: 213.957 [ms] (mean, across all concurrent requests)
Transfer rate: 2.23 [Kbytes/sec] received
Там нет абсолютно никакой пользы от одновременных запросов! Запрос в секунду по-прежнему на уровне ~ 4,5. Как будто сервер обрабатывает запросы последовательно.
Теперь о действительно странной части. Если я посмотрю на выведенный SQL-запрос из интерфейса запросов ActiveRecord и вместо этого просто использую find_by_sql, я получу это без параллелизма:
Concurrency Level: 1
Time taken for tests: 49.547 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 489000 bytes
HTML transferred: 16000 bytes
Requests per second: 20.18 [#/sec] (mean)
Time per request: 49.547 [ms] (mean)
Time per request: 49.547 [ms] (mean, across all concurrent requests)
Transfer rate: 9.64 [Kbytes/sec] received
Здесь нет сюрпризов. find_by_sql работает быстрее, чем ActiveRecord и AREL для построения запросов. НО, если я запускаю предыдущий с параллелизмом, установленным в 10, я получаю:
Concurrency Level: 10
Time taken for tests: 17.859 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 489000 bytes
HTML transferred: 16000 bytes
Requests per second: 55.99 [#/sec] (mean)
Time per request: 178.587 [ms] (mean)
Time per request: 17.859 [ms] (mean, across all concurrent requests)
Transfer rate: 26.74 [Kbytes/sec] received
Обратите внимание, что количество запросов в секунду увеличивается в 3 раза. Итак, мой вопрос:
Как / Почему использование ActiveRecord (и AREL) для построения запросов приводит к тому, что параллельные запросы так плохо отвечают? Может ли ActiveRecord быть настолько загруженным процессором?