Skip to content

add cp throttling#312

Merged
ayushkamat merged 7 commits into
mainfrom
ayush/cp-bp
Aug 24, 2023
Merged

add cp throttling#312
ayushkamat merged 7 commits into
mainfrom
ayush/cp-bp

Conversation

@ayushkamat
Copy link
Copy Markdown
Contributor

Signed-off-by: Ayush Kamat ayush@latch.bio

Signed-off-by: Ayush Kamat <ayush@latch.bio>
Signed-off-by: Ayush Kamat <ayush@latch.bio>
Signed-off-by: Ayush Kamat <ayush@latch.bio>
Signed-off-by: Ayush Kamat <ayush@latch.bio>
@ayushkamat ayushkamat marked this pull request as ready for review August 23, 2023 22:27
Copy link
Copy Markdown
Contributor

@AidanAbd AidanAbd left a comment

Choose a reason for hiding this comment

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

Do you want to throttle on complete_upload as well? Treat start_upload and complete_upload as basically the same in terms of DB load (I think this is true) and then use the same queue.

Comment on lines +7 to +15
@dataclass
class Throttle:
delay: float = 0

def get_delay(self):
return self.delay

def set_delay(self, d: float):
self.delay = d
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is there a class for a constant?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

needed for multiprocessing manager so that more than one process can interact with it

also i believe theres a built in Value in multiprocessing.SyncManager but i think this is more readable

UploadInfoBySrcType: TypeAlias = DictProxy[Path, "StartUploadReturnType"]

logging.basicConfig()
multiprocessing.get_logger().setLevel(logging.DEBUG)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

set back to default?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ah need to del this

Comment on lines +71 to +72
if config.progress != Progress.none:
click.secho(f"Uploading {src_path.name}", fg="blue")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It is strange to me that the progress bar setting is used to indicate the verbosity of our logger. I would leave this as is, or add a separate verbosity flag.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

there is a separate verbosity flag, this is based on the assumption that if a person picks --progress=none then they probably don't want verbose output either (i.e. passing --progress=none --verbose doesn't really make sense)

im not strongly opinionated here though

click.clear()
click.echo(
f"""{click.style("Upload Complete", fg="green")}
if config.progress != Progress.none:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same comment (idk if this should dictate verbosity...)

Comment thread latch_cli/services/cp/upload.py Outdated
Comment on lines +336 to +337
if throttle is not None:
time.sleep(throttle.get_delay())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

From what I can see here, a delay is set and all the start uploads wait. Then when the delay is unset, they all wake up and spam together. I think some jitter on the wakeup would help a lot, probably based on what we deem to be a reasonable amount of time for a start_upload request to complete (50ms)? Then sample from distribution around 50ms and use this to modify the delay?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this isn't what happens empirically, easier to talk about irl

Comment on lines +398 to +399
time.sleep(0.1 * random.random())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

wot

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

jitter

parts_by_src: "PartsBySrcType",
upload_info_by_src: "UploadInfoBySrcType",
):
def throttler(t: Throttle, q: "LatencyQueueType"):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This design is weird because it has a separate process that calculates based on the last posted latency.

  • We want to use some mean (probably arithmetic) of the last n posted latencies within some timeframe.
  • We can probably implement a function called get_delay or something that takes the latency queue and returns a number or None
  • If we have been blocked a lot recently (like more than 10 seconds), we should probably try the request and fail with a Load error if that does not work.
  • Then, we do not need a separate spinning process. The only concurrent object we need is a queue that evicts its oldest object when it overflows some set size.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

will talk irl

Comment on lines +351 to +352
if latency_q is not None:
latency_q.put(end - start)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Idk why this is optional but idrc

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

in the case where u upload a single file, none of the concurrency stuff is passed to the function

Signed-off-by: Ayush Kamat <ayush@latch.bio>
@ayushkamat ayushkamat merged commit d4c7c7b into main Aug 24, 2023
@ayushkamat ayushkamat deleted the ayush/cp-bp branch August 24, 2023 00:28
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.

2 participants