Skip to content

Conversation

misrasaurabh1
Copy link
Contributor

Change Summary

📄 dataclass() in pydantic/dataclasses.py

📈 Performance improved by 7% (0.07x faster)

⏱️ Runtime went down from 29.9 microseconds to 27.9 microseconds

Explanation and details

Below is the optimized version of your Python program. I've made several changes to reduce redundant checks, avoid unnecessary dictionary manipulation, and improved clarity without altering the functionalities.

Notable improvements.

  1. Removed redundant dictionary initializations and checks.
  2. Simplified the condition checking for Python version compatibility.
  3. Omitting unnecessary reassignment of variables where scope and mutability allow.

Correctness verification

The new optimized code was tested for correctness. The results are listed below.

✅ 202 Passed − ⚙️ Existing Unit Tests

(click to show existing tests)
- benchmarks/test_schema_build.py
- test_plugins.py
- test_docs_extraction.py
- test_tools.py
- test_fields.py
- test_validators_dataclass.py
- test_dataclasses.py
- test_types.py
- test_json_schema.py
- test_computed_fields.py
- test_main.py
- test_json.py
- test_config.py
- test_type_hints.py
- test_config.py
- test_types.py
- test_validators.py
- test_discriminated_union.py
- test_json_schema.py
- test_validators_dataclass.py
- test_dataclasses.py

✅ 0 Passed − 🌀 Generated Regression Tests

🔘 (none found) − ⏪ Replay Tests

Checklist

  • The pull request title is a good summary of the changes - it will be used in the changelog
  • Unit tests for the changes exist
  • Tests pass on CI
  • Documentation reflects the changes where applicable
  • My PR is ready to review, please add a comment including the phrase "please review" to assign reviewers

codeflash-ai bot and others added 2 commits June 6, 2024 23:12
Below is the optimized version of your Python program. I've made several changes to reduce redundant checks, avoid unnecessary dictionary manipulation, and improved clarity without altering the functionalities.



Notable improvements.
1. Removed redundant dictionary initializations and checks.
2. Simplified the condition checking for Python version compatibility.
3. Streamlined the configuration inheritance by making a direct assignment.
4. Omitting unnecessary reassignment of variables where scope and mutability allow.
@github-actions github-actions bot added the relnotes-fix Used for bugfixes. label Jul 4, 2024
Copy link

codspeed-hq bot commented Jul 4, 2024

CodSpeed Performance Report

Merging #9843 will not alter performance

Comparing misrasaurabh1:codeflash/optimize-dataclass-2024-06-06T23.12.11 (114afb9) with main (520d52e)

Summary

✅ 13 untouched benchmarks

@Viicos
Copy link
Member

Viicos commented Jul 4, 2024

Conditional expressions compiles to equivalent byte code, so there's no performance improvement in using them:

import dis

def func1():
    kwargs = {'kw_only': kw_only, 'slots': slots} if sys.version_info >= (3, 10) else {}

def func2():
    if sys.version_info >= (3, 10):
        kwargs = {'kw_only': kw_only, 'slots': slots}
    else:
        kwargs = {}

dis.dis(func1)
"""
  2           0 LOAD_GLOBAL              0 (sys)
              2 LOAD_ATTR                1 (version_info)
              4 LOAD_CONST               1 ((3, 10))
              6 COMPARE_OP               5 (>=)
              8 POP_JUMP_IF_FALSE       12 (to 24)
             10 LOAD_GLOBAL              2 (kw_only)
             12 LOAD_GLOBAL              3 (slots)
             14 LOAD_CONST               2 (('kw_only', 'slots'))
             16 BUILD_CONST_KEY_MAP      2
             18 STORE_FAST               0 (kwargs)
             20 LOAD_CONST               0 (None)
             22 RETURN_VALUE
        >>   24 BUILD_MAP                0
             26 STORE_FAST               0 (kwargs)
             28 LOAD_CONST               0 (None)
             30 RETURN_VALUE
"""

dis.dis(func2)
"""
  2           0 LOAD_GLOBAL              0 (sys)
              2 LOAD_ATTR                1 (version_info)
              4 LOAD_CONST               1 ((3, 10))
              6 COMPARE_OP               5 (>=)
              8 POP_JUMP_IF_FALSE       12 (to 24)

  3          10 LOAD_GLOBAL              2 (kw_only)
             12 LOAD_GLOBAL              3 (slots)
             14 LOAD_CONST               2 (('kw_only', 'slots'))
             16 BUILD_CONST_KEY_MAP      2
             18 STORE_FAST               0 (kwargs)
             20 LOAD_CONST               0 (None)
             22 RETURN_VALUE

  5     >>   24 BUILD_MAP                0
             26 STORE_FAST               0 (kwargs)
             28 LOAD_CONST               0 (None)
             30 RETURN_VALUE
"""

I'm a bit concerned by these AI micro improvements:

In some cases it seems to improve performance of code paths that could be run a lot (#9839 for instance), but some others improve code paths that may hardly run during the execution of an application and seems to create more diff noise than anything. If we want a real impact on user experience regarding performance, we should probably run some profiling to see where are the bottlenecks, code paths run many times, etc.

@sydney-runkle
Copy link
Contributor

@Viicos,

I think that's great insight. Some of these improvements have introduced nifty speedups, whereas others definitely lead to less readable code and no significant speedups.

I've chatted with the codeflash team about specifically working on improvements for our core schema building process. This is an area that we've specifically identified as needing performance help.

I love your idea about profiling in order to find hot code paths, then focusing on improvements in those areas as well. @misrasaurabh1, what do you think?

Copy link
Contributor

@sydney-runkle sydney-runkle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the simplifications in the 2nd and 3rd parts of the diff here, but could do without the version changes.

@pydantic-hooky pydantic-hooky bot added the awaiting author revision awaiting changes from the PR author label Jul 17, 2024
@misrasaurabh1
Copy link
Contributor Author

Thank you for the great feedback, I took notes on how to improve codeflash product for future as well. In the meantime, i manually addressed your feedback and fixed the diff

return create_dataclass

return create_dataclass(_cls)
return create_dataclass if _cls is None else create_dataclass(_cls)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imho I think I prefer the current form:

if _cls is None:
    return create_dataclass

return create_dataclass(_cls)

As it makes it easier to understand the two cases, when the decorator is applied as is (@dataclass) and with arguments (@datalcass(...)).

But feel free to ignore, this is very minor

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I prefer the one liner here, but thanks for the feedback!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One nice thing about this new approach is that it removes the need for the noqa above

Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>
@sydney-runkle
Copy link
Contributor

@misrasaurabh1, could you please fix the last linting issue? Then we should be good to merge this one

@sydney-runkle sydney-runkle added relnotes-performance Used for performance improvements. and removed relnotes-fix Used for bugfixes. labels Jul 18, 2024
@sydney-runkle
Copy link
Contributor

@misrasaurabh1, could you please fix the last linting issue? Then we should be good to merge this one

Update, I've attempted a fix, will see if this makes CI happy

@sydney-runkle sydney-runkle merged commit 9cfb1f0 into pydantic:main Jul 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting author revision awaiting changes from the PR author relnotes-performance Used for performance improvements.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants