[gnome-ostree] Dynamically choose memory for QEMU



commit 69300cd6c11b37677721aac2e6b342cb24d669fe
Author: Colin Walters <walters verbum org>
Date:   Mon Jun 3 19:35:11 2013 -0400

    Dynamically choose memory for QEMU
    
    integrationtest was often triggering OOM since we're running 16 cores,
    but only 768M.  Let's scale resources to the machine more slightly
    more intelligently.
    
    But this is still a hack; we really need a global view of resources
    across all tasks.

 src/js/libqa.js          |   81 +++++++++++++++++++++++++++++++--------------
 src/js/tasks/testbase.js |    6 +---
 2 files changed, 57 insertions(+), 30 deletions(-)
---
diff --git a/src/js/libqa.js b/src/js/libqa.js
index f975eec..6d699c5 100644
--- a/src/js/libqa.js
+++ b/src/js/libqa.js
@@ -25,10 +25,62 @@ const ProcUtil = imports.procutil;
 const GuestFish = imports.guestfish;
 
 const DEFAULT_GF_PARTITION_OPTS = ['-m', '/dev/sda3', '-m', '/dev/sda1:/boot'];
-const DEFAULT_QEMU_OPTS = ['-vga', 'std', '-m', '768M',
-                           '-usb', '-usbdevice', 'tablet',
-                          '-net', 'none'];
 
+function linuxGetMemTotalMb() {
+    let [success,contents] = GLib.file_get_contents('/proc/meminfo');
+    let contentLines = contents.toString().split(/\n/);
+    for (let i = 0; contentLines.length; i++) {
+       let line = contentLines[i];
+       if (line.indexOf('MemTotal:') == 0) {
+           return parseInt(/([0-9]+) kB/.exec(line)[1]) / 1024;
+       }
+    }
+    throw new Error("Couldn't determine total memory from /proc/meminfo");
+}
+
+function getQemuPath() {
+    let fallbackPaths = ['/usr/libexec/qemu-kvm']
+    let qemuPathString = GLib.find_program_in_path('qemu-kvm');
+    qemuPathString = GLib.find_program_in_path('qemu-kvm');
+    if (!qemuPathString)
+       qemuPathString = GLib.find_program_in_path('kvm');
+    if (qemuPathString == null) {
+        for (let i = 0; i < fallbackPaths.length; i++) {
+            let path = Gio.File.new_for_path(fallbackPaths[i]);
+            if (!path.query_exists(null))
+                continue;
+            qemuPathString = path.get_path();
+        }
+    }
+    if (qemuPathString == null) {
+        throw new Error("Unable to find qemu-kvm");
+    }
+    return qemuPathString;
+}
+
+function getDefaultQemuOptions(params) {
+    params = Params.parse(params, { parallel: false });
+    let args = [getQemuPath(), '-vga', 'std', '-usb', '-usbdevice', 'tablet', '-net', 'none'];
+
+    let systemMemoryMb = linuxGetMemTotalMb();
+    let minimumGuestMemoryMb = 768;
+    let maximumGuestMemoryMb = 4 * 1024;
+    // As a guess, use 1/4 of host memory, rounded up to the nearest
+    // multiple of 128M; subject to above constraints as a lame
+    // default...we need global coordination here.
+    let guestMemoryGuessMb = Math.floor(systemMemoryMb / 4 / 128) * 128;
+    let guestMemory = Math.floor(Math.max(minimumGuestMemoryMb,
+                                         Math.min(maximumGuestMemoryMb,
+                                                  guestMemoryGuessMb)));
+    args.push.apply(args, ['-m', ''+guestMemory]);
+    
+    if (params.parallel) {
+        let nCores = Math.min(16, GLib.get_num_processors());
+        args.push.apply(args, ['-smp', ''+nCores]);
+    }
+
+    return args;
+}
 
 function newReadWriteMount(diskpath, cancellable) {
     let mntdir = Gio.File.new_for_path('mnt');
@@ -95,26 +147,6 @@ function copyDisk(srcpath, destpath, cancellable) {
                      destpath.get_path()], cancellable);
 }
 
-function getQemuPath() {
-    let fallbackPaths = ['/usr/libexec/qemu-kvm']
-    let qemuPathString = GLib.find_program_in_path('qemu-kvm');
-    qemuPathString = GLib.find_program_in_path('qemu-kvm');
-    if (!qemuPathString)
-       qemuPathString = GLib.find_program_in_path('kvm');
-    if (qemuPathString == null) {
-        for (let i = 0; i < fallbackPaths.length; i++) {
-            let path = Gio.File.new_for_path(fallbackPaths[i]);
-            if (!path.query_exists(null))
-                continue;
-            qemuPathString = path.get_path();
-        }
-    }
-    if (qemuPathString == null) {
-        throw new Error("Unable to find qemu-kvm");
-    }
-    return qemuPathString;
-}
-
 function getDeployDirs(mntdir, osname) {
     let basedir = mntdir.resolve_relative_path('ostree/deploy/' + osname);
     return [basedir.get_child('current'),
@@ -315,8 +347,7 @@ LABEL %s\n\
 }
 
 function bootloaderInstall(diskpath, workdir, osname, cancellable) {
-    let qemuArgs = [getQemuPath()];
-    qemuArgs.push.apply(qemuArgs, DEFAULT_QEMU_OPTS);
+    let qemuArgs = getDefaultQemuOptions();
 
     let tmpKernelPath = workdir.get_child('kernel.img');
     let tmpInitrdPath = workdir.get_child('initrd.img');
diff --git a/src/js/tasks/testbase.js b/src/js/tasks/testbase.js
index 64ec6ec..03abd39 100644
--- a/src/js/tasks/testbase.js
+++ b/src/js/tasks/testbase.js
@@ -260,12 +260,8 @@ const TestOneDisk = new Lang.Class({
         else
             this._diskArch = 'i686';
 
-        let qemuArgs = [LibQA.getQemuPath()];
-        qemuArgs.push.apply(qemuArgs, LibQA.DEFAULT_QEMU_OPTS);
+        let qemuArgs = LibQA.getDefaultQemuOptions({ parallel: true });
     
-        let nCores = Math.min(16, GLib.get_num_processors());
-        qemuArgs.push.apply(qemuArgs, ['-smp', ''+nCores]);
-
         let diskClone = subworkdir.get_child('testoverlay-' + diskPath.get_basename());
         GSystem.shutil_rm_rf(diskClone, cancellable);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]