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 — gh-126868: Add freelist for compact int objects by eendebakpt · Pull Request #126865 · python/cpython

Conversation

@eendebakpt

@eendebakpt eendebakpt commented Nov 15, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

We can add freelists for the int object to improve performance. Using the new methods from #121934 the amount of code needed for adding a freelist is quite small. We only implement the freelist for compact ints (e.g. a single digit). For multi-digit int objects adding freelists is more complex (we need a size-based freelist) and the gains are smaller (for very large int objects the allocation is not a significant part of the computation time)

Notes:

  • The freelist size was chosen to be 100 (equal to the freelist size of float), but perhaps this can be tuned better
  • The long_dealloc and _PyLong_ExactDealloc are almost identical, we could keep just long_dealloc at the cost of a tiny bit of performance.

Some references to discussions on freelists

  • gh-100240: Use a consistent implementation for freelists #121934
  • Use a principled, and consistent, implementation of freelists. faster-cpython/ideas#132
  • Use freelist for range object, iterator objects and other often used objects #126703
  • GH-100240: Generic freelist, applied to ints #101453

The freelist improves performance of int operations in microbenchmarks:

bench_long: Mean +- std dev: [main_long] 106 ns +- 5 ns -> [pr_long1c] 99.8 ns +- 4.4 ns: 1.07x faster
bench_alloc: Mean +- std dev: [main_long] 210 us +- 6 us -> [pr_long1c] 177 us +- 10 us: 1.19x faster

Benchmark hidden because not significant (1): bench_collatz

Geometric mean: 1.08x faster
Benchmark script
# Quick benchmark for cpython long objects

import pyperf


def collatz(a):
    while a > 1:
        if a % 2 == 0:
            a = a // 2
        else:
            a = 3 * a + 1


def bench_collatz(loops):
    range_it = range(loops)
    t0 = pyperf.perf_counter()
    for ii in range_it:
        collatz(ii)
    return pyperf.perf_counter() - t0


def bench_long(loops):
    range_it = range(loops)
    t0 = pyperf.perf_counter()
    x = 10
    for ii in range_it:
        x = x * x
        y = x // 2
        x = y + ii + x
        if x > 10**10:
            x = x % 1000
    return pyperf.perf_counter() - t0


def bench_alloc(loops):
    range_it = range(loops)
    t0 = pyperf.perf_counter()
    for ii in range_it:
        for kk in range(20_000):
            del kk
    return pyperf.perf_counter() - t0


# %timeit bench_long(1000)

if __name__ == "__main__":
    runner = pyperf.Runner()
    runner.bench_time_func("bench_collatz", bench_collatz)
    runner.bench_time_func("bench_long", bench_long)
    runner.bench_time_func("bench_alloc", bench_alloc)

On the pyperformance test suite (actually, a subset of the suite, not all benchmarks run on my system) shows the percentage of successfull freelist allocations increases significantly

Main:

Allocations from freelist 	2,004,971,371 	39.8%
Frees to freelist 	2,005,350,418 	
Allocations 	3,034,877,938 	60.2%
Allocations to 512 bytes 	3,008,791,812 	59.7%
Allocations to 4 kbytes 	18,648,072 	0.4%
Allocations over 4 kbytes 	7,438,054 	0.1%
Frees 	3,142,033,922

PR

Allocations from freelist 	3,058,347,887 	58.6%
Frees to freelist 	3,058,576,117 	
Allocations 	2,159,771,546 	41.4%
Allocations to 512 bytes 	2,133,373,693 	40.9%
Allocations to 4 kbytes 	18,802,328 	0.4%
Allocations over 4 kbytes 	7,595,525 	0.1%
Frees 	2,267,538,686
  • Issue: Add freelist for compact int objects #126868

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@eendebakpt
Add freelist of compact int objects
0713034
@eendebakpt
eendebakpt requested review from ericsnowcurrently and markshannon as code owners November 15, 2024 11:20
@bedevere-app bedevere-app Bot added the awaiting review label Nov 15, 2024
eendebakpt added 2 commits November 15, 2024 12:32
@eendebakpt
fix build
be58ade
@eendebakpt
cleanup freelist at exit
3f50b54
@eendebakpt eendebakpt changed the title Draft: Add freelist of compact int objects Draft: gh-126868: Add freelist for compact int objects Nov 15, 2024
@eendebakpt
eendebakpt marked this pull request as draft November 15, 2024 12:50
@bedevere-app bedevere-app Bot removed the awaiting review label Nov 15, 2024
@bedevere-app bedevere-app Bot mentioned this pull request Nov 15, 2024
Add freelist for compact int objects #126868
Closed
@mdboom

