|
45 | 45 | #: number of free memory bytes expected to get during CHECK_PERIOD_S |
46 | 46 | #: seconds |
47 | 47 | CHECK_DELTA = CHECK_PERIOD_S * CHECK_MB_S * 1024 * 1024 |
| 48 | +LAST_SECOND = max(1, int(1 / BALLOON_DELAY)) |
48 | 49 |
|
49 | 50 |
|
50 | 51 | class SystemState: |
@@ -283,42 +284,93 @@ def do_balloon_dom(self, dom_memset: dict) -> bool: |
283 | 284 | for _, dom in dom_dict.items(): |
284 | 285 | dom.no_progress = False |
285 | 286 |
|
| 287 | + mem_set_threshold = 1.1 |
286 | 288 | succeeded = [] |
287 | 289 | memset_reqs = {} |
288 | 290 | for domid, memset in dom_memset.items(): |
| 291 | + dom = dom_dict[domid] |
289 | 292 | 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 | + ) |
293 | 301 | succeeded.append(domid) |
294 | 302 | continue |
295 | | - mem_pref = qubes.qmemman.algo.pref_mem(dom_dict[domid]) |
| 303 | + mem_pref = qubes.qmemman.algo.pref_mem(dom) |
296 | 304 | 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)", |
299 | 309 | domid, |
300 | 310 | mem_pref, |
| 311 | + dom.mem_actual, |
| 312 | + diff, |
301 | 313 | ) |
302 | 314 | else: |
303 | 315 | 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 | + ) |
304 | 325 |
|
| 326 | + actual_mem_ring: dict[str, list[int]] = {} |
305 | 327 | while True: |
306 | | - self.log.debug("niter={:d}".format(niter)) |
307 | 328 | self.refresh_mem_actual(domid_list) |
308 | 329 | for domid, dom in dom_dict.items(): |
| 330 | + if domid in succeeded: |
| 331 | + continue |
309 | 332 | 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: |
314 | 340 | 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 | + ) |
315 | 348 | if all(dom in succeeded for dom in domid_list): |
316 | 349 | 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): |
318 | 368 | return False |
319 | 369 | for domid, memset in memset_reqs.items(): |
| 370 | + if domid in succeeded: |
| 371 | + continue |
320 | 372 | 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)) |
322 | 374 | time.sleep(BALLOON_DELAY) |
323 | 375 | niter += 1 |
324 | 376 |
|
|
0 commit comments