-
Notifications
You must be signed in to change notification settings - Fork 2
gardenlinux: PoC: vCPU throttling/auto-converge #13
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
gardenlinux: PoC: vCPU throttling/auto-converge #13
Conversation
86db5eb to
f2978b1
Compare
f2978b1 to
d7003ea
Compare
|
I just stress tested this and ran into an issue after 174 successful migrations. I'm now in a state where the receiver side is on 100% cpu whereas the sender side is idling, and the migration does not continue |
5554499 to
36985cb
Compare
This comment was marked as outdated.
This comment was marked as outdated.
36985cb to
7b8e12a
Compare
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
b291803 to
464bc74
Compare
464bc74 to
fc98bdb
Compare
vmm/src/vm.rs
Outdated
| VmState::Created | ||
| }; | ||
|
|
||
| let vcpu_throttle_thread_handle = ThrottleThreadHandle::new_from_cpu_manager(&cpu_manager); |
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.
| let vcpu_throttle_thread_handle = ThrottleThreadHandle::new_from_cpu_manager(&cpu_manager); | |
| let vcpu_throttler = ThrottleThreadHandle::new_from_cpu_manager(&cpu_manager); |
502eaff to
f4bd5b4
Compare
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.
Thank you for the changes and especially for the awesome documentation that made it relatively easy to follow what the code in this commit does!
I have added a few comments below which you can either decide to consider already now or wait until you start preparing this feature for production. See also the list on this issue.
Moreover once we get to making this production ready then if we decide to instead spawn the throttling thread per (full) migration attempt (potentially with seccomp setup) instead, then as we already mentioned in direct messages it should be possible to simplify the code a bit by only having a single loop in the throttling thread.
| fn test_vcpu_throttling_thread_lifecycle() { | ||
| for _ in 0..5 { | ||
| // State transitions: Waiting -> Exit | ||
| { | ||
| let mut handler = ThrottleThreadHandle::new(Box::new(|| {}), Box::new(|| {})); | ||
|
|
||
| // The test is successful if it does not get stuck. | ||
| handler.shutdown(); | ||
| } | ||
|
|
||
| // Dummy CpuManager | ||
| let cpus_throttled = Arc::new(AtomicBool::new(false)); | ||
| let callback_pause_vcpus = { | ||
| let cpus_running = cpus_throttled.clone(); | ||
| Box::new(move || { | ||
| let old = cpus_running.swap(true, Ordering::SeqCst); | ||
| assert!(!old); | ||
| }) | ||
| }; | ||
| let callback_resume_vcpus = { | ||
| let cpus_running = cpus_throttled.clone(); | ||
| Box::new(move || { | ||
| let old = cpus_running.swap(false, Ordering::SeqCst); | ||
| assert!(old); | ||
| }) | ||
| }; | ||
|
|
||
| // State transitions: Waiting -> Throttle -> Waiting -> Throttle -> Exit | ||
| { | ||
| let mut handler = | ||
| ThrottleThreadHandle::new(callback_pause_vcpus, callback_resume_vcpus); | ||
| handler.set_throttle_percent(5); | ||
| sleep(Duration::from_millis(ThrottleWorker::TIMESLICE_MS)); | ||
| handler.set_throttle_percent(10); | ||
| sleep(Duration::from_millis(ThrottleWorker::TIMESLICE_MS)); | ||
|
|
||
| // Assume we aborted vCPU throttling (or the live-migration at all). | ||
| handler.set_throttle_percent(0 /* reset to waiting */); | ||
| handler.set_throttle_percent(5); | ||
| sleep(Duration::from_millis(ThrottleWorker::TIMESLICE_MS)); | ||
| handler.set_throttle_percent(10); | ||
| sleep(Duration::from_millis(ThrottleWorker::TIMESLICE_MS)); | ||
|
|
||
| // The test is successful if we don't have a panic here due to a | ||
| // closed channel. | ||
| for _ in 0..10 { | ||
| handler.shutdown(); | ||
| sleep(Duration::from_millis(1)); | ||
| } | ||
|
|
||
| // The test is successful if it does not get stuck. | ||
| drop(handler); | ||
| } | ||
| } | ||
| } |
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 will suffice for the PoC, but when you start preparing this for production then it would be cool if you would instead insert callbacks that record certain events (e.g. the timestamps when they get called, how many times they are called, etc) and check that this (roughly) corresponds to what one would expect.
| /// function must not perform any artificial delay itself. | ||
| /// - `callback_resume_vcpus`: Function putting all vCPUs back into running | ||
| /// state. The function must not perform any artificial delay itself. | ||
| fn new( |
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.
Nit:
| fn new( | |
| fn spawn( |
| /// | ||
| /// # Parameters | ||
| /// - `cpu_manager`: CPU manager to pause and resume vCPUs | ||
| pub fn new_from_cpu_manager(cpu_manager: &Arc<Mutex<CpuManager>>) -> Self { |
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.
Nit:
| pub fn new_from_cpu_manager(cpu_manager: &Arc<Mutex<CpuManager>>) -> Self { | |
| pub fn spawn_with_cpu_manager(cpu_manager: Arc<Mutex<CpuManager>>) -> Self { |
f4bd5b4 to
55a1549
Compare
c2bc313 to
ff9d41e
Compare
3dd8f15 to
0b82a8f
Compare
auto-converge (vCPU throttling) is a technique combined with precopy live-migration flows to migrate VMs with a high dirty rate (high working set with many writes). It is an alternative to postcopy migration, which is not yet implemented in Cloud Hypervisor. By throttling the vCPUs incrementally, the dirty rate drops and the VM migrates (converges) eventually. More specifically, the reduced dirty rate ensures that the configured downtime can be reached. The implementation is inspired by QEMU, but adapted to Cloud Hypervisor. Various discussions, intermediate steps, and experiments lead to this final result. vCPU throttling was implemented with a dedicated thread and a manager for that thread. This thread utilizes the CpuManager's pause() and resume() in conjunction with (interruptible) sleeps to apply the current throttling percentage onto the vCPUs, thus the VM. The implementation is designed to not block or delay normal operation any longer than necessary. The proposed design relies on the recent improvements and fixes for CpuManager's pause() and resume(). For correctness, on each pause/resume cycle, the time for these actions is measured. This way, a dynamic timeslice can be used, guaranteeing the VM is indeed throttled at the indented percentage. Although not supported yet by Cloud Hypervisor, this thread will support throttling cancellation when live-migrations are cancelled. This was intensively tested in an automated setup with thousands of live-migrations with VMs under load. - auto-converging starts always after two memory delta transfer iterations - every two iterations, it is increased (step size is 10%) - maximum throttling is 99% - the VM will get slower. At 99% throttling, it will be unsurprisingly barely usable. This is something users have to accept if they want to migrate their VMs running heavy workloads. Signed-off-by: Philipp Schuster <[email protected]> Reviewed-by: Stefan Kober <[email protected]> Reviewed-by: Oliver Anderson <[email protected]> Reviewed-by: Thomas Prescher <[email protected]> On-behalf-of: SAP [email protected]
0b82a8f to
1b1cabb
Compare
5c96d5f
into
cyberus-technology:gardenlinux
This adds the PoC for vCPU-throttling/auto-converge for pre-copy migration.
vm-migration: add vCPU throttling (auto-converge) for pre-copy
About
auto-converge (vCPU throttling) is a crucial technique to migrate
VMs with a high dirty rate (high working set with intense usage).
It is an alternative to postcopy migration, which is not yet
implemented in Cloud Hypervisor.
Implementation
vCPU throttling was implemented with a different thread and a
manager for that thread. It is possible to abort vCPU throttling
in case one aborts a live-migration, for example.
The rather complex thread state management is covered in unit
tests ensuring liveliness throughout all possible scenarios.
The throttling itself is implemented by utilizing the CpuManager's
pause() and resume() functions.
Effective Behaviour
iterations (not configurable yet)
the vCPU is paused for 99ms and runs for 1ms, and again.
Signed-off-by: Philipp Schuster [email protected]
On-behalf-of: SAP [email protected]
Hints for Reviewers
Steps to Undraft