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

make TaskWarriorShellout() do task --version only once #159

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

smemsh
Copy link

@smemsh smemsh commented May 16, 2022

TaskWarriorShellout() is doing at least 3 task --version to get the instance (before we can run any methods), and then is doing these calls again for each filter_task(), task_add(), or sync() method call.

This patch moves task --version execution to a cached class attribute so it can be done one time only during the lifetime.

Note that we cannot move this to instance constructor because it's run during module import at toplevel (via .can_use() call at bottom of taskw/warrior.py)

Fixes #158

Thanks also to @ryneeverett for suggesting use a cached class attribute in get_version()

@smemsh smemsh changed the title TaskWarriorShellout() is doing at least 3 task --version to get the instance (before we can run any methods), and then is doing these calls again for each filter_task(), task_add(), or sync() method call. make TaskWarriorShellout() do task --version only once May 16, 2022
@ryneeverett
Copy link
Contributor

Don't we still need to wrap the result in LooseVersion?

Wouldn't it be more readable to just cache the get_version method? I don't know if there are better options on our supported python versions but it would be simple enough to assign to cls.taskwarrior_version and check if hasattr(cls, 'taskwarrior_version') at the beginning of the method.

@smemsh
Copy link
Author

smemsh commented May 16, 2022

Don't we still need to wrap the result in LooseVersion?

Yes, I had missed that when copying the block, thanks.

Wouldn't it be more readable to just cache [the version value in] the get_version method?

Yes, agree that it's simpler, not sure why I didn't use that approach as it's the obvious way. I'll try it like that instead, thanks!

@smemsh smemsh force-pushed the task-version-once branch 2 times, most recently from 9b994af to 5ac48dd Compare May 16, 2022 05:40
@smemsh
Copy link
Author

smemsh commented May 16, 2022

@ryneeverett seems to work. Hopefully it will be merged, perhaps someday ;-)

A TaskWarriorShellout instance calls .get_version() already thrice: once
when determining if we .can_use() TaskWarriorShellout rather than
TaskWarriorDirect, and then twice in the instance constructor itself.
Therefore creation of the instance already calls it thrice.  Each of
these ends up executing "task --version" with execve(2) via
subprocess.Popen().

Use of the methods .sync() or .filter_tasks() would execute this once
again, while using .task_add() would do it twice.  We therefore end up
executing "task --version" four times for a single filter_tasks() and
five times for a task_add().

Scripts which are doing multiple filters are constantly adding the
overhead of these fork/execve just to obtain the version.  My own
personal taskgrep wrapper is making several calls with different
filters, and strace is showing 18 different "task --version" calls,
which on my modern-ish laptop adds about a tenth of a second to my
taskgreps:

     $ TIMEFORMAT='time: %3Rs'; time \
       for ((i = 0; i < 18; i++))
       do task --version &>/dev/null; done
     time: 0.089s

It's not huge, but these unncessary repeated "task --version" calls
really can just be done once and the value cached as a class attribute

Note that we cannot do this in the instance constructor, because
can_use() is a class method called at module import time, before any
instance will have been created, so we need get_version() to continue to
be a class method.

Thanks also to @ryneeverett for suggesting to use a simple cached class
attribute in get_version() rather than the first implementation which
moved these statements into the class definition.
@smemsh smemsh force-pushed the task-version-once branch from 5ac48dd to 5515645 Compare June 18, 2022 02:28
bergercookie added a commit to bergercookie/taskw-ng that referenced this pull request Jan 23, 2024
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.

unnecessary "task --version" 3x to start, 1x for every filter and 2x for every add
2 participants