-
Notifications
You must be signed in to change notification settings - Fork 135
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
Unify CLI options (verbosity, version) #685
Conversation
Reviewer's Guide by SourceryThis pull request introduces a new Sequence diagram for the modified download processsequenceDiagram
participant Client
participant DownloadManager
participant HTTPClient
Client->>DownloadManager: download_file(url, show_progress)
DownloadManager->>HTTPClient: init(url, show_progress)
activate HTTPClient
loop Until EOF
HTTPClient->>HTTPClient: read(100KB blocks)
Note right of HTTPClient: Increased from 1KB to 100KB blocks
alt show_progress is true
HTTPClient->>Client: Update progress bar
end
end
HTTPClient-->>DownloadManager: Download complete
deactivate HTTPClient
DownloadManager-->>Client: File downloaded
Class diagram showing modified download componentsclassDiagram
class HTTPClient {
-response
-now_downloaded: int
-start_time: float
+init(url, headers, output_file, show_progress)
+perform_download(file, progress)
}
class DownloadManager {
+download_file(url, dest_path, headers, show_progress)
}
class PullCommand {
+pull(args)
}
PullCommand ..> DownloadManager : uses
DownloadManager ..> HTTPClient : uses
note for HTTPClient "Block size increased to 100KB"
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
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.
Hey @mkesper - I've reviewed your changes - here's some feedback:
Overall Comments:
- The --quiet flag should use action="store_true" instead of action="store" with default=False to be consistent with other boolean flags in the codebase
Here's what I looked at during the review
- 🟡 General issues: 1 issue found
- 🟢 Security: all looks good
- 🟢 Testing: all looks good
- 🟢 Complexity: all looks good
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
@@ -45,9 +45,9 @@ def pull_blob(repos, layer_digest, accept, registry_head, models, model_name, mo | |||
run_cmd(["ln", "-sf", relative_target_path, model_path]) | |||
|
|||
|
|||
def init_pull(repos, accept, registry_head, model_name, model_tag, models, model_path, model): | |||
def init_pull(repos, accept, registry_head, model_name, model_tag, models, model_path, model, show_progress): |
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.
issue (bug_risk): Function signature mismatch: pull_config_blob is called with show_progress parameter but doesn't accept it
Change looks fine to me @mkesper you just need to sign your commits with something like:
to satisfy the DCO bot. |
Lots of tests failed too, we need to get this build green somehow, at least some of the failures are flakes, not sure how many. This will all be rebuilt anyway when you the commits are signed. |
ramalama/common.py
Outdated
@@ -177,7 +177,7 @@ def download_file(url, dest_path, headers=None, show_progress=True): | |||
show_progress = False | |||
|
|||
try: | |||
http_client.init(url=url, headers=headers, output_file=dest_path, progress=show_progress) | |||
http_client.init(url=url, headers=headers, output_file=dest_path, show_progress=show_progress) |
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.
This rename needs to be made to HttpClient.init as well.
Anybody know what "podman pull" or "podman artifact pull" block size is? @baude @rhatdan We could just standardise on that, it's likely a sane value. I probably care about reliability over cpu usage. I know in practice at the TCP level of the stack a max packet size is 1500 bytes, but that's probably not so important at the http level. |
It could be the progress bar causing the CPU usage issue also, maybe we could change it so that it doesn't update every single block iteration. |
Does quiet alone lower the CPU usage significantly @mkesper ? |
@ericcurtin Best I can tell, the image copier used in podman updates once per second by default: |
If you guys could check if this makes a difference I'd appreciate it, not much CPU usage issues on my machine (and maybe the time calculation is as expensive that printing a progress bar update, I've no idea): |
@@ -26,11 +26,11 @@ def pull_config_blob(repos, accept, registry_head, manifest_data): | |||
download_file(url, config_blob_path, headers=headers, show_progress=False) |
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.
Lines 18 to 26 in 94bd95e
def pull_config_blob(repos, accept, registry_head, manifest_data): | |
cfg_hash = manifest_data["config"]["digest"] | |
config_blob_path = os.path.join(repos, "blobs", cfg_hash) | |
os.makedirs(os.path.dirname(config_blob_path), exist_ok=True) | |
url = f"{registry_head}/blobs/{cfg_hash}" | |
headers = {"Accept": accept} | |
download_file(url, config_blob_path, headers=headers, show_progress=False) |
Please add the
show_progress
parameter in this function and use the same in the download_file()
call, removing the hard coded False
.
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.
I can do this to make it more consistent although this will change behaviour to before the patch.
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.
I think False is always correct here, it's not a bulky file, the progress means very little, we only show progress for the gguf file
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.
sounds good !
Sorry, I had no time to check yet. |
To add: Interrupting the download is still perfectly possible with Ctrl-C. |
Thanks @mkesper |
ramalama/http_client.py
Outdated
@@ -60,7 +60,7 @@ def perform_download(self, file, progress): | |||
self.now_downloaded = 0 | |||
self.start_time = time.time() | |||
while True: | |||
data = self.response.read(1024) | |||
data = self.response.read(100 * 1024) |
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 patch looks good to me. How about we add a constant 100KB=100*1024 and use it here? It's faster reading for all people.
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.
I'm not sure this is the best fix, I think this works because the read is so big it delays the time that the next iteration of the loop is called. In practice you cannot depend on TCP packet sizes being larger than 1400 bytes (because of middleboxes, legacy, etc.) and this encourages fragmenting the bytes, which isn't spectacular for reliability, performance (from the transport perspective), etc.
I think it's likely the whole printing the progress bar thing is contributing to spiking the CPU usage, so if we just avoid updating that I think it could be a better fix to try (just updated this PR):
But I don't have CPU spike issues personally so cannot test the above PR.
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.
But reading python http library, they seem to default to 8kb, that seems more reasonable than 100kb:
https://github.com/python/cpython/blob/main/Lib/http/client.py
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.
We could try both PRs together
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.
I'm happy to drop #717 if it doesn't make much difference to CPU usage, although it does seem excessive to update the progress bar on each iteration.
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.
I'm not sure this is the best fix, I think this works because the read is so big it delays the time that the next iteration of the loop is called. In practice you cannot depend on TCP packet sizes being larger than 1400 bytes (because of middleboxes, legacy, etc.) and this encourages fragmenting the bytes, which isn't spectacular for reliability, performance (from the transport perspective), etc.
As far as I understand the Python http client library code, read() does not operate at TCP level but at HTTP stream level, right? That would render this concern moot.
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.
True, but it's still a consideration as HTTP is on top of TCP
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.
IMHO, Splitting in two patches make sense, one for the progress bar and another for buffer size to be discussed. The progress bar skipping should already help as @ericcurtin mentioned.
LGTM I add minor comment. |
CI/CD is complaning about:
|
The another issue in CI/CD don't see related to the patch:
|
Was this a duplicate of the other PR? |
They are related, we can take this PR in too if the tests are fixed so it's passing CI. 100kb is an excessively high block size though, we'd have to reduce that |
High block sizes can break some network connections outright... |
The add subcommand means most likely that --quiet option was not added to one of the parsers. |
Related: containers#685 Signed-off-by: Michael Kesper <[email protected]>
Related: containers#685 Signed-off-by: Michael Kesper <[email protected]>
Squash and sign your commits. |
Related: containers#685 Signed-off-by: Michael Kesper <[email protected]>
Related: containers#685 Signed-off-by: Michael Kesper <[email protected]>
Seems I'm stuck now, can't see how to fix this (seems to be connected to autocomplete):
|
Related: containers#685 Signed-off-by: Michael Kesper <[email protected]>
#835 Should fix the --quiet issue. |
@mkesper Rebase and repush and we should get this in before the release. |
Can we change --dry-run back to --dryrun please |
If there is inconsistence "--dry-run" -> "--dryrun" |
We should alias the two, since I can never remember to use --dryrun or --dry-run. Podman actually uses both spellings. podman auto update uses --dry-run and quadlet uses --dryrun. |
Yeah I actually copied quadlet at the time |
I added a clarifying comment to the second dryrun argument. I honestly thought that it was mistakenly added twice. |
Add --quiet as mutually exclusive with --debug. Maybe a --verbose switch could also be added. Related: containers#684 Signed-off-by: Michael Kesper <[email protected]>
`version` is already a subcommand. Signed-off-by: Michael Kesper <[email protected]>
Related: containers#684 Signed-off-by: Michael Kesper <[email protected]>
See containers#684 Signed-off-by: Michael Kesper <[email protected]>
Feel free to adjust block size. But 1k blocks are ridiculously low for downloading GiB of LLM data.
Related: #684
Summary by Sourcery
New Features:
--quiet
flag to suppress the progress bar during downloads.