Вывод результата в JSON достаточно прост в Rails:
render json: @statuses
Это работает отлично, если нужно вывести небольшое количество записей. Но что случится, если нам потребуется вывести сразу 10'000 записей? Производительность серьезно просядет, а самыми затратными по времени окажутся сериализация JSON и операции с базой данных.
Включайте только необходимые атрибуты
Первое очевидное решение — генерировать JSON только с необходимыми нам атрибутами, т.е.:
render json: @statuses, methods: [:latitude, :longitude, :timestamp, :virtual_odometer]
Отфильтрованный JSON даст нам более 20% прироста производительности:
default 5.940000 0.080000 6.020000 ( 6.094221)
attrs 4.820000 0.010000 4.830000 ( 4.932337)
Делайте выборку только необходимых полей
Второе решение — забирать из базы не все, а только необходимые нам поля.
render json: @statuses.select([:latitude, :longitude, :timestamp, :virtual_odometer])
Это поможет нам избежать передачи огромного количества лишних данных из базы в приложение и даст нам 2х прирост скорости:
default 5.940000 0.080000 6.020000 ( 6.094221)
attrs 4.820000 0.010000 4.830000 ( 4.932337)
select 2.170000 0.020000 2.190000 ( 2.222277)
Не инициализируйте объекты ActiveRecord, если это возможно
Давайте реализуем метод, который будет возвращать «молниеносный» массив хэшей вместо объектов ActiveRecord:
def self.lightning
connection.select_all(select([:latitude, :longitude, :timestamp, :virtual_odometer]).arel).each do |attrs|
attrs.each_key do |attr|
attrs[attr] = type_cast_attribute(attr, attrs)
end
end
end
Это работает также как метод pluck, но возвращает массив хэшей, а не массив значений одного поля. Вызовем наш новый метод в контроллере:
render json: @statuses.lightning
Использование легковесных хэшей ускоряет создание JSON еще в 2 раза:
default 5.940000 0.080000 6.020000 ( 6.094221)
attrs 4.820000 0.010000 4.830000 ( 4.932337)
select 2.170000 0.020000 2.190000 ( 2.222277)
lightning 1.120000 0.010000 1.130000 ( 1.148763)
Используйте самый быстрый дампер JSON
На текущий момент доступно несколько библиотек JSON:
- JSON — gem JSON по-умолчанию (+ C-расширения, поставляется вместе с Ruby 1.9)
- Yajl — Yet Another JSON Library (автор Brian Lopez)
- Oj — Optimized JSON (автор Peter Ohler)
Хорошая идея использовать самую быструю из них:
json 0.810000 0.020000 0.830000 ( 0.841307)
yajl 0.760000 0.020000 0.780000 ( 0.809903)
oj 0.640000 0.010000 0.650000 ( 0.666230)
Так что мы выбираем Oj дампер:
render json: Oj.dump(@statuses.lightning, mode: :compat)
Обобщенные результаты теста:
user system total real
default 5.940000 0.080000 6.020000 ( 6.094221)
attrs 4.820000 0.010000 4.830000 ( 4.932337)
select 2.170000 0.020000 2.190000 ( 2.222277)
lightning 1.120000 0.010000 1.130000 ( 1.148763)
json 0.810000 0.020000 0.830000 ( 0.841307)
yajl 0.760000 0.020000 0.780000 ( 0.809903)
oj 0.640000 0.010000 0.650000 ( 0.666230)
Автор: Svyatov