Python 3.11.0rc1 is now available

This is the first release candidate of Python 3.11

https://www.python.org/downloads/release/python-3110rc1/

This release, **3.11.0rc1**, is the penultimate release preview.  Entering the release candidate phase, only reviewed code changes which are clear bug fixes are allowed between this release candidate and the final release. The second candidate and the last planned release preview is currently planned for Monday, 2022-09-05 while the official release is planned for Monday, 2022-10-03.

There will be no ABI changes from this point forward in the 3.11 series and the goal is that there will be as few code changes as possible.

Call to action

Core developers: all eyes on the docs now

* Are all your changes properly documented?

* Did you notice other changes you know of to have insufficient documentation?

Community members

We strongly encourage maintainers of third-party Python projects to prepare their projects for 3.11 compatibilities during this phase. As always, report any issues to the Python bug tracker.

Please keep in mind that this is a preview release and its use is **not** recommended for production environments.

Major new features of the 3.11 series, compared to 3.10

Among the new major new features and changes so far:

  • PEP 657 – Include Fine-Grained Error Locations in Tracebacks
  • PEP 654 – Exception Groups and except*
  • PEP 673 – Self Type
  • PEP 646 – Variadic Generics
  • PEP 680 – tomllib: Support for Parsing TOML in the Standard Library
  • PEP 675 – Arbitrary Literal String Type
  • PEP 655 – Marking individual TypedDict items as required or potentially-missing
  • bpo-46752 – Introduce task groups to asyncio
  • PEP 681 – Data Class Transforms
  • bpo-433030– Atomic grouping ((?>…)) and possessive quantifiers (*+, ++, ?+, {m,n}+) are now supported in regular expressions.
  • The Faster Cpython Project is already yielding some exciting results. Python 3.11 is up to 10-60% faster than Python 3.10. On average, we measured a 1.22x speedup on the standard benchmark suite. See Faster CPython for details.
  • (Hey, fellow core developer, if a feature you find important is missing from this list, let Pablo know.)

The next pre-release of Python 3.11 will be 3.11.0rc2, currently scheduled for  Monday, 2022-09-05.

More resources

And now for something completely different

A quark star is a hypothetical type of compact, exotic star, where extremely high core temperature and pressure have forced nuclear particles to form quark matter, a continuous state of matter consisting of free quarks. 

Some massive stars collapse to form neutron stars at the end of their life cycle, as has been both observed and explained theoretically. Under the extreme temperatures and pressures inside neutron stars, the neutrons are normally kept apart by degeneracy pressure, stabilizing the star and hindering further gravitational collapse. However, it is hypothesized that under even more extreme temperature and pressure, the degeneracy pressure of the neutrons is overcome, and the neutrons are forced to merge and dissolve into their constituent quarks, creating an ultra-dense phase of quark matter based on densely packed quarks. In this state, a new equilibrium is supposed to emerge, as a new degeneracy pressure between the quarks, as well as repulsive electromagnetic forces, will occur and hinder total gravitational collapse.

If these ideas are correct, quark stars might occur, and be observable, somewhere in the universe. Theoretically, such a scenario is seen as scientifically plausible, but it has been impossible to prove both observationally and experimentally because the very extreme conditions needed for stabilizing quark matter cannot be created in any laboratory nor observed directly in nature. The stability of quark matter, and hence the existence of quark stars, is for these reasons among the unsolved problems in physics.

We hope you enjoy the new releases!

Thanks to all of the many volunteers who help make Python Development and these releases possible! Please consider supporting our efforts by volunteering yourself or through organization contributions to the Python Software Foundation.


a2ps @ Savannah: a2ps 4.14.91 released [alpha]

This alpha release marks the return of GNU a2ps to the Translation Project.

Some other minor issues have also been fixed.

Here are the compressed sources and a GPG detached signature:
  https://alpha.gnu.org/gnu/a2ps/a2ps-4.14.91.tar.gz
  https://alpha.gnu.org/gnu/a2ps/a2ps-4.14.91.tar.gz.sig

Use a mirror for higher download bandwidth:
  https://www.gnu.org/order/ftp.html

Here are the SHA1 and SHA256 checksums:

36c2514304132eb2eb8921252145ced28f209182  a2ps-4.14.91.tar.gz
1LQ+pPTsYhMbt09CdSMrTaMP55VIi0MP7oaa+zDvRG0  a2ps-4.14.91.tar.gz

The SHA256 checksum is base64 encoded, instead of the
hexadecimal encoding that most checksum tools default to.

Use a .sig file to verify that the corresponding file (without the
.sig suffix) is intact.  First, be sure to download both the .sig file
and the corresponding tarball.  Then, run a command like this:

  gpg –verify a2ps-4.14.91.tar.gz.sig

The signature should match the fingerprint of the following key:

  pub   rsa2048 2013-12-11 [SC]
        2409 3F01 6FFE 8602 EF44  9BB8 4C8E F3DA 3FD3 7230
  uid   Reuben Thomas <rrt@sc3d.org>
  uid   keybase.io/rrt <rrt@keybase.io>

If that command fails because you don’t have the required public key,
or that public key has expired, try the following commands to retrieve
or refresh it, and then rerun the ‘gpg –verify’ command.

  gpg –locate-external-key rrt@sc3d.org

  gpg –recv-keys 4C8EF3DA3FD37230

  wget -q -O- ‘https://savannah.gnu.org/project/release-gpgkeys.php?group=a2ps&download=1’ | gpg –import –

As a last resort to find the key, you can try the official GNU
keyring:

  wget -q https://ftp.gnu.org/gnu/gnu-keyring.gpg
  gpg –keyring gnu-keyring.gpg –verify a2ps-4.14.91.tar.gz.sig

This release was bootstrapped with the following tools:
  Autoconf 2.69
  Automake 1.16.1
  Gnulib v0.1-5347-gc0c72120f0

NEWS

* Noteworthy changes in release 4.14.91 (2022-08-08) [alpha]
 * Build:
   – Re-add a2ps to the Translation Project, and remove po files from git.
 * Bug fixes:
   – Remove reference to @COM_distill@ variable in a2ps_cfg.in.
 * Documentation:
   – Format –help output consistently to 80 columns.
   – Fix a couple of message typos.

Citing danger of “ink spills” Epson programs end of life for some printers

You have a perfectly healthy, functioning Epson inkjet printer in your home office. It’s served you well for years and you use it frequently. Then, one day, you go to print a document and realize that the printer isn’t working. A message on the display reads “a part inside your printer is at the end of its service life. Service is required.” That’s funny, you think. You hadn’t noticed anything wrong with your printer before this message appeared. The device was working well and the quality of the printing was fine. If nothing was broken, why are you suddenly getting this message? More important: how do you get rid of it so that you can continue using your printer? This should absolutely be criminal behaviour. If there was ever an industry that could do with a worldwide judicial probe and investigation, it’s the printer makers. They employ so many clearly scammy business practices, and get away with them too.

Matt Glaman: ReactPHP for Drupal deployments and workers

I recently held a live stream where I walked through the continuous integration and deployment (CI/CD) of a Drupal project to DigitalOcean’s App Platform and other CI/CD items. App Platform has its quirks, but it’s simple to build an application with various components. My project, Whiskey Dex, builds a Docker image that pushes to my container registry and then updates my App Platform manifest to use the new image tag, triggering a deployment. 

Andy Wingo: coarse or lazy?

sweeping, coarse and lazy

One of the things that had perplexed me about the Immix collector was how to effectively defragment the heap via evacuation while keeping just 2-3% of space as free blocks for an evacuation reserve. The original Immix paper states:

To evacuate the object, the collector uses the same allocator as the mutator, continuing allocation right where the mutator left off. Once it exhausts any unused recyclable blocks, it uses any completely free blocks. By default, immix sets aside a small number of free blocks that it never returns to the global allocator and only ever uses for evacuating. This headroom eases defragmentation and is counted against immix’s overall heap budget. By default immix reserves 2.5% of the heap as compaction headroom, but […] is fairly insensitive to values ranging between 1 and 3%.

To Immix, a “recyclable” block is partially full: it contains surviving data from a previous collection, but also some holes in which to allocate. But when would you have recyclable blocks at evacuation-time? Evacuation occurs as part of collection. Collection usually occurs when there’s no more memory in which to allocate. At that point any recyclable block would have been allocated into already, and won’t become recyclable again until the next trace of the heap identifies the block’s surviving data. Of course after the next trace they could become “empty”, if no object survives, or “full”, if all lines have survivor objects.

In general, after a full allocation cycle, you don’t know much about the heap. If you could easily know where the live data and the holes were, a garbage collector’s job would be much easier 🙂 Any algorithm that starts from the assumption that you know where the holes are can’t be used before a heap trace. So, I was not sure what the Immix paper is meaning here about allocating into recyclable blocks.

Thinking on it again, I realized that Immix might trigger collection early sometimes, before it has exhausted the previous cycle’s set of blocks in which to allocate. As we discussed earlier, there is a case in which you might want to trigger an early compaction: when a large object allocator runs out of blocks to decommission from the immix space. And if one evacuating collection didn’t yield enough free blocks, you might trigger the next one early, reserving some recyclable and empty blocks as evacuation targets.

when do you know what you know: lazy and eager

Consider a basic question, such as “how many bytes in the heap are used by live objects”. In general you don’t know! Indeed you often never know precisely. For example, concurrent collectors often have some amount of “floating garbage” which is unreachable data but which survives across a collection. And of course you don’t know the difference between floating garbage and precious data: if you did, you would have collected the garbage.

Even the idea of “when” is tricky in systems that allow parallel mutator threads. Unless the program has a total ordering of mutations of the object graph, there’s no one timeline with respect to which you can measure the heap. Still, Immix is a stop-the-world collector, and since such collectors synchronously trace the heap while mutators are stopped, these are times when you can exactly compute properties about the heap.

Let’s retake the question of measuring live bytes. For an evacuating semi-space, knowing the number of live bytes after a collection is trivial: all survivors are packed into to-space. But for a mark-sweep space, you would have to compute this information. You could compute it at mark-time, while tracing the graph, but doing so takes time, which means delaying the time at which mutators can start again.

Alternately, for a mark-sweep collector, you can compute free bytes at sweep-time. This is the phase in which you go through the whole heap and return any space that wasn’t marked in the last collection to the allocator, allowing it to be used for fresh allocations. This is the point in the garbage collection cycle in which you can answer questions such as “what is the set of recyclable blocks”: you know what is garbage and you know what is not.

Though you could sweep during the stop-the-world pause, you don’t have to; sweeping only touches dead objects, so it is correct to allow mutators to continue and then sweep as the mutators run. There are two general strategies: spawn a thread that sweeps as fast as it can (concurrent sweeping), or make mutators sweep as needed, just before they allocate (lazy sweeping). But this introduces a lag between when you know and what you know—your count of total live heap bytes describes a time in the past, not the present, because mutators have moved on since then.

For most collectors with a sweep phase, deciding between eager (during the stop-the-world phase) and deferred (concurrent or lazy) sweeping is very easy. You don’t immediately need the information that sweeping allows you to compute; it’s quite sufficient to wait until the next cycle. Moving work out of the stop-the-world phase is a win for mutator responsiveness (latency). Usually people implement lazy sweeping, as it is naturally incremental with the mutator, naturally parallel for parallel mutators, and any sweeping overhead due to cache misses can be mitigated by immediately using swept space for allocation. The case for concurrent sweeping is less clear to me, but if you have cores that would otherwise be idle, sure.

eager coarse sweeping

Immix is interesting in that it chooses to sweep eagerly, during the stop-the-world phase. Instead of sweeping irregularly-sized objects, however, it sweeps over its “line mark” array: one byte for each 128-byte “line” in the mark space. For 32 kB blocks, there will be 256 bytes per block, and line mark bytes in each 4 MB slab of the heap are packed contiguously. Therefore you get relatively good locality, but this just mitigates a cost that other collectors don’t have to pay. So what does eager marking over these coarse 128-byte regions buy Immix?

Firstly, eager sweeping buys you eager identification of empty blocks. If your large object space needs to steal blocks from the mark space, but the mark space doesn’t have enough empties, it can just trigger collection and then it knows if enough blocks are available. If no blocks are available, you can grow the heap or signal out-of-memory. If the lospace (large object space) runs out of blocks before the mark space has used all recyclable blocks, that’s no problem: evacuation can move the survivors of fragmented blocks into these recyclable blocks, which have also already been identified by the eager coarse sweep.

Without eager empty block identification, if the lospace runs out of blocks, firstly you don’t know how many empty blocks the mark space has. Sweeping is a kind of wavefront that moves through the whole heap; empty blocks behind the wavefront will be identified, but those ahead of the wavefront will not. Such a lospace allocation would then have to either wait for a concurrent sweeper to advance, or perform some lazy sweeping work. The expected latency of a lospace allocation would thus be higher, without eager identification of empty blocks.

Secondly, eager sweeping might reduce allocation overhead for mutators. If allocation just has to identify holes and not compute information or decide on what to do with a block, maybe it go brr? Not sure.

lines, lines, lines

The original Immix paper also notes a relative insensitivity of the collector to line size: 64 or 256 bytes could have worked just as well. This was a somewhat surprising result to me but I think I didn’t appreciate all the roles that lines play in Immix.

Obviously line size affect the worst-case fragmentation, though this is mitigated by evacuation (which evacuates objects, not lines). This I got from the paper. In this case, smaller lines are better.

Line size affects allocation-time overhead for mutators, though which way I don’t know: scanning for holes will be easier with fewer lines in a block, but smaller lines would contain more free space and thus result in fewer collections. I can only imagine though that with smaller line sizes, average hole size would decrease and thus medium-sized allocations would be harder to service. Something of a wash, perhaps.

However if we ask ourselves the thought experiment, why not just have 16-byte lines? How crazy would that be? I think the impediment to having such a precise line size would mainly be Immix’s eager sweep, as a fine-grained traversal of the heap would process much more data and incur possibly-unacceptable pause time overheads. But, in such a design you would do away with some other downsides of coarse-grained lines: a side table of mark bytes would make the line mark table redundant, and you eliminate much possible “dark matter” hidden by internal fragmentation in lines. You’d need to defer sweeping. But then you lose eager identification of empty blocks, and perhaps also the ability to evacuate into recyclable blocks. What would such a system look like?

Readers that have gotten this far will be pleased to hear that I have made some investigations in this area. But, this post is already long, so let’s revisit this in another dispatch. Until then, happy allocations in all regions.