GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — pickletools optimize performance degraded with factor 3-4 in python 3.14 · Issue #140175 · python/cpython

pickletools optimize performance degraded with factor 3-4 in python 3.14 #140175

New issue
Copy link
New issue
Copy link
Closed as duplicate
Closed as duplicate
pickletools optimize performance degraded with factor 3-4 in python 3.14#140175
Copy link
Labels
performancePerformance or resource usagePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@ghost
ghost
opened on Oct 15, 2025

Bug report

Bug description:

The pickletools.optimize code suddenly performs bad starting with python 3.14, with or without JIT.
The degradation is a factor 3 to 4.

It is easy to test.

First use this script to make a sizeable dict and pickle it and write it to file.

import pickle

x = {}

for i in range(1, 1000000):
    x[i] = f"ii{i:>07}"

with open("pickled", "wb") as fh:
    pickle.dump(x, fh, protocol=4)

Then write a script, let's call it optpickle.py to read the pickled dict from file and optimize it and write the result to another file.

# optpickle.py

import pickletools

with open("pickled", "rb") as fh:
    p = fh.read()

s = pickletools.optimize(p)

with open("pickledopt", "wb") as fh:
    fh.write(s)

Now execute this in three separate terminal windows, one geared to python 3.13, one to python 3.14.0 without JIT, and one to python 3.14.0 with JIT.

My results on a mac with M1 processor were

version time elapsed cpu time
3.13 1.67 1.773
3.14.0 no JIT 6.52 6.664
3.14.0 JIT 6.52 6.642

That is a dramatic drop in performance!

The filesizes are 16.9 MB for the unoptimized file and 15.9 for the optimized one.

I decided to drop the optimization in an app where I used it heavily

CPython versions tested on:

3.14

Operating systems tested on:

macOS

Activity

  1. ghost added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Oct 15, 2025
  2. StanFromIreland
    added
    performancePerformance or resource usagePerformance or resource usage
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    on Oct 15, 2025
  3. StanFromIreland
    added this to Pickle and copy issues 🥒on Oct 15, 2025
  4. StanFromIreland commented on Oct 15, 2025

    @StanFromIreland
    StanFromIreland
    on Oct 15, 2025
    Member
    More actions

    Are your results an average, or just one off tests?

  5. tim-one commented on Oct 15, 2025

    @tim-one
    tim-one
    on Oct 15, 2025
    Member
    More actions

    Just curious about how things might change if you added:

    import gc
    gc.disable()
    

    Another recent report (sorry, can't find it now) pointed out slowdowns when creating lots of little tuples, due to changes in the cyclic garbage collector (which isn't really needed here). optimize() does create lots of little tuples.

  6. sergey-miryanov commented on Oct 15, 2025

    @sergey-miryanov
    sergey-miryanov
    on Oct 15, 2025
    Contributor
    More actions

    @tim-one #139951

    Reacted by Tim Peters
  7. tim-one commented on Oct 15, 2025

    @tim-one
    tim-one
    on Oct 15, 2025
    Member
    More actions

    FYI, on my box (Win10 Pro with the released 3.14.0 from pyhon.org), the time for your second script drops from about 12 seconds to about 4 seconds when disabling gc, and enclosing the body of your script in a loop to run both ways repeatedly (to factor out possible "warmup" distortions).

  8. tim-one commented on Oct 16, 2025

    @tim-one
    tim-one
    on Oct 16, 2025
    Member
    More actions

    @dirkroorda, thank you for the very thorough and helpful follow-ups! You've done more than your share here 😄

    pickletools.optimize() rarely saves much. What it's aiming at: pickling is a 1-pass process, writing out "opcodes" as it goes along. When an object is pickled, there's no way to know whether that object may appear again as a sub-object in the entire object graph being pickled. So, "just in case", a PUT opcode is pumped out after a single object's pickle has been produced. If the same object is encountered again, a GET opcode is emitted referencing the index of that object saved away by PUT.

    It's often the case that a given PUT is never referenced again. All optimize() aims at is removing the PUT opcodes that are never used. But a PUT opcode occupies few bytes, and there can't be more of them than there are individual sub-objects pickled. Bytes produced for the payload (actual data bytes) typically account for the vast bulk of a pickle stream. optimize() can't do anything to shrink those.

    So optimize() is rarely worth the bother. I wrote optimize(), so that's not just sour grapes 😉. Nevertheless, it can be useful in some niche cases. I used to be a "gc expert" too, but that's changed a lot since my days on it, and I no longer have actual insight into how it currently works. So I can't do more here than confirm that this really has almost nothing to do with optimize(), apart from that it creates object graphs of kinds that provoke 3.14's version of gc into bad performance.

    I have no doubt that the current gc experts have already thought of several ways that could be repaired.

  9. sergey-miryanov commented on Oct 27, 2025

    @sergey-miryanov
    sergey-miryanov
    on Oct 27, 2025
    Contributor
    More actions

    @dirkroorda Since #139951 has been fixed and merged, could you please confirm whether it works for you?

    Reacted by Mikhail Efimov and Tim Peters
  10. efimov-mikhail commented on Oct 27, 2025

    @efimov-mikhail
    efimov-mikhail
    on Oct 27, 2025
    Member
    More actions

    Link to merged PR: #140262

    Reacted by Tim Peters
  11. tim-one commented on Oct 27, 2025

    @tim-one
    tim-one
    on Oct 27, 2025
    Member
    More actions

    On current main branch, whether or not gc is enabled makes scant difference now to the speed of the OP's test case. So closing,, as fixed by #140262.

  12. tim-one
    closed this as completedon Oct 27, 2025
  13. github-project-automation
    moved this to Done in Pickle and copy issues 🥒on Oct 27, 2025
  14. StanFromIreland
    closed this as a duplicateof Potentially serious regression in garbage collector performance in Python 3.14 #139951 on Oct 27, 2025
  15. efimov-mikhail commented on Oct 29, 2025

    @efimov-mikhail
    efimov-mikhail
    on Oct 29, 2025
    Member
    More actions

    I'll have to figure out how I can get a python where this is fixed. Maybe I'll wait till Python is a tad closer to π

    You can make Python (3.14 or 3.15) from the source code (see https://devguide.python.org/#quick-reference).
    Or you can wait for Python 3.14.1 to be released, of course.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    performancePerformance or resource usagePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    • Pickle and copy issues 🥒
      Status
      Done
      Show more project fields

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402520 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.