mdboom commented Nov 15, 2024

Copy link
Copy Markdown
Contributor

I'm running this PR over pyperformance on our benchmarking hardware. It will take ~3 hours.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mdboom

mdboom commented Nov 15, 2024

Copy link
Copy Markdown
Contributor

I'm running this PR over pyperformance on our benchmarking hardware. It will take ~3 hours.

Actually, scratch that -- I'll wait until the tests are passing here. That's required for PGO builds.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

eendebakpt and others added 7 commits November 16, 2024 19:59
@eendebakpt
fix memory leak; align with float implementation
fa97302
@eendebakpt
remove stale comment
d72486f
@eendebakpt
remove unused function
e07c218
@eendebakpt
avoid some problematic decrefs
328e0c1
@eendebakpt
jit build
e1dc2b3
@blurb-it
📜🤖 Added by blurb_it.
9df776b
@eendebakpt
Merge branch 'main' into int_freelist
6b73046
@eendebakpt

eendebakpt commented Nov 16, 2024

Copy link
Copy Markdown
Contributor Author

Tests are passing now, but I disabled returning objects to the freelist at a couple of places. Changing PyObject_Free to _PyLong_ExactDealloc on the lines of code marked with "needs to be converted to freelist" introduces refleaks. It seems related to #125323. @fidgetSpinner Do you perhaps have an idea what is going on?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@markshannon

markshannon commented Nov 18, 2024

Copy link
Copy Markdown
Member

What happens exactly when you change these lines:

PyStackRef_CLOSE_SPECIALIZED(left, (destructor)PyObject_Free); // needs to be converted to freelist

to

PyStackRef_CLOSE_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);

?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@eendebakpt

eendebakpt commented Nov 18, 2024

Copy link
Copy Markdown
Contributor Author

@markshannon When I change the lines several tests related to refleaks in the CI are failing. For example test_no_memleak, which can be reproduced from the command line with:

python -Xshowrefcount -c  "[x+x*x for x in range(1000)]"

The output should be [0 refs, 0 blocks], but instead I get [982 refs, 0 blocks] (exact numbers depending on which lines I change and the exact code executed).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Fidget-Spinner
Fidget-Spinner reviewed Nov 20, 2024
View reviewed changes

@Fidget-Spinner Fidget-Spinner left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

The "leaks" are due to the freelist itself. They are a sign the freelist is working :).
Can you please convert all to _PyLong_ExactDealloc and apply the suggestion below, and tell me how many allocations this removes?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Objects/longobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/longobject.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@Fidget-Spinner
Apply review suggestions
db8247e
@Fidget-Spinner

Fidget-Spinner commented Nov 20, 2024

Copy link
Copy Markdown
Member

@eendebakpt sorry I pushed to your branch as I'm really eager to get benchmark results on this :).

eendebakpt reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Fidget-Spinner
Fixup
d1e4aa2
@Fidget-Spinner

Fidget-Spinner commented Nov 20, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

On my machine using the benchmark script provided above (release build, no PGO, no LTO):

bench_collatz: Mean +- std dev: [without_freelist] 9.41 us +- 0.08 us -> [with_freelist] 9.22 us +- 0.08 us: 1.02x faster
bench_long: Mean +- std dev: [without_freelist] 187 ns +- 1 ns -> [with_freelist] 164 ns +- 2 ns: 1.14x faster
bench_alloc: Mean +- std dev: [without_freelist] 411 us +- 4 us -> [with_freelist] 333 us +- 2 us: 1.24x faster

Geometric mean: 1.13x faster
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

eendebakpt
eendebakpt commented Nov 20, 2024
View reviewed changes
Comment thread Objects/longobject.c Outdated
}

