Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add benchmarks for ctypes function call overhead #197

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

mdboom
Copy link

@mdboom mdboom commented May 10, 2022

This additionally adds support for building C extensions as part of creating a benchmark's virtual environment, since that didn't seem to be possible prior to this change.

See faster-cpython/ideas#370 for some background discussion.

@ericsnowcurrently ericsnowcurrently self-requested a review May 16, 2022
@mdboom
Copy link
Author

@mdboom mdboom commented May 23, 2022

Wanted to add a note: This is definitely a "microbenchmark" that isn't a great example of a real-world workload.

Copy link
Member

@ericsnowcurrently ericsnowcurrently left a comment

Mostly LGTM. There are some slight changes we should consider though, particularly using runner.bench_time_func() for micro benchmarks.

benchmark_dir = os.path.dirname(bench.metafile)
if os.path.isfile(os.path.join(benchmark_dir, "setup.py")):
requirements._add(benchmark_dir)
Copy link
Member

@ericsnowcurrently ericsnowcurrently May 24, 2022

Choose a reason for hiding this comment

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

+1 to adding support for a per-benchmark setup.py. It makes sense.

If we are going to explicitly support it then it should be documented in doc/custom_benchmarks.rst.

Copy link
Member

@ericsnowcurrently ericsnowcurrently May 24, 2022

Choose a reason for hiding this comment

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

Also, as an official feature, it would probably make sense to add something like Benchmark.setup_py (set if the file exists). At the least, the code here would change:

Suggested change
benchmark_dir = os.path.dirname(bench.metafile)
if os.path.isfile(os.path.join(benchmark_dir, "setup.py")):
requirements._add(benchmark_dir)
if bench.setup_py:
requirements._add(benchmark_dir)

If fact, it would make sense to update Requirements.from_benchmarks() to use it, which would make these lines unnecessary.

Copy link
Member

@ericsnowcurrently ericsnowcurrently May 24, 2022

Choose a reason for hiding this comment

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

Taking this further, we should also consider adding some entry to the benchmark's metadata (and thus pyproject.toml) to explicitly indicate the setup.py should be used.

(If we want the presence of setup.py to imply it should be installed by default, then maybe we add an opt-out indicator instead. That can be done later if needed, but the level of effort right now is small.)

void_foo_void()
int_foo_int(1)
void_foo_int(1)
void_foo_int_int(1, 2)
void_foo_int_int_int(1, 2, 3)
void_foo_int_int_int_int(1, 2, 3, 4)
void_foo_constchar(b"bytes")
Copy link
Member

@ericsnowcurrently ericsnowcurrently May 24, 2022

Choose a reason for hiding this comment

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

The real benefit of micro-benchmarks is that it narrows down where performance regressions might be. With that in mind, would these different signatures have enough independent potential for regression that it would it make sense to have a separate benchmark for each? Would it be worth bothering even if they did?

@mdboom mdboom requested a review from ericsnowcurrently May 24, 2022
Copy link
Member

@ericsnowcurrently ericsnowcurrently left a comment

Thanks for the changes. I just have a couple more suggestions.

if bench.setup_py:
self._add(os.path.dirname(bench.metafile))
Copy link
Member

@ericsnowcurrently ericsnowcurrently May 25, 2022

Choose a reason for hiding this comment

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

Suggested change
if bench.setup_py:
self._add(os.path.dirname(bench.metafile))
if bench.setup_py:
self._add(bench.setup_py)

Copy link
Author

@mdboom mdboom May 26, 2022

Choose a reason for hiding this comment

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

I'm not sure I get this one. setup_py is not a boolean to indicate there is one, and then you pass the directory it contains to pip (not the file itself). Maybe renaming this flag to needs_build would be more accurate (since that how pip see it -- this directory has something that needs to be built, and setup.py is just an implementation detail...)

Copy link
Member

@ericsnowcurrently ericsnowcurrently May 27, 2022

Choose a reason for hiding this comment

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

Sorry for the confusion. My point is that we should record the directory name on the Benchmark object rather than using os.path.dirname() here. We could call it something like setup_py_dir if you prefer.

@@ -333,6 +333,7 @@ tool.extra_opts [str] X
tool.inherits file
tool.runscript file X
tool.datadir file X
tool.setup_py bool
Copy link
Member

@ericsnowcurrently ericsnowcurrently May 25, 2022

Choose a reason for hiding this comment

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

setup_py might be too ambiguous. Consider something like:

Suggested change
tool.setup_py bool
tool.install_setup bool

I can also imagine someone wanting to use a different filename that setup.py (e.g. if they have multiple different setup scripts). So:

Suggested change
tool.setup_py bool
tool.install_setup bool
tool.setupscript str

The default for setupscript would be 'setup.py'.

Copy link
Member

@ericsnowcurrently ericsnowcurrently May 25, 2022

Choose a reason for hiding this comment

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

If adding "setupscript" seems premature, we can skip it. (I'm just trying to keep custom benchmarks in mind. Any friction in writing a benchmark can mean the difference between someone doing it or not.)

Copy link
Author

@mdboom mdboom May 26, 2022

Choose a reason for hiding this comment

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

Yeah -- in addition, I don't think pip makes it possible. You don't tell it "here's a setup.py", you tell it "here's a source directory to install, and it knows that setup.py is one of the ways to build it..."

@property
def setup_py(self):
return self._get_metadata_value('setup_py', False)
Copy link
Member

@ericsnowcurrently ericsnowcurrently May 25, 2022

Choose a reason for hiding this comment

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

Let's return the filename (and check if the file exists) here:

Suggested change
@property
def setup_py(self):
return self._get_metadata_value('setup_py', False)
@property
def setup_py(self):
try:
return self._setup_py
except AttributeError:
self._setup_py = None
if self._get_metadata_value('install_setup', True):
filename = self._get_metadata_value('setupscript', 'setup.py')
rootdir = os.path.dirname(self.metafile)
#rootdir = self._get_rootdir()
filename = os.path.join(rootdir, filename)
if os.path.isdir(filename):
filename = os.path.join(filename, 'setup.py')
if os.path.exists(filename):
self._setup_py = filename
return self._setup_py

Also, I'm thinking it might be best for the default "install_setup" to be True. So, by default, the setup script is installed if it is there. That seems like the more likely user expectation.

Copy link
Author

@mdboom mdboom May 26, 2022

Choose a reason for hiding this comment

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

See above for why the filename may not be necessary.

But no harm in changing the default to True (I think).

@mdboom mdboom requested a review from ericsnowcurrently May 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants