Skip to content

Commit 18d8497

Browse files
committed
Merge remote-tracking branch 'origin/pr/730'
* origin/pr/730: Wait for memory by transfer speed
2 parents 2aa0747 + b52eccd commit 18d8497

File tree

2 files changed

+66
-13
lines changed

2 files changed

+66
-13
lines changed

qubes/qmemman/systemstate.py

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#: number of free memory bytes expected to get during CHECK_PERIOD_S
4646
#: seconds
4747
CHECK_DELTA = CHECK_PERIOD_S * CHECK_MB_S * 1024 * 1024
48+
LAST_SECOND = max(1, int(1 / BALLOON_DELAY))
4849

4950

5051
class SystemState:
@@ -283,42 +284,93 @@ def do_balloon_dom(self, dom_memset: dict) -> bool:
283284
for _, dom in dom_dict.items():
284285
dom.no_progress = False
285286

287+
mem_set_threshold = 1.1
286288
succeeded = []
287289
memset_reqs = {}
288290
for domid, memset in dom_memset.items():
291+
dom = dom_dict[domid]
289292
if memset == 0:
290-
# Domain hasn't meminfo back to the server, it is still at the
291-
# initial amount. pref_mem can't be calculated yet.
292-
if dom_dict[domid].mem_used is None:
293+
# Domain hasn't sent meminfo back to the server, it is still at
294+
# the initial amount. pref_mem can't be calculated yet.
295+
if dom.mem_used is None:
296+
self.log.info(
297+
"mem requested for dom '%s' is 0 but meminfo was not "
298+
+ "reported back, skipping ballooning",
299+
domid,
300+
)
293301
succeeded.append(domid)
294302
continue
295-
mem_pref = qubes.qmemman.algo.pref_mem(dom_dict[domid])
303+
mem_pref = qubes.qmemman.algo.pref_mem(dom)
296304
memset_reqs[domid] = mem_pref
297-
self.log.debug(
298-
"mem for dom '%s' is 0, using its pref '%s'",
305+
diff = round(getattr(dom, "mem_actual", 0) / mem_pref, 2)
306+
self.log.info(
307+
"mem requested for dom '%s' is 0, using its pref '%s' while"
308+
+ " actual mem is '%s' (%sx)",
299309
domid,
300310
mem_pref,
311+
dom.mem_actual,
312+
diff,
301313
)
302314
else:
303315
memset_reqs[domid] = memset
316+
diff = round(dom.mem_actual / memset, 2)
317+
self.log.info(
318+
"mem requested for dom '%s' is '%s' while actual mem is "
319+
+ "'%s' (%sx)",
320+
domid,
321+
memset,
322+
dom.mem_actual,
323+
diff,
324+
)
304325

326+
actual_mem_ring: dict[str, list[int]] = {}
305327
while True:
306-
self.log.debug("niter={:d}".format(niter))
307328
self.refresh_mem_actual(domid_list)
308329
for domid, dom in dom_dict.items():
330+
if domid in succeeded:
331+
continue
309332
assert isinstance(dom.mem_actual, int)
310-
if (
311-
domid not in succeeded
312-
and dom.mem_actual / memset_reqs[domid] < 1.1
313-
):
333+
if niter > 0 and niter % 10 == 0 and dom_memset[domid] == 0:
334+
mem_pref = qubes.qmemman.algo.pref_mem(dom)
335+
if mem_pref != memset_reqs[domid]:
336+
memset_reqs[domid] = mem_pref
337+
self.log.info("adjusted pref to '%s'", mem_pref)
338+
diff = round(dom.mem_actual / memset_reqs[domid], 2)
339+
if domid not in succeeded and diff <= mem_set_threshold:
314340
succeeded.append(domid)
341+
self.log.debug(
342+
"round '%d' dom '%s' has actual mem of %s (%sx)",
343+
niter,
344+
dom.domid,
345+
dom.mem_actual,
346+
diff,
347+
)
315348
if all(dom in succeeded for dom in domid_list):
316349
return True
317-
if niter >= CHECK_PERIOD:
350+
slow = []
351+
for domid, dom in dom_dict.items():
352+
if domid in succeeded:
353+
continue
354+
assert isinstance(dom.mem_actual, int)
355+
actual_mem_ring.setdefault(domid, []).append(dom.mem_actual)
356+
if niter >= CHECK_PERIOD:
357+
ring = actual_mem_ring[domid]
358+
transfer_speed_mib = int(
359+
(ring[-LAST_SECOND] - ring[-1]) / 1024**2
360+
)
361+
if transfer_speed_mib < CHECK_MB_S:
362+
self.log.warning(
363+
"slow transfer speed of %sMiB/s on the last second",
364+
transfer_speed_mib,
365+
)
366+
slow.append(domid)
367+
if any(dom in slow for dom in domid_list):
318368
return False
319369
for domid, memset in memset_reqs.items():
370+
if domid in succeeded:
371+
continue
320372
self.mem_set(domid, memset)
321-
self.log.debug("sleeping for {} s".format(BALLOON_DELAY))
373+
self.log.debug("sleeping for {}s".format(BALLOON_DELAY))
322374
time.sleep(BALLOON_DELAY)
323375
niter += 1
324376

qubes/vm/qubesvm.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2095,6 +2095,7 @@ def set_mem(self):
20952095
if not qmemman_present or self.maxmem == 0:
20962096
return None
20972097

2098+
self.log.info("Setting qube memory to pref mem")
20982099
qmemman_client = qubes.qmemman.client.QMemmanClient()
20992100
try:
21002101
result = qmemman_client.set_mem({self.xid: 0})

0 commit comments

Comments
 (0)