-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Document explicit speedup approaches. #1994
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thanks for the work. |
The main speedup comes from 1) ability to use unsorted output (unfortunately Sorted/OrderedDicts are slow), and 2) skipping is_simple_callable() checks. The latter is harder to support in a clean and completely safe way. |
Echoing @xordoquy here, yup. Almost certainly not a trade-off we'd consider, but certainly worth investigating anything that can make it simpler to do this as a third party serializer base class. To expand on this slightly...
Eg...
We'd also want to document up the advanced usage of how and when you'd want to use a sorted dict,, or the |
Closing. Very much appreciate the input, but not quite in the direction I'd like us to take things for the reasons outlined above. Don't take that as meaning that we can't discuss this or similar ideas further, but keeping scope and direction on-track in the meantime. |
@tomchristie Is there a way we can keep track of this work ? I'd like to keep it on our radars. |
@xordoquy Happy for us to open a documentation ticket as detailed above, or role it into #1976. Anything else depends on where @akaariai wants to take this. If there are API hooks that we ought to be adding into the serializer class in order to support these sorts of modifications then we can consider those on a case-by-case basis. @akaariai Apologies also for my directness wrt to closing tickets off, not at all any comment on the worthiness on the patch, I've just been maintaining the project long enough now I think we've got a good feel for what helps and what harms the long-term maintenance and end-user usability of the project, and I'm very strongly in favor of us optimising for simplest-possible wherever possible. |
My work was mainly trying to check where DRF uses extra time that could be easy to shave off. So, +1 to closing this :) While the benchmark presented wasn't too realistic, I currently have a need for a faster serializer than what DRF can offer. When just reading objects from DB and serializing them the Serializer class is a bottleneck even in version-3.0. Of course, we aren't talking about huge changes here Another idea could be adding a couple of built-in to_representation functions (or just documenting them).
Then, document how to write a faster to_representation() method, and point out that DRF includes these two convenience methods you can use directly. As a bonus these methods gives a runtime of 1.9s compared to 3.1s of this PR's version (or almost 5x faster than version-3.0). See akaariai@b2336f0 for this idea. |
Strongly in favour of documenting something like this...
Not sure about pulling the source into the package tho - rather call it out very explicitly as an example, but force folks to deal with any of the subtleties of the limitations it introduces themselves. Pulling it into core we'd almost certainly get 'but it doesn't work in XYZ case' etc... This would also be a good conversation to have around where we introduce Noting that you don't always need to be using Reopening this ticket, and re-naming as documentation-focused. |
Oh wait, not correct, given that this was a PR. I'll open as a seperate issue instead. Sorry for the noise. |
I implemented quickly a way to use non-ordered dicts, see akaariai@2ee4cdc. There shouldn't be any cave-eats with the approach except of course your output will be non-ordered. See the commit message for how to use the approach. If this approach seems like something you'd like to support, then I am happy to open a separate pull request for that. This could also be implemented as a mixin outside DRF if the BTW If this PR isn't appropriate place for discussing further ideas I am happy to continue this discussion somewhere else. Also, thanks for your fast and informative responses to this PR! |
I'm also seeing slowness issue with OrderedDict (#2454), but related to pickling. I like the customizable |
I wouldn't currently be in a favor of that. For the large majority of cases DB access is going to be the limiting factor, so I'd prefer for this to just be an advanced bit of API limited to the serializers. |
I think this is still a good thing to do (customizable I'll try to get an updated patch (off of DRF 3.1), submit PR and maybe include some performance tests |
I've implemented a couple of ideas to speed up rest framework. The most important idea is to memoize situations where simple getattr calls can be used instead of the full blown get_attribute. This patch also does slight speedup to serializer.to_representation(), and allows using non-sorted output from serializers.
The test case I used was rendering 100000 simple objects with ten simple fields to a JSON list. I am using ensure_ascii when rendering, as that is fastest option.
Current master renders the data to JSON in 24s, while version-3.0 renders it in around 8.2s. When using the patched version with ordered output, the run speed is around 5.1s, and with unordered output, the speed is around 3.1s. All combined the speedup is 8x compared to master. The patched version is 2.6x faster than version-3.0. Dumping the data directly without a serializer takes around 0.9s.
The biggest drawbacks of the used approach are:
data = [Obj(some_attr=datetime.now if i > 1 else None) for i in range(0, 10)]
would not work with the current implementation. Notably caching is_simple_callable is impossible for such data, and most of the speedup comes from bypassing is_simple_callable checks.While the patch passes all tests the work is at proof of concept stage.
After the changes the time is mostly consumed in iterating the fields, calling get_attribute, and then calling field.to_representation(). There isn't any obvious extra work done any more. The top lines of the profile are:
The test script used was: