Skip to content

bpo-31659: ssl: Don't use textwrap.fill() to format PEM cert#3849

Merged
methane merged 1 commit into
python:masterfrom
methane:ssl-no-textwrap
Oct 2, 2017
Merged

bpo-31659: ssl: Don't use textwrap.fill() to format PEM cert#3849
methane merged 1 commit into
python:masterfrom
methane:ssl-no-textwrap

Conversation

@methane

@methane methane commented Oct 2, 2017

Copy link
Copy Markdown
Member

DER_cert_to_PEM_cert() used textwrap.fill() to format PEM.
But it's library to wrap lines on word boundary, while PEM is
base64 encoded string.
Additionally, importing textwrap is little slow.

https://bugs.python.org/issue31659

DER_cert_to_PEM_cert() used textwrap.fill() to format PEM.
But it's library to wrap lines on word boundary.
And importing textwrap is little slow.
@methane methane changed the title bpo-31659: Use simple slicing to format PEM cert. bpo-31659: ssl: Don't use textwrap.fill() to format PEM cert Oct 2, 2017
@methane methane merged commit b75a228 into python:master Oct 2, 2017
@methane methane deleted the ssl-no-textwrap branch October 2, 2017 07:33

@tiran tiran left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I like the general idea but not the execution.

Comment thread Lib/ssl.py
textwrap.fill(f, 64) + '\n' +
PEM_FOOTER + '\n')
ss = [PEM_HEADER]
ss += [f[i:i+64] for i in range(0, len(f), 64)]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

+1 for the idea

Please don't use += and use a self-explaining local variable name:

lines = [PEM_HEADER]
lines.extend(f[i:i+64] for i in range(0, len(f), 64))
lines.extend([PEM_FOOTER, ''])
return '\n'.join(lines)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My first impulse was to add a similar comment. But actually this doesn't matter. All lists here are small I hope, so copying lists doesn't add much overhead. On other hand, the variant with extend() and generator expression add their own overheads.

  1. Generator expression is slightly slower than a list comprehension.
  2. list.extend() is special cased for tuples and list. It is slower with general iterators.
  3. Calling a method is slower than executing an operator.
  4. I didn't checked, but maybe PEM_FOOTER + '\n' is faster than [PEM_FOOTER, ''].

Hence the current code looks good enough to me. It is enough fast and looks enough Pythonic. If there are opportunities to enhance it, it is not worth the spent time.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm sorry about variable name. I didn't care about name for very short scope variables.

In case of performance, as serhiy said, cert size won't be arbitrary large.
And old code used temporal string for body part. This commit didn't make anythong worse.

$ ./python -m perf timeit -s "import textwrap; s='a'*1000" -- 'textwrap.fill(s, 60)'
.....................
Mean +- std dev: 192 us +- 10 us

$ ./python -m perf timeit -s "import textwrap; s='a'*1000" -- 'x=[]; x+=[s[i:i+60] for i in range(0,len(s),60)]; "\n".join(x)'
.....................
Mean +- std dev: 4.66 us +- 0.06 us

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants