Consider: Feature to readonly fetch without dirty tracking for performance?

In some times when I have profiled expensive parts of some apps, it’s seemed that instantiating full ActiveRecord models is actually quite expensive. And when trying to profile that, it’s seemed that the apparatus for dirty tracking – all the object instantiation that is required to do it especially – is one of the expensive parts.

If this is accurate, I wonder if anyone has ever considered an AR feature where you could ask to fetch records with read-only set (already a feature), and that when doing so dirty tracking woudl actually not be set up at all or available. With the goal being improved performance and reduced RAM consumption (and GC work) by eliminating the setup for dirty tracking – in use cases where you don’t plan on editing/saving the objects, which are pretty common actually.

Curious if this seems like an interesting path, or if anyone knows of any previous consideration?

1 Like

I don’t think this one concept alone is the reason for AR instances being so resource intensive. Also dirty tracking should only get triggered if checked. Also this raises a lot of questions. Do these methods no longer exist? Now you have an “AR” record that doesn’t abide by the AR interface. If they do exist what do they return? You can’t say always true/false cause it could be dirty. So, How would you entail this actually work?

Since you are saying you simply don’t want them available you are kind of saying “I don’t want AR at all” your easiest alternative is probably to use a class or Data “model” and instantiate those from using pluck()

Can you share any of your traces showing dirty tracking utilizing substantial resources?

I’m definitely not saying I don’t want ActiveRecord at all! Just that for many front-end use cases, models get fetched for display and no editing. You wouldn’t tell people that if they don’t mutate and persist on every fetch they sound like they’re saying they don’t want ActiveRecord, that’s just weird!

When you mark a model “readonly” (which you already can do), it will raise if you do certain things that otherwise woudl be okay. If you fetch a model with strict_loading, it will raise if you do certain things that otherwise would not raise. There are probably more examples. It is established that models can be in certain states where some functions raise.

Anyway, I didn’t come here to argue about it – you answered the question that you personally do not see the point of this, ok, heard!

1 Like

I will have to dig into it again. I somehow thought this was accepted common knowledge, but maybe not? The issue was lots of objects being instantiated to set up the state, a cost paid on instantiation. But okay, I’ll have to spend some time digging in for a clear way to report. It’s possibleI am wrong – I had thought I had seen other people talking about this, and it was an understood thing.

Heh… My apologize. I wasn’t trying to say “you don’t want AR”.

But the statement still stands, I doubt Dirty Tracking is [the only] reason instantiating AR instances is so slow. AR instances are big. As far as I know dirty tracking is lazy, and only checked when requested (or saving) and has nothing to do with the instantiation time. If you simply didn’t want mutatable instances you can freeze them, but again, has nothing to do with instantiation time.

You could setup your own custom AM models with only the pieces of AM you want, and see if the performance is much better. Without looking at some sort of profiling though, I’d say AR instantiation is slow cause of a lot of little things, not one or two big things.

I’m personally curious what an “immutable” active record object would look like. AR objects usually have enough readers/accessors/associations that I can see the usefulness in the idea.

I also see the alternative being: can the things you profiled be sped up rather than disabled?

1 Like