if (PyLong_CheckExact(self)) {
if (_PyLong_IsCompact((PyLongObject *)self)) {

@eendebakpt eendebakpt Nov 20, 2024

Copy link
Copy Markdown
Contributor Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

@Fidget-Spinner The _PyLong_IsCompact check has already been done in this method, can we move this into the if (pylong && _PyLong_IsCompact(pylong)) part?

Also, can we remove the pylong && part? I think pylong can never be NULL. (PyLong_CheckExact assumes the pointer is not NULL I think)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@Fidget-Spinner Fidget-Spinner Nov 21, 2024

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Ok that sounds good

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@Fidget-Spinner

Fidget-Spinner commented Nov 21, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Results:

  • 1.1% speedup on macOS: https://github.com/faster-cpython/benchmarking-public/blob/main/results/bm-20241121-3.14.0a1%2B-d1e4aa2/bm-20241121-darwin-arm64-eendebakpt-int_freelist-3.14.0a1%2B-d1e4aa2-vs-base.svg
  • 0.3% speedup on x86-Linux: https://github.com/faster-cpython/benchmarking-public/blob/main/results/bm-20241121-3.14.0a1%2B-d1e4aa2/bm-20241121-linux-x86_64-eendebakpt-int_freelist-3.14.0a1%2B-d1e4aa2-vs-base.svg
  • No speedup on Windows

This is a great result! Congrats and great work @eendebakpt !

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

picnixz
picnixz reviewed Nov 21, 2024
View reviewed changes

@picnixz picnixz left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Out of curiosity, are compact integers allowed to be signed or not? (you mentioned that we only focus on single digit numbers but the C API considers compact objects as being an implementation detail IIRC). If not, how hard would it be to make them support free lists? (I don't have much knowledge in free lists; for instance it's a mystery to me for how the free list grows)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Python/bytecodes.c Outdated
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_range.h" // _PyRangeIterObject
#include "pycore_long.h" // void _PyLong_ExactDealloc(PyLongObject *op);

@picnixz picnixz Nov 21, 2024

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Can we align the // (on mobile it seems 1 char off)?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Objects/longobject.c Outdated
0, /* tp_alloc */
long_new, /* tp_new */
PyObject_Free, /* tp_free */
(freefunc)PyObject_Free, /* tp_free */

@picnixz picnixz Nov 21, 2024

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Can we align the .tp_free comment? (maybe tabs and spaces are mixed, hence that's why I see them unaligned on monile). Also, is the cast necessary to avoid UBSan failures? If not, you can just use .tp_free = ... to emphasize the semantic

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Objects/longobject.c Outdated
Comment on lines +3641 to +3643
* we accidentally decref small Ints out of existence. Instead,
* since small Ints are immortal, re-set the reference count.
*/

@picnixz picnixz Nov 21, 2024

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Suggested change
* we accidentally decref small Ints out of existence. Instead,
* since small Ints are immortal, re-set the reference count.
*/
* we accidentally decref small Ints out of existence. Instead,
* since small Ints are immortal, re-set the reference count.
*/

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Objects/longobject.c Outdated
#include "pycore_bitutils.h" // _Py_popcount32()
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_call.h" // _PyObject_MakeTpCall
#include "pycore_freelist.h" // _Py_FREELIST_FREE(), _Py_FREELIST_POP()

@picnixz picnixz Nov 21, 2024

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Comment alignment.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Include/internal/pycore_long.h

/* other API */

PyAPI_FUNC(void) _PyLong_ExactDealloc(PyObject *self);

@picnixz picnixz Nov 21, 2024

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Do you need it to be exported like that or could you live with a simple extern? If not, can you explain which file needs this export?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@Fidget-Spinner Fidget-Spinner Nov 21, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

It's needed by the JIT on Windows, as it's used in bytecodes.c. This is a pretty common pattern in the internal C API unfortunately

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

picnixz reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@picnixz picnixz Nov 21, 2024

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

For semantic purposes, would it be better to have a macro named differently? (it would be a simple alias but it could help semantics and reviewers)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Objects/longobject.c Outdated
{
assert(PyLong_CheckExact(op));
_Py_DECREF_SPECIALIZED((PyObject *)op, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED((PyObject *)op, (destructor) _PyLong_ExactDealloc);

@picnixz picnixz Nov 21, 2024

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Suggested change
_Py_DECREF_SPECIALIZED((PyObject *)op, (destructor) _PyLong_ExactDealloc);
_Py_DECREF_SPECIALIZED((PyObject *)op, (destructor)_PyLong_ExactDealloc);

I'm also not sure whether you need the cast. If you need the cast, I'd suggest changing the signature of the drstructor itself.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-app bedevere-app Bot added the awaiting changes label Dec 4, 2024
@bedevere-app

bedevere-app Bot commented Dec 4, 2024

Copy link
Copy Markdown

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

eendebakpt added 3 commits December 7, 2024 23:11
@eendebakpt
review comment
efde111
@eendebakpt
Merge branch 'main' into int_freelist
928e912
@eendebakpt
regenerate
437c24c
@eendebakpt

eendebakpt commented Dec 7, 2024

Copy link
Copy Markdown
Contributor Author

The generated files need to be regenerated, and I'd like to rerun the benchmarks to confirm the additional small int checks don't impact performance too much.

I assume you mean the small int checks in _PyLong_ExactDealloc? In current main these checks are not present (PyObject_Free is called directly), so we could argue they are not needed in _PyLong_ExactDealloc either. On the other hand, if I understand things well to be correct they should be added.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

eendebakpt
eendebakpt commented Dec 7, 2024
View reviewed changes
Comment thread Misc/NEWS.d/next/Core_and_Builtins/2024-11-16-22-37-46.gh-issue-126868.yOoHSY.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

@eendebakpt
Update Misc/NEWS.d/next/Core_and_Builtins/2024-11-16-22-37-46.gh-issu…
b034948
…e-126868.yOoHSY.rst
@eendebakpt

eendebakpt commented Dec 9, 2024

Copy link
Copy Markdown
Contributor Author

I have made the requested changes; please review again

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot added awaiting change review and removed awaiting changes labels Dec 9, 2024
@bedevere-app

bedevere-app Bot commented Dec 9, 2024

Copy link
Copy Markdown

Thanks for making the requested changes!

@markshannon: please review the changes made to this pull request.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app
bedevere-app Bot requested a review from markshannon December 9, 2024 10:42
@markshannon

markshannon commented Dec 12, 2024

Copy link
Copy Markdown
Member

0.6% speedup

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

markshannon
markshannon approved these changes Dec 12, 2024
View reviewed changes

@markshannon markshannon left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Thanks for doing this. The code looks good now.

The speedup may not be as large as initially claimed due to addition checks for small integers, but it is a real speedup and should be further improved by #127620

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting change review labels Dec 12, 2024
@markshannon

markshannon commented Dec 12, 2024

Copy link
Copy Markdown
Member

It seems likely the thread sanitizer failure is not caused by this PR, but this PR does expose it.
Hopefully it will be fixed soon, but we'll need to wait a bit before merging this PR.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@colesbury

colesbury commented Dec 12, 2024

Copy link
Copy Markdown
Contributor

TSan failure is addressed in #127880.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@colesbury colesbury mentioned this pull request Dec 12, 2024
gh-127879: Fix data race in _PyFreeList_Push #127880
Merged
@colesbury

colesbury commented Dec 12, 2024

Copy link
Copy Markdown
Contributor

The TSan failure is fixed in main now, if you want to merge main back into the PR.

eendebakpt reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

eendebakpt added 2 commits December 12, 2024 21:49
@eendebakpt
Merge branch 'main' into int_freelist
19f64f6
@eendebakpt
Merge branch 'main' into int_freelist
14681c1
@markshannon
markshannon merged commit 5fc6bb2 into python:main Dec 13, 2024
@bedevere-app bedevere-app Bot removed the awaiting merge label Dec 13, 2024
@markshannon markshannon mentioned this pull request Dec 13, 2024
gh-127119: Faster check for small ints in long_dealloc #127620
Merged
@bedevere-bot

bedevere-bot commented Dec 13, 2024

Copy link
Copy Markdown

⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️

Hi! The buildbot iOS ARM64 Simulator 3.x has failed when building commit 5fc6bb2.

What do you need to do:

  1. Don't panic.
  2. Check the buildbot page in the devguide if you don't know what the buildbots are or how they work.
  3. Go to the page of the buildbot that failed (https://buildbot.python.org/#/builders/1380/builds/2109) and take a look at the build logs.
  4. Check if the failure is related to this commit (5fc6bb2) or if it is a false positive.
  5. If the failure is related to this commit, please, reflect that on the issue and make a new Pull Request with a fix.

You can take a look at the buildbot page here:

https://buildbot.python.org/#/builders/1380/builds/2109

Summary of the results of the build (if available):

==

Click to see traceback logs
Traceback (most recent call last):
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

srinivasreddy pushed a commit to srinivasreddy/cpython that referenced this pull request Jan 8, 2025
@eendebakpt @srinivasreddy
pythongh-126868: Add freelist for compact int objects (pythonGH-126865)
abf3b83
@dg-pb dg-pb mentioned this pull request Apr 24, 2025
Increase _PY_NSMALLPOSINTS size faster-cpython/ideas#725
Closed
@KRRT7 KRRT7 mentioned this pull request May 28, 2026
Widen specialized int fast paths to full int64 range #150424
Open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@picnixz picnixz picnixz left review comments
@Fidget-Spinner Fidget-Spinner Fidget-Spinner left review comments
@markshannon markshannon markshannon approved these changes
@ericsnowcurrently ericsnowcurrently Awaiting requested review from ericsnowcurrently ericsnowcurrently is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

7 participants

@eendebakpt @mdboom @markshannon @Fidget-Spinner @colesbury @bedevere-bot @picnixz
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — 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.