Guru on Rails

if you don’t sacrifice for your dream then your dream becomes your sacrifice.
Sydney, Sat 01 Jun 2019
Callbacks in model might make performance worse
Wed 05 Sep 2018

I encountered this issue yesterday. It's hard to find the cause because of callbacks. We create objects and we use them somewhere in the scope. We created callbacks for models before but when we use them in next few days, we won't touch these callbacks. That makes us not notice about them. Sometimes callbacks are not really necessary. We should skip them to improve performance.

For example, when we make upload function for evaluation. Uploading evaluation from mobile with hundreds of photos. We'd like to improve uploading time. We don't want to make users wait in long time. Unluckily that we implemented callbacks for Image Model.

before_create :make_thumbnails

That means every time we want to create an image, make_thumbnails will be called first. What happen if we create hundreds or thousands of images? make_thumbnails will be called thousands of times. But wait, it's not a matter until we see that make_thumbnails processes images by downloading from AWS, cropping, resizing etc. 

In order to improve the time of upload we should pull the make_thumbnails out. We still make thumbnails but we don't do that at uploading time. We put this process to delayed jobs so that users won't see the delayed time. We enqueue them all or schedule them to run at specific time. 

But how can we do that in ruby (the same idea for other language). Firstly, we need to check how many callbacks.

Image._create_callbacks.select { |cb| cb.kind == :before }

We skip and reset callbacks of Image model like this.

Image.skip_callback(:create, :before, :make_thumbnails)
# Doing something without make_thumbnails callback
Image.set_callback(:create, :before, :make_thumbnails)