- PVSM.RU - https://www.pvsm.ru -
Вывод результата в 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:
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 [1], но возвращает массив хэшей, а не массив значений одного поля. Вызовем наш новый метод в контроллере:
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 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)
Обобщенные результаты теста [5]:
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
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ruby/16122
Ссылки в тексте:
[1] pluck: https://github.com/rails/rails/blob/f8f4ac91203506c94d547ee0ef530bd60faf97ed/activerecord/lib/active_record/relation/calculations.rb#L169-184
[2] JSON: https://github.com/flori/json
[3] Yajl: https://github.com/brianmario/yajl-ruby
[4] Oj: https://github.com/ohler55/oj
[5] теста: https://gist.github.com/a012d50e817373c08f79
Нажмите здесь для печати.