From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528106616927485.3998379143111; Mon, 4 Jun 2018 03:03:36 -0700 (PDT) Received: from localhost ([::1]:38645 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmKq-0004n9-JY for importer@patchew.org; Mon, 04 Jun 2018 06:03:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46459) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmDh-0007QU-RF for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmDf-00014f-OZ for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:09 -0400 Received: from mail-pg0-x232.google.com ([2607:f8b0:400e:c05::232]:32926) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmDf-000140-IN for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:07 -0400 Received: by mail-pg0-x232.google.com with SMTP id e11-v6so5057011pgq.0 for ; Mon, 04 Jun 2018 02:56:07 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.03 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4NIs+2JTEEmrVtAr14UHoODFpxYdQG+ZGBzKV/b+En0=; b=JUqtzMwoK8OIQ2zXjDjw/gPvSTBNR149j0HnxNt+n5NPU4X5qSPZBzJDOL0pm6F1Hn rWVrZnJgC9zcJzgBcIKNHq+qqpSCnnpeoBVoveag5EVhV0dVF9v2iSHiwffLm4BztQWM sLuv0abq7SaEzu/klW10T1kzyQBR1po8D4569rNwx9cxd2ZrRZEN9GOJAfDpHSc0SFcZ cVFDV9+br6l/qgRIS2/dDu0Zhr5Ge5BLCdq33HdAkMn4a62UwdZ5D/MXahsw7fxi8zUq MuiNj6LwHedeM8O29J9yfb36/IcTfbxYlW02JmAlVAxEeJRgaMg/mb2AJfO3ze2x26zk 6V1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4NIs+2JTEEmrVtAr14UHoODFpxYdQG+ZGBzKV/b+En0=; b=aiAfNPbnoVcOUgyOgCEYbwrA0Fv3BuBvu2/R/zOLxvzziIYZGVHGHDm2hcmFnW3jUr 0JIBHqDT40c2i/XASpqgMFHe4+x9zmeKBzZ48Cl3Tw+1WTnixVhc+SySL16/9C252W8f nzVUYYuN3HiEcgEXukj+aezQ/4kh4ZljqDqnD1xvwnfaJucx3dgLOM9CTUOtkAatx9v+ I+sSUh/dIlax9ydOnVZFJOZugM/pVUENS+4UUEos11KpkhwcB/opEQW2d5rHvRQFnF/5 CdCyrSh4QmWcAfqQnpwQvubRZXbqZtxJuDgiYbdKdAOcma7u4lXjVsue8aeFzYp3q6m3 1iYw== X-Gm-Message-State: ALKqPwdKs6IbqdB4DknHGrK0S//o69SjV7h5X8DzW7UZLCVN9iLSJcfN /980DdBFmeefPPMxaS91580= X-Google-Smtp-Source: ADUXVKJPcLauB3ICQHlHZSxFaoCbTBY4/cr8yMPCtbx/ih7x8HhRvWEKp4kuPrf1bi7AxHKG20kAHw== X-Received: by 2002:a63:931c:: with SMTP id b28-v6mr16451502pge.167.1528106166667; Mon, 04 Jun 2018 02:56:06 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:09 +0800 Message-Id: <20180604095520.8563-2-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::232 Subject: [Qemu-devel] [PATCH 01/12] migration: do not wait if no free thread X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xiao Guangrong Instead of putting the main thread to sleep state to wait for free compression thread, we can directly post it out as normal page that reduces the latency and uses CPUs more efficiently Signed-off-by: Xiao Guangrong --- migration/ram.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index 5bcbf7a9f9..0caf32ab0a 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1423,25 +1423,18 @@ static int compress_page_with_multi_thread(RAMState= *rs, RAMBlock *block, =20 thread_count =3D migrate_compress_threads(); qemu_mutex_lock(&comp_done_lock); - while (true) { - for (idx =3D 0; idx < thread_count; idx++) { - if (comp_param[idx].done) { - comp_param[idx].done =3D false; - bytes_xmit =3D qemu_put_qemu_file(rs->f, comp_param[idx].f= ile); - qemu_mutex_lock(&comp_param[idx].mutex); - set_compress_params(&comp_param[idx], block, offset); - qemu_cond_signal(&comp_param[idx].cond); - qemu_mutex_unlock(&comp_param[idx].mutex); - pages =3D 1; - ram_counters.normal++; - ram_counters.transferred +=3D bytes_xmit; - break; - } - } - if (pages > 0) { + for (idx =3D 0; idx < thread_count; idx++) { + if (comp_param[idx].done) { + comp_param[idx].done =3D false; + bytes_xmit =3D qemu_put_qemu_file(rs->f, comp_param[idx].file); + qemu_mutex_lock(&comp_param[idx].mutex); + set_compress_params(&comp_param[idx], block, offset); + qemu_cond_signal(&comp_param[idx].cond); + qemu_mutex_unlock(&comp_param[idx].mutex); + pages =3D 1; + ram_counters.normal++; + ram_counters.transferred +=3D bytes_xmit; break; - } else { - qemu_cond_wait(&comp_done_cond, &comp_done_lock); } } qemu_mutex_unlock(&comp_done_lock); @@ -1755,7 +1748,10 @@ static int ram_save_target_page(RAMState *rs, PageSe= archStatus *pss, * CPU resource. */ if (block =3D=3D rs->last_sent_block && save_page_use_compression(rs))= { - return compress_page_with_multi_thread(rs, block, offset); + res =3D compress_page_with_multi_thread(rs, block, offset); + if (res > 0) { + return res; + } } =20 return ram_save_page(rs, pss, last_stage); --=20 2.14.4 From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528106417844438.3650086716581; Mon, 4 Jun 2018 03:00:17 -0700 (PDT) Received: from localhost ([::1]:38624 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmHh-0002FW-1d for importer@patchew.org; Mon, 04 Jun 2018 06:00:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46479) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmDj-0007QV-Nv for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmDi-00016V-Tz for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:11 -0400 Received: from mail-pl0-x230.google.com ([2607:f8b0:400e:c01::230]:35514) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmDi-000169-O8 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:10 -0400 Received: by mail-pl0-x230.google.com with SMTP id i5-v6so19391737plt.2 for ; Mon, 04 Jun 2018 02:56:10 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.06 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ZIcgHqiGrOqdEEk6CF+98IpQq3ozsW53SvYXg5tRTjM=; b=rGbAJ9XmGSnkhx2feL9BVP26Qwyl+KuorGsqXstEnH3zrxGJubXNKW8VS93MJyZlWw XR/jg1xLy6tjTvFS8jk36L27TYYFfOcm/GfVuwsmoLPpeFFh1/os3hfVUpfjzO8l2HS8 B+kp+xxDysvFqB/u/T5+Beg6EracF2zRst4137pFxCTNiehAixEPlMzwtsKUcUe2TmZ/ 3WfIm2OSRmQC5SG898Y3cI9K/EOVcD9v1Ph9bbOIXY0kK8V9JYhl/XXqxUZFrhsuFdUF dAubhH9XxIKPCZH0D8qlCHGP+kcb0LUBsPqthoZgNnpSQt59l0tkC/H0inMTVcwdSWv0 eUVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ZIcgHqiGrOqdEEk6CF+98IpQq3ozsW53SvYXg5tRTjM=; b=A4Vko6V3Zh3TKO40Va9NAR5xoxq58d5nfBWk8Glh83OLhlhTh1d8KdR5WFBqM/CXQ5 qlsDH0sFWYB9nBDLF+17ZmACPWDmH9F4XYSX7omE2eiApoTEpll8UVN2dlPSPbPzYSyX J812TL+6EvijB/bbT7rz1+JHserLDLc5yIi5jnZiqmKSbCV/yqmUUaFIdib3Hnd/QXa9 KBDjbTHPAYoW9dWuZfJ5Aoh76fE+Ww7qOF0TjQDqPYoTtUFxUK029iSUQIcBJCam+Ogm /rmBilxvn86nbNEvNG5eQjUZ5K2O0HJsOVRmHQgFYXvbNKuV4pk2k5Y4Qts4Q/TWCBaA ljPQ== X-Gm-Message-State: ALKqPwfdfoY15QcaMT/KtwqbsRICb9WrIYEP4LauwUxafQaigK/08kv+ xKcOEtt4usu8lETRxDFSaWw= X-Google-Smtp-Source: ADUXVKJs/tJY4/GJ6bDgw9vgrnb6zuAY6vuUZNQYR+cDD4m2dQ5lsUosiIZQ6a/riyKF/feMLlnfOg== X-Received: by 2002:a17:902:3a5:: with SMTP id d34-v6mr21612324pld.103.1528106169880; Mon, 04 Jun 2018 02:56:09 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:10 +0800 Message-Id: <20180604095520.8563-3-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::230 Subject: [Qemu-devel] [PATCH 02/12] migration: fix counting normal page for compression X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xiao Guangrong The compressed page is not normal page Signed-off-by: Xiao Guangrong --- migration/ram.c | 1 - 1 file changed, 1 deletion(-) diff --git a/migration/ram.c b/migration/ram.c index 0caf32ab0a..dbf24d8c87 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1432,7 +1432,6 @@ static int compress_page_with_multi_thread(RAMState *= rs, RAMBlock *block, qemu_cond_signal(&comp_param[idx].cond); qemu_mutex_unlock(&comp_param[idx].mutex); pages =3D 1; - ram_counters.normal++; ram_counters.transferred +=3D bytes_xmit; break; } --=20 2.14.4 From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528106362936786.8723880961012; Mon, 4 Jun 2018 02:59:22 -0700 (PDT) Received: from localhost ([::1]:38619 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmGo-0001HT-62 for importer@patchew.org; Mon, 04 Jun 2018 05:59:22 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46490) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmDm-0007S3-N5 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmDm-000180-2x for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:14 -0400 Received: from mail-pg0-x22e.google.com ([2607:f8b0:400e:c05::22e]:39554) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmDl-00017a-Su for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:14 -0400 Received: by mail-pg0-x22e.google.com with SMTP id w12-v6so13037391pgc.6 for ; Mon, 04 Jun 2018 02:56:13 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.10 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GTtfNbytUKqqoHpXl/5SQkmcW73uJZck6kFxWCHAV8A=; b=jS5zpSYeV5+rP12XO+cP0TVtfPq5nsXoJ8bSlzhj5R13zWGYnsUNiYTTMPD+cz9fSC rgn1L2gYyCjQJ2LxmQXd7Nk9zVkznlCFhuVI6laRFw4VIUOtqTOqkUtAoVpr+bNzAjnK 4FwXAlJWHuVpX73LKOjJg9F4ibbTJRvWAomD4qIOpbW2B6q3V2lUXAFZ3dphMwLRQ/Le YeRjj0HMChlNMnRbw2oPPf3yBPsdRX4tBSxI97XEZNLZ3iHmZXBorME/x5mnICml6bbA BYgaAKyxE2ci3z2gtaOQGauV1mlIAiUyxP6Le6/PkhbGdO8bJDJN9Fw/ToKGe+yONGrG OR6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=GTtfNbytUKqqoHpXl/5SQkmcW73uJZck6kFxWCHAV8A=; b=P6zi8iz9G0WBoPz83QD0hPkmD9OKxOx7nDAC44WP/eYbn7UorbbVfQuYH11EXsl9Kw bjN2JajKn7Zqq3wSiYXYByYex+hTgy6rVhnhIYu6/G+SN1m4EyJbpcs+ZKw/+X1T2+qM vlcx8lc/fsWYaYG7ZXgIkDIUKShWxZFteHubPSdz2lp3eSXGDwZSsZRUPXsyU1MQWOIC lhgsaVaSIrtVvR8uyLEyC7Q/jSvItVhOb59h/JDTHyy70uewhPyVYUw5T5wKs3pGV/pb xkvtCUkeZFaAtYUYpZboyeY10jAKJ2qumuTNmumIMJQDnElzxf/tWlzjfnDdxn2mdEzC igkQ== X-Gm-Message-State: ALKqPweMUtvNgSKIZebdyCg+DfPRsztB+7znm61EYh4nr3kQvBiCUbW/ 4faFVfUyxgEHMzIGV2ITJkP1KA== X-Google-Smtp-Source: ADUXVKK4h966uNi06yiGHh+g7OT5fLKRfRD0i5FAo5HRsDBd9u412g39/KYqXjirTZLkrQ1C+8SH/g== X-Received: by 2002:a63:2bc4:: with SMTP id r187-v6mr16651146pgr.231.1528106173019; Mon, 04 Jun 2018 02:56:13 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:11 +0800 Message-Id: <20180604095520.8563-4-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::22e Subject: [Qemu-devel] [PATCH 03/12] migration: fix counting xbzrle cache_miss_rate X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xiao Guangrong Sync up xbzrle_cache_miss_prev only after migration iteration goes forward Signed-off-by: Xiao Guangrong Reviewed-by: Dr. David Alan Gilbert --- migration/ram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/ram.c b/migration/ram.c index dbf24d8c87..dd1283dd45 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1189,9 +1189,9 @@ static void migration_bitmap_sync(RAMState *rs) (double)(xbzrle_counters.cache_miss - rs->xbzrle_cache_miss_prev) / (rs->iterations - rs->iterations_prev); + rs->xbzrle_cache_miss_prev =3D xbzrle_counters.cache_miss; } rs->iterations_prev =3D rs->iterations; - rs->xbzrle_cache_miss_prev =3D xbzrle_counters.cache_miss; } =20 /* reset period counters */ --=20 2.14.4 From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528106548136720.2908816654634; Mon, 4 Jun 2018 03:02:28 -0700 (PDT) Received: from localhost ([::1]:38640 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmJn-0003zS-9K for importer@patchew.org; Mon, 04 Jun 2018 06:02:27 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46531) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmDu-0007Yw-6Q for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmDp-00019b-Ce for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:22 -0400 Received: from mail-pg0-x233.google.com ([2607:f8b0:400e:c05::233]:42116) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmDp-00019H-66 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:17 -0400 Received: by mail-pg0-x233.google.com with SMTP id p9-v6so14239988pgc.9 for ; Mon, 04 Jun 2018 02:56:17 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.13 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=rFUOcxpoIl7y/fY0ndasP+psXK2ovkE6HqfEdl19mjE=; b=GaqS63asSa6vTreBBOwH/jmN57rgIL+ibWSFAXJZTia/9O1qP1cbgZ+y+eZSVApKDP b/AkVzebpiEsKk2vCz84iSthQHzexy4JAma8u/miO/CAPbgE59KD4HV457qgY9jmp7t5 5le1U/th4r8jVwy8W9DsAKHAt4Oa9/b4+hVN9ZohOrLyPMof3Pe/g3mFcYu35q4FdURI ma1OQS03dDwwh/ezShfGjB7Ej7OM42FS7sIOLCDyi/H9y9PTbwdlIHfKW35fBBu52ajP JjCRIh1ZZeUvj3oIoX+hPNSyRLdkY4Que3ndgzLl8YPZrjGEQGRpGwdAp95+CyqZpgHE NWoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=rFUOcxpoIl7y/fY0ndasP+psXK2ovkE6HqfEdl19mjE=; b=pIK9lLAh/sWWJzsYXUmnmEDCbon9Yh6k+cidbexUswb8PCJVHzcmToUlbodZm0jOR0 mnJ3np/OJLNUDicAzFz4vpn9f8+hKCuMMvOJfWR5Nglx1yVhttqdIlzHiPtER6Cu69+6 sOftyEIHTI5KcXmyjUVcaxaetSJyYrC0ydgXp8hrYDmLS6500aHKE1p7GPWj/8tsHOkk tCruOowEUTiBhXG67OPQZzNlo8BGx2sW5dZIO6CCQ86zrH3mGtM8SSKuQcI4uy8FpaW+ aghvgrTT60wEMnbeWiO97ITrhSqGAAgiFgQz4etIaO1zaH1gD+WFRSalvUttp/nVNpJX rc/A== X-Gm-Message-State: ALKqPwca4x1r/YuBrnjykoVYS5+KVQqer+MMVbqy5xzkroRdD+6R3NJk rwIAdZo5a0k0mgxBRC9gQxE= X-Google-Smtp-Source: ADUXVKIsSoERgKOm+tFHUYP+1VZBGvGsU8431lYlMO3rqUabtWEec4d8QKQ+rbGTNSw5ev7OvC0Btw== X-Received: by 2002:a63:778b:: with SMTP id s133-v6mr16204691pgc.400.1528106176279; Mon, 04 Jun 2018 02:56:16 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:12 +0800 Message-Id: <20180604095520.8563-5-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::233 Subject: [Qemu-devel] [PATCH 04/12] migration: introduce migration_update_rates X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xiao Guangrong It is used to slightly clean the code up, no logic is changed Signed-off-by: Xiao Guangrong Reviewed-by: Dr. David Alan Gilbert --- migration/ram.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index dd1283dd45..ee03b28435 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1130,6 +1130,25 @@ uint64_t ram_pagesize_summary(void) return summary; } =20 +static void migration_update_rates(RAMState *rs, int64_t end_time) +{ + uint64_t iter_count =3D rs->iterations - rs->iterations_prev; + + /* calculate period counters */ + ram_counters.dirty_pages_rate =3D rs->num_dirty_pages_period * 1000 + / (end_time - rs->time_last_bitmap_sync); + + if (!iter_count) { + return; + } + + if (migrate_use_xbzrle()) { + xbzrle_counters.cache_miss_rate =3D (double)(xbzrle_counters.cache= _miss - + rs->xbzrle_cache_miss_prev) / iter_count; + rs->xbzrle_cache_miss_prev =3D xbzrle_counters.cache_miss; + } +} + static void migration_bitmap_sync(RAMState *rs) { RAMBlock *block; @@ -1159,9 +1178,6 @@ static void migration_bitmap_sync(RAMState *rs) =20 /* more than 1 second =3D 1000 millisecons */ if (end_time > rs->time_last_bitmap_sync + 1000) { - /* calculate period counters */ - ram_counters.dirty_pages_rate =3D rs->num_dirty_pages_period * 1000 - / (end_time - rs->time_last_bitmap_sync); bytes_xfer_now =3D ram_counters.transferred; =20 /* During block migration the auto-converge logic incorrectly dete= cts @@ -1183,16 +1199,9 @@ static void migration_bitmap_sync(RAMState *rs) } } =20 - if (migrate_use_xbzrle()) { - if (rs->iterations_prev !=3D rs->iterations) { - xbzrle_counters.cache_miss_rate =3D - (double)(xbzrle_counters.cache_miss - - rs->xbzrle_cache_miss_prev) / - (rs->iterations - rs->iterations_prev); - rs->xbzrle_cache_miss_prev =3D xbzrle_counters.cache_miss; - } - rs->iterations_prev =3D rs->iterations; - } + migration_update_rates(rs, end_time); + + rs->iterations_prev =3D rs->iterations; =20 /* reset period counters */ rs->time_last_bitmap_sync =3D end_time; --=20 2.14.4 From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528106461649593.2659294647418; Mon, 4 Jun 2018 03:01:01 -0700 (PDT) Received: from localhost ([::1]:38633 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmIO-0002rM-Pb for importer@patchew.org; Mon, 04 Jun 2018 06:01:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46532) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmDu-0007Yx-75 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmDs-0001Aq-NM for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:22 -0400 Received: from mail-pl0-x244.google.com ([2607:f8b0:400e:c01::244]:39696) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmDs-0001AS-Dt for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:20 -0400 Received: by mail-pl0-x244.google.com with SMTP id f1-v6so18956671plt.6 for ; Mon, 04 Jun 2018 02:56:20 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.16 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=S45CZXLrcKyS7wD5A3IyHvvzQNr9spl5Eof4b8X9Xeg=; b=Bo5Ba3kTF5/8Ekd9m3SjIEciY3Kjp7S8Hp0KG9hUt5YGqYr7rQ5DMiiF0PH+h4vofM YiymzvIxxuWaDiwf/31Huue/7UiDxRclDFVl6xnYXoM0WAt3sjTGMgh0M8Wf5x2hI5S5 BaSHw3z2Yas//5tTmi8EWWg9XZnW9IsqqcmprOniHk8EbMHKYcPtDzmRVmnp3HcmIP3F sCVpapw0yv85/YxpSW1RcSwmXkY7HSQ9Heosa456/TSDDfvgFlVmMiEvzEPCYOdAC0rg xd0quH4xNhGuaYMVWMQlOdTvHcgY/VRzaxgZUlUqCcIa9Rf6QXxgcOvAuSGWp4Xm5fV+ Wkvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=S45CZXLrcKyS7wD5A3IyHvvzQNr9spl5Eof4b8X9Xeg=; b=lXUePMVxWGEmzKPPcHR7FHyfiIZlkurUHNIDjs46wBAfLFec7cWlmVLzvMwGIEI0C5 avOmvcdOxyLfaNB/FwopKjP4XBmyhdzmJOwYVqkfJnu4miC1Geixc75Rsm8GTB4WC9+d tGNbc84/25zUFR7vw69xgeSxZcvVAuUcnTbI6/OKZ7Q8Y1x1QRH5BM9wYB+YSlNfiseM njyjcQlxhFOf1Bu/rrf7vSqDT9kneoHHgs2ELOnKNV3/jlYbxFL1nvtphJO3tNKPEd5V p9ahzeJOjArJ4YvU9vZ9FNsyeDLPOvEamOfrwz//bmvQBCR+wmXysCC18C8yzV/60yeF fL+w== X-Gm-Message-State: APt69E0X7C1Hd4A+Hu3PUXPLKO3Wj+mFVlN2Ll5ibpC2riG0oosF0siA 4n/3Skbp4lB1Qdaa2mizASQ= X-Google-Smtp-Source: ADUXVKJiJ08ofTxhqE91WCYOQ4rTl/fnljAkgZQ0tshBZ+8jxpV/Zi4E7L8l6JzXtXIf5L3gyuBKVw== X-Received: by 2002:a17:902:9309:: with SMTP id bc9-v6mr3269923plb.189.1528106179493; Mon, 04 Jun 2018 02:56:19 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:13 +0800 Message-Id: <20180604095520.8563-6-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::244 Subject: [Qemu-devel] [PATCH 05/12] migration: show the statistics of compression X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xiao Guangrong Then the uses can adjust the parameters based on this info Currently, it includes: pages: amount of pages compressed and transferred to the target VM busy: amount of count that no free thread to compress data busy-rate: rate of thread busy reduced-size: amount of bytes reduced by compression compression-rate: rate of compressed size Signed-off-by: Xiao Guangrong --- hmp.c | 13 +++++++++++++ migration/migration.c | 11 +++++++++++ migration/ram.c | 37 +++++++++++++++++++++++++++++++++++++ migration/ram.h | 1 + qapi/migration.json | 25 ++++++++++++++++++++++++- 5 files changed, 86 insertions(+), 1 deletion(-) diff --git a/hmp.c b/hmp.c index ef93f4878b..5c2d3bd318 100644 --- a/hmp.c +++ b/hmp.c @@ -269,6 +269,19 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) info->xbzrle_cache->overflow); } =20 + if (info->has_compression) { + monitor_printf(mon, "compression pages: %" PRIu64 " pages\n", + info->compression->pages); + monitor_printf(mon, "compression busy: %" PRIu64 "\n", + info->compression->busy); + monitor_printf(mon, "compression busy rate: %0.2f\n", + info->compression->busy_rate); + monitor_printf(mon, "compression reduced size: %" PRIu64 "\n", + info->compression->reduced_size); + monitor_printf(mon, "compression rate: %0.2f\n", + info->compression->compression_rate); + } + if (info->has_cpu_throttle_percentage) { monitor_printf(mon, "cpu throttle percentage: %" PRIu64 "\n", info->cpu_throttle_percentage); diff --git a/migration/migration.c b/migration/migration.c index 05aec2c905..bf7c63a5a2 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -693,6 +693,17 @@ static void populate_ram_info(MigrationInfo *info, Mig= rationState *s) info->xbzrle_cache->overflow =3D xbzrle_counters.overflow; } =20 + if (migrate_use_compression()) { + info->has_compression =3D true; + info->compression =3D g_malloc0(sizeof(*info->compression)); + info->compression->pages =3D compression_counters.pages; + info->compression->busy =3D compression_counters.busy; + info->compression->busy_rate =3D compression_counters.busy_rate; + info->compression->reduced_size =3D compression_counters.reduced_s= ize; + info->compression->compression_rate =3D + compression_counters.compression_rate; + } + if (cpu_throttle_active()) { info->has_cpu_throttle_percentage =3D true; info->cpu_throttle_percentage =3D cpu_throttle_get_percentage(); diff --git a/migration/ram.c b/migration/ram.c index ee03b28435..80914b747e 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -292,6 +292,15 @@ struct RAMState { uint64_t num_dirty_pages_period; /* xbzrle misses since the beginning of the period */ uint64_t xbzrle_cache_miss_prev; + + /* compression statistics since the beginning of the period */ + /* amount of count that no free thread to compress data */ + uint64_t compress_thread_busy_prev; + /* amount bytes reduced by compression */ + uint64_t compress_reduced_size_prev; + /* amount of compressed pages */ + uint64_t compress_pages_prev; + /* number of iterations at the beginning of period */ uint64_t iterations_prev; /* Iterations since start */ @@ -329,6 +338,8 @@ struct PageSearchStatus { }; typedef struct PageSearchStatus PageSearchStatus; =20 +CompressionStats compression_counters; + struct CompressParam { bool done; bool quit; @@ -1147,6 +1158,24 @@ static void migration_update_rates(RAMState *rs, int= 64_t end_time) rs->xbzrle_cache_miss_prev) / iter_count; rs->xbzrle_cache_miss_prev =3D xbzrle_counters.cache_miss; } + + if (migrate_use_compression()) { + uint64_t comp_pages; + + compression_counters.busy_rate =3D (double)(compression_counters.b= usy - + rs->compress_thread_busy_prev) / iter_count; + rs->compress_thread_busy_prev =3D compression_counters.busy; + + comp_pages =3D compression_counters.pages - rs->compress_pages_pre= v; + if (comp_pages) { + compression_counters.compression_rate =3D + (double)(compression_counters.reduced_size - + rs->compress_reduced_size_prev) / + (comp_pages * TARGET_PAGE_SIZE); + rs->compress_pages_prev =3D compression_counters.pages; + rs->compress_reduced_size_prev =3D compression_counters.reduce= d_size; + } + } } =20 static void migration_bitmap_sync(RAMState *rs) @@ -1412,6 +1441,9 @@ static void flush_compressed_data(RAMState *rs) qemu_mutex_lock(&comp_param[idx].mutex); if (!comp_param[idx].quit) { len =3D qemu_put_qemu_file(rs->f, comp_param[idx].file); + /* 8 means a header with RAM_SAVE_FLAG_CONTINUE. */ + compression_counters.reduced_size +=3D TARGET_PAGE_SIZE - len = + 8; + compression_counters.pages++; ram_counters.transferred +=3D len; } qemu_mutex_unlock(&comp_param[idx].mutex); @@ -1441,6 +1473,10 @@ static int compress_page_with_multi_thread(RAMState = *rs, RAMBlock *block, qemu_cond_signal(&comp_param[idx].cond); qemu_mutex_unlock(&comp_param[idx].mutex); pages =3D 1; + /* 8 means a header with RAM_SAVE_FLAG_CONTINUE. */ + compression_counters.reduced_size +=3D TARGET_PAGE_SIZE - + bytes_xmit + 8; + compression_counters.pages++; ram_counters.transferred +=3D bytes_xmit; break; } @@ -1760,6 +1796,7 @@ static int ram_save_target_page(RAMState *rs, PageSea= rchStatus *pss, if (res > 0) { return res; } + compression_counters.busy++; } =20 return ram_save_page(rs, pss, last_stage); diff --git a/migration/ram.h b/migration/ram.h index d386f4d641..7b009b23e5 100644 --- a/migration/ram.h +++ b/migration/ram.h @@ -36,6 +36,7 @@ =20 extern MigrationStats ram_counters; extern XBZRLECacheStats xbzrle_counters; +extern CompressionStats compression_counters; =20 int xbzrle_cache_resize(int64_t new_size, Error **errp); uint64_t ram_bytes_remaining(void); diff --git a/qapi/migration.json b/qapi/migration.json index 3ec418dabf..a11987cdc4 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -72,6 +72,26 @@ 'cache-miss': 'int', 'cache-miss-rate': 'number', 'overflow': 'int' } } =20 +## +# @CompressionStats: +# +# Detailed compression migration statistics +# +# @pages: amount of pages compressed and transferred to the target VM +# +# @busy: amount of count that no free thread to compress data +# +# @busy-rate: rate of thread busy +# +# @reduced-size: amount of bytes reduced by compression +# +# @compression-rate: rate of compressed size +# +## +{ 'struct': 'CompressionStats', + 'data': {'pages': 'int', 'busy': 'int', 'busy-rate': 'number', + 'reduced-size': 'int', 'compression-rate': 'number' } } + ## # @MigrationStatus: # @@ -169,6 +189,8 @@ # only present when the postcopy-blocktime migration capability # is enabled. (Since 2.13) # +# @compression: compression migration statistics, only returned if compres= sion +# feature is on and status is 'active' or 'completed' (Since 2.1= 4) # # Since: 0.14.0 ## @@ -183,7 +205,8 @@ '*cpu-throttle-percentage': 'int', '*error-desc': 'str', '*postcopy-blocktime' : 'uint32', - '*postcopy-vcpu-blocktime': ['uint32']} } + '*postcopy-vcpu-blocktime': ['uint32'], + '*compression': 'CompressionStats'} } =20 ## # @query-migrate: --=20 2.14.4 From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 15281064495821016.2080726163625; Mon, 4 Jun 2018 03:00:49 -0700 (PDT) Received: from localhost ([::1]:38631 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmIC-0002fp-Nv for importer@patchew.org; Mon, 04 Jun 2018 06:00:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46552) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmDw-0007bL-Km for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmDv-0001CA-Og for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:24 -0400 Received: from mail-pl0-x243.google.com ([2607:f8b0:400e:c01::243]:34704) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmDv-0001Bs-Ir for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:23 -0400 Received: by mail-pl0-x243.google.com with SMTP id g20-v6so1601248plq.1 for ; Mon, 04 Jun 2018 02:56:23 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.19 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=aH2Gwskf+jJbLGc5BYs25N5cBEGULq8L0irgyJaU/HM=; b=X0WCPNbNZXYyoD7cHY3remVQ1Nho84koou+Yo5PdHO2cCf5s0/N/1wG6z5+5UDJ6yU u6Xoj8RniuyoI78gHgUoeRwVAIjTv/4uuxxSBeQWfMXJnfzFdrpNBjq/Hr4fEstM0dbK dnXely0pBUGE2TxLORPOy6C2492AfzwHI6XbRUoat8c4tHTbHg2T6ufMn5RKR4fpTABq 4ucm3VxJjySZrn+8fg60oApbl2l1KjWmm4bMEhwwh+cpz+hZVpNsIvyRXFPklgbzer93 dSc8X1f4jZyWxtRaJpByS7BFE0e/EP8wl/dyMez3IpoGzxenPxipbruvptl57pdpcJey o1PQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=aH2Gwskf+jJbLGc5BYs25N5cBEGULq8L0irgyJaU/HM=; b=ZJcYU0+4OjrvjfVwWkdlAsKL2CNiKnwNXTeZAwoyeb0KD2JQRu9y/785XNPT8FuS+/ LyPjFyKOPLjPc2kjRYJR8pRA5hLxcOQ+Hv0Tpa7xDIaM1UCFLv3BslefWJzdzd+kM+cc 14ly98t9pd7fahpWbFR60KxBGiszTKswGZS6tLnsO9LncKsOiutJneHFIqlPT5qc8xyO 1UkYZWj+VNDbs2AUsy2Nq9E32o+3HAYCr1TvLigAQANu68kCLlh5s9KGvq26JcAR5wFt 8oJtrM5IfntBO3nvgs3cgRxC/u2Z9+AmpMwazZ12IjysbxxbvNb5jorm8nwgcjF1VW6a TdCg== X-Gm-Message-State: ALKqPwdp2+nScPLl7NrLtVCzeZ6E0RAr4pRYm0dzk1N/uroq//jKUtic KGryBPPKiC/riaQQLGcHojo= X-Google-Smtp-Source: ADUXVKJLPcKpQ3DWcjYJZKnBDjawUPjpu59nJCChtVYIAwQngzRp4ST4AiGwaEdy+Taeb3VjonjIqg== X-Received: by 2002:a17:902:d697:: with SMTP id v23-v6mr12715755ply.193.1528106182707; Mon, 04 Jun 2018 02:56:22 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:14 +0800 Message-Id: <20180604095520.8563-7-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::243 Subject: [Qemu-devel] [PATCH 06/12] migration: do not detect zero page for compression X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xiao Guangrong Detecting zero page is not a light work, we can disable it for compression that can handle all zero data very well Signed-off-by: Xiao Guangrong --- migration/ram.c | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index 80914b747e..15b20d3f70 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1760,15 +1760,30 @@ static int ram_save_target_page(RAMState *rs, PageS= earchStatus *pss, return res; } =20 - /* - * When starting the process of a new block, the first page of - * the block should be sent out before other pages in the same - * block, and all the pages in last block should have been sent - * out, keeping this order is important, because the 'cont' flag - * is used to avoid resending the block name. - */ - if (block !=3D rs->last_sent_block && save_page_use_compression(rs)) { + if (save_page_use_compression(rs)) { + /* + * When starting the process of a new block, the first page of + * the block should be sent out before other pages in the same + * block, and all the pages in last block should have been sent + * out, keeping this order is important, because the 'cont' flag + * is used to avoid resending the block name. + * + * We post the fist page as normal page as compression will take + * much CPU resource. + */ + if (block !=3D rs->last_sent_block) { flush_compressed_data(rs); + } else { + /* + * do not detect zero page as it can be handled very well + * for compression + */ + res =3D compress_page_with_multi_thread(rs, block, offset); + if (res > 0) { + return res; + } + compression_counters.busy++; + } } =20 res =3D save_zero_page(rs, block, offset); @@ -1785,19 +1800,6 @@ static int ram_save_target_page(RAMState *rs, PageSe= archStatus *pss, return res; } =20 - /* - * Make sure the first page is sent out before other pages. - * - * we post it as normal page as compression will take much - * CPU resource. - */ - if (block =3D=3D rs->last_sent_block && save_page_use_compression(rs))= { - res =3D compress_page_with_multi_thread(rs, block, offset); - if (res > 0) { - return res; - } - compression_counters.busy++; - } =20 return ram_save_page(rs, pss, last_stage); } --=20 2.14.4 From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 152810664615787.18393994233259; Mon, 4 Jun 2018 03:04:06 -0700 (PDT) Received: from localhost ([::1]:38648 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmLN-00058z-5C for importer@patchew.org; Mon, 04 Jun 2018 06:04:05 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46564) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmDz-0007g9-LS for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmDy-0001Dd-RQ for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:27 -0400 Received: from mail-pl0-x243.google.com ([2607:f8b0:400e:c01::243]:33370) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmDy-0001DS-Ks for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:26 -0400 Received: by mail-pl0-x243.google.com with SMTP id n10-v6so19388158plp.0 for ; Mon, 04 Jun 2018 02:56:26 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.22 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GWPTn5Zn3pO7uqSBhl34CPShONRtaV8vyCn3yu3F3wo=; b=UCEiPKwPHBRiZrCyUE5lqIJFVq3v6KtpWZ1fTRK1jUwVjsChCUjmIrhlyhKUW3KwRV SU4nzHb1O46acXr+jV7QFcQ5NZVeDozFaASfhHm4FtsIl3gPYH4AQRJfH0L79NcaA8by 7dKvMevc+YqHuLYmcIQzfdziVivFq8rocZb2G2hWc/vFnmpfcEujevOdLuP6FJr/DMHn hMKaQt89PZK/mfr6yu9BXELYlCnFU8GjA2DqkDTwegtd4ZY+Up1H4hK0+oN9NPu6NKLB b+6XsvtZEyT+fgeQWxXuDmE8UXlOLN8xWyaacbWjHs41IU4z+sqIAZtmJf3fAFQIpWlj 2FdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=GWPTn5Zn3pO7uqSBhl34CPShONRtaV8vyCn3yu3F3wo=; b=dZcvbKzsT7pGfEIWrj/6Wr4tHwqgIvOQ9kbbtf4a1uu7yeugIALHIk/sfuLJUGPxF7 wL8YFlVJyssW2ZAoN4Ogoi+j5n/8RXUiAOUq8n2bUYLXVR4Kdil3YesDkI8LBR62YBu0 0Cho5+IpFr0i1bTIJjt5kaW5dpYwW0KHR9yLREIou644i+mMJM6hQkMeyds03UymLNVg uikcixGsog+++PiXly7r4ZLI3gm3LifvXtlmn4uOa1dGLJ7Pm17OZU7pMK6lChLpR+sw tErF51YtPQ9NbxOTmd5wuR0Tj8Y7b6PSONG8pOeTK63vPGDVYmhKH9HiG8ZJ49fXVdeP hFMg== X-Gm-Message-State: APt69E2PjFb36mPrP+/QHqkncpzBCcGhXjArPDx4XglIC/1c9B918JAx PZuRQZh7imXXiy0ifrztm6Q= X-Google-Smtp-Source: ADUXVKJFXAZ8Plutfh9jyIaaSIo+osOppw7aqNIXVlKj1sL/YvQ7mGWwHd9klqk+CMQ+ARJzjR+3mg== X-Received: by 2002:a17:902:b582:: with SMTP id a2-v6mr9032712pls.335.1528106185831; Mon, 04 Jun 2018 02:56:25 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:15 +0800 Message-Id: <20180604095520.8563-8-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::243 Subject: [Qemu-devel] [PATCH 07/12] migration: hold the lock only if it is really needed X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xiao Guangrong Try to hold src_page_req_mutex only if the queue is not empty Signed-off-by: Xiao Guangrong Reviewed-by: Dr. David Alan Gilbert --- include/qemu/queue.h | 1 + migration/ram.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/include/qemu/queue.h b/include/qemu/queue.h index 59fd1203a1..ac418efc43 100644 --- a/include/qemu/queue.h +++ b/include/qemu/queue.h @@ -341,6 +341,7 @@ struct { = \ /* * Simple queue access methods. */ +#define QSIMPLEQ_EMPTY_ATOMIC(head) (atomic_read(&((head)->sqh_first)) =3D= =3D NULL) #define QSIMPLEQ_EMPTY(head) ((head)->sqh_first =3D=3D NULL) #define QSIMPLEQ_FIRST(head) ((head)->sqh_first) #define QSIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) diff --git a/migration/ram.c b/migration/ram.c index 15b20d3f70..f9a8646520 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1550,6 +1550,10 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr= _t *offset) { RAMBlock *block =3D NULL; =20 + if (QSIMPLEQ_EMPTY_ATOMIC(&rs->src_page_requests)) { + return NULL; + } + qemu_mutex_lock(&rs->src_page_req_mutex); if (!QSIMPLEQ_EMPTY(&rs->src_page_requests)) { struct RAMSrcPageRequest *entry =3D --=20 2.14.4 From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528106807065775.2581369599797; Mon, 4 Jun 2018 03:06:47 -0700 (PDT) Received: from localhost ([::1]:38666 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmNy-0007d4-7L for importer@patchew.org; Mon, 04 Jun 2018 06:06:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46585) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmE7-0007mP-05 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmE2-0001GU-4w for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:35 -0400 Received: from mail-pf0-x243.google.com ([2607:f8b0:400e:c00::243]:42185) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmE1-0001GA-VB for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:30 -0400 Received: by mail-pf0-x243.google.com with SMTP id w7-v6so272827pfn.9 for ; Mon, 04 Jun 2018 02:56:29 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.26 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6UIMXJeRHsmt3t6Z9BLFXL0bs+zbtKQsppSSK4fEsCs=; b=s7kAjAmikinq0AESH3ls5h4ISiHqsxfDeaTMCgi82IhvA+kOXq1XpqALjnuEAwYRha 5f0QixuXqoAQJ8yB7EBBV7HHE4FAWXLmT2/ppOIkJw7T9TkyDQLPdZ9KVc7Ax1QEr3b0 WI6gHC2n7K/ZRzCdh8mzN56qrMljHIhe2YdyVJ08VTNx1CaWmMKfj3TI11HsaKl5Z9CB Ihh1Tq3ZG8lp18JWZ4doV+SnvDuIX02mvG2dJuQ0MR6qfjQ50+8KqqVrceZypam2RdRc NIq/uw9ffM39ON1wUtxWAQRPXFdCLtTMN1NGH27Rlq+RXb4wzWY0oly7YyngJN6QebRV JRsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6UIMXJeRHsmt3t6Z9BLFXL0bs+zbtKQsppSSK4fEsCs=; b=hKmFfLJmp/lK3NQDSzPUqxaXzEyRRUWf6qfhkbASs9zUN3MSvO5CKRIsGkm8qhdZk7 Moal3DRVQeqvxgL+RKPM/SN7XMihlJxZDH8MEijLp2a+vPZJdoXnJPc28mbIc5tPYGTe u2YJ7vokik4vMkLrt816ePAB7fgUnHNQMG++gQMa/qPpwwsNkL5bCKfmY1PGmlndmK0G FX1WzlET4bGH0JQmDJ3bFsot7cP2J4hgUYW4POmIYptC0HfOn2N/MG+POC+3mo47jlwm SviswOX8x9nEs9F0D49po0qOzVtiqSpOPC9drDLlShtEOMZRwA7mCwDxxetBv/gMbUVd LozA== X-Gm-Message-State: ALKqPwdZBLkvG/FfjwU9FJ4YncxMiT+D9JniiNCRmh6bz11um+P6bGVx a0/mtes1tn5ZyEH8BCyO9uU= X-Google-Smtp-Source: ADUXVKKqubf/LkGirzMmh8PqssJ2bkS4ch5nn7rZmf/Y9/toxisMiT1yAoaYEtnhlxLi/lHuI0jMPw== X-Received: by 2002:a62:ff1d:: with SMTP id b29-v6mr20815419pfn.181.1528106188946; Mon, 04 Jun 2018 02:56:28 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:16 +0800 Message-Id: <20180604095520.8563-9-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::243 Subject: [Qemu-devel] [PATCH 08/12] migration: do not flush_compressed_data at the end of each iteration X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xiao Guangrong flush_compressed_data() needs to wait all compression threads to finish their work, after that all threads are free until the migration feed new request to them, reducing its call can improve the throughput and use CPU resource more effectively We do not need to flush all threads at the end of iteration, the data can be kept locally until the memory block is changed Signed-off-by: Xiao Guangrong --- migration/ram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/ram.c b/migration/ram.c index f9a8646520..0a38c1c61e 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1994,6 +1994,7 @@ static void ram_save_cleanup(void *opaque) } =20 xbzrle_cleanup(); + flush_compressed_data(*rsp); compress_threads_save_cleanup(); ram_state_cleanup(rsp); } @@ -2690,7 +2691,6 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) } i++; } - flush_compressed_data(rs); rcu_read_unlock(); =20 /* --=20 2.14.4 From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 15281066615271006.234748857094; Mon, 4 Jun 2018 03:04:21 -0700 (PDT) Received: from localhost ([::1]:38650 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmLc-0005N7-6b for importer@patchew.org; Mon, 04 Jun 2018 06:04:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46587) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmE7-0007mT-71 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmE5-0001I3-G3 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:35 -0400 Received: from mail-pg0-x243.google.com ([2607:f8b0:400e:c05::243]:43792) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmE5-0001Hb-6u for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:33 -0400 Received: by mail-pg0-x243.google.com with SMTP id p8-v6so14245454pgq.10 for ; Mon, 04 Jun 2018 02:56:33 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.29 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qXkycAqMmbGcGFZKPe690vC4AXBOJPj/HAGZpJQqslU=; b=iI1npKXEiC8xUBD2ekhS57kr/ZgNRwdA5IBNN3Z41AYi9lm8qQ6bb09Xn26V2wyp2F 0akjbkm3qZqQieGokM63iscUCshWFTp9OfTzlnQ2rFijWR2gSteF6n38wv9x6RCr5T11 qtwTToEy44WrZn8xfHwJa6zgNv6LrImlvghqPmWvOzQ8qxodz+BLNwuOAxKBczvgBCv8 pfCmopGyRBpSFmMn5iByuRsrGZr9XVk97nSDhO+fe+CND8YRsdYNk9JTy7h8FSarC89o 2e9JHAhhNllidXX8nnaNwTlm+B6XDaG8yXc+XhnUCl6dx4jWd9FuUoa6QID8GFWDDvs3 2wOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=qXkycAqMmbGcGFZKPe690vC4AXBOJPj/HAGZpJQqslU=; b=P0hzhEIn0Y2K4/hnBQSt4m5NY7XhC+BIXnB9USq3tBLuhvUxjxSdvJWeraYSr9RlVB jJrwp99HMx6CJz6Ef+ZcUQOcSR3opwzFy9MimCxu2McPkPYatfuplPQ+OSE3LHAzx2sb TP7/5+q79RUr3HYxdDcF8AjMTrP2f0ht+AMZuD9++0d6O4tH/0afrbEsKDzRHVUvkRFN tQ4gociV43oWkct4RIrfCN2mX9ntmbtEaUKU9CfLBqXThK92lrYhLsPTf8UUnzP0iot+ Fo1BakArP7IZRGuvASKD4Y5KIf3re15uDbnYSC035al8kVev9JuEp8QABuxChyDqgckZ XVpQ== X-Gm-Message-State: ALKqPwe/DzvIO63Zy5kK0SMzUg2nu3itVNoxErhya7u5m+hEh51mWFqF Zg/JsgV1WisDrOUCiQxqbZI= X-Google-Smtp-Source: ADUXVKKGBHojH0VYIuqHTYOD8DEaNzhsKfS6mHtySWP4j3rVsQlpiat7TYME7Z2rerEwnPE6Jr3w/g== X-Received: by 2002:a63:770f:: with SMTP id s15-v6mr17086199pgc.30.1528106192142; Mon, 04 Jun 2018 02:56:32 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:17 +0800 Message-Id: <20180604095520.8563-10-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::243 Subject: [Qemu-devel] [PATCH 09/12] ring: introduce lockless ring buffer X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xiao Guangrong It's the simple lockless ring buffer implement which supports both single producer vs. single consumer and multiple producers vs. single consumer. Many lessons were learned from Linux Kernel's kfifo (1) and DPDK's rte_ring (2) before i wrote this implement. It corrects some bugs of memory barriers in kfifo and it is the simpler lockless version of rte_ring as currently multiple access is only allowed for producer. If has single producer vs. single consumer, it is the traditional fifo, If has multiple producers, it uses the algorithm as followings: For the producer, it uses two steps to update the ring: - first step, occupy the entry in the ring: retry: in =3D ring->in if (cmpxhg(&ring->in, in, in +1) !=3D in) goto retry; after that the entry pointed by ring->data[in] has been owned by the producer. assert(ring->data[in] =3D=3D NULL); Note, no other producer can touch this entry so that this entry should always be the initialized state. - second step, write the data to the entry: ring->data[in] =3D data; For the consumer, it first checks if there is available entry in the ring and fetches the entry from the ring: if (!ring_is_empty(ring)) entry =3D &ring[ring->out]; Note: the ring->out has not been updated so that the entry pointed by ring->out is completely owned by the consumer. Then it checks if the data is ready: retry: if (*entry =3D=3D NULL) goto retry; That means, the producer has updated the index but haven't written any data to it. Finally, it fetches the valid data out, set the entry to the initialized state and update ring->out to make the entry be usable to the producer: data =3D *entry; *entry =3D NULL; ring->out++; Memory barrier is omitted here, please refer to the comment in the code. (1) https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree= /include/linux/kfifo.h (2) http://dpdk.org/doc/api/rte__ring_8h.html Signed-off-by: Xiao Guangrong --- migration/ring.h | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 265 insertions(+) create mode 100644 migration/ring.h diff --git a/migration/ring.h b/migration/ring.h new file mode 100644 index 0000000000..da9b8bdcbb --- /dev/null +++ b/migration/ring.h @@ -0,0 +1,265 @@ +/* + * Ring Buffer + * + * Multiple producers and single consumer are supported with lock free. + * + * Copyright (c) 2018 Tencent Inc + * + * Authors: + * Xiao Guangrong + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef _RING__ +#define _RING__ + +#define CACHE_LINE 64 +#define cache_aligned __attribute__((__aligned__(CACHE_LINE))) + +#define RING_MULTI_PRODUCER 0x1 + +struct Ring { + unsigned int flags; + unsigned int size; + unsigned int mask; + + unsigned int in cache_aligned; + + unsigned int out cache_aligned; + + void *data[0] cache_aligned; +}; +typedef struct Ring Ring; + +/* + * allocate and initialize the ring + * + * @size: the number of element, it should be power of 2 + * @flags: set to RING_MULTI_PRODUCER if the ring has multiple producer, + * otherwise set it to 0, i,e. single producer and single consumer. + * + * return the ring. + */ +static inline Ring *ring_alloc(unsigned int size, unsigned int flags) +{ + Ring *ring; + + assert(is_power_of_2(size)); + + ring =3D g_malloc0(sizeof(*ring) + size * sizeof(void *)); + ring->size =3D size; + ring->mask =3D ring->size - 1; + ring->flags =3D flags; + return ring; +} + +static inline void ring_free(Ring *ring) +{ + g_free(ring); +} + +static inline bool __ring_is_empty(unsigned int in, unsigned int out) +{ + return in =3D=3D out; +} + +static inline bool ring_is_empty(Ring *ring) +{ + return ring->in =3D=3D ring->out; +} + +static inline unsigned int ring_len(unsigned int in, unsigned int out) +{ + return in - out; +} + +static inline bool +__ring_is_full(Ring *ring, unsigned int in, unsigned int out) +{ + return ring_len(in, out) > ring->mask; +} + +static inline bool ring_is_full(Ring *ring) +{ + return __ring_is_full(ring, ring->in, ring->out); +} + +static inline unsigned int ring_index(Ring *ring, unsigned int pos) +{ + return pos & ring->mask; +} + +static inline int __ring_put(Ring *ring, void *data) +{ + unsigned int index, out; + + out =3D atomic_load_acquire(&ring->out); + /* + * smp_mb() + * + * should read ring->out before updating the entry, see the comments in + * __ring_get(). + */ + + if (__ring_is_full(ring, ring->in, out)) { + return -ENOBUFS; + } + + index =3D ring_index(ring, ring->in); + + atomic_set(&ring->data[index], data); + + /* + * should make sure the entry is updated before increasing ring->in + * otherwise the consumer will get a entry but its content is useless. + */ + smp_wmb(); + atomic_set(&ring->in, ring->in + 1); + return 0; +} + +static inline void *__ring_get(Ring *ring) +{ + unsigned int index, in; + void *data; + + in =3D atomic_read(&ring->in); + + /* + * should read ring->in first to make sure the entry pointed by this + * index is available, see the comments in __ring_put(). + */ + smp_rmb(); + if (__ring_is_empty(in, ring->out)) { + return NULL; + } + + index =3D ring_index(ring, ring->out); + + data =3D atomic_read(&ring->data[index]); + + /* + * smp_mb() + * + * once the ring->out is updated the entry originally indicated by the + * the index is visible and usable to the producer so that we should + * make sure reading the entry out before updating ring->out to avoid + * the entry being overwritten by the producer. + */ + atomic_store_release(&ring->out, ring->out + 1); + + return data; +} + +static inline int ring_mp_put(Ring *ring, void *data) +{ + unsigned int index, in, in_next, out; + + do { + in =3D atomic_read(&ring->in); + out =3D atomic_read(&ring->out); + + if (__ring_is_full(ring, in, out)) { + if (atomic_read(&ring->in) =3D=3D in && + atomic_read(&ring->out) =3D=3D out) { + return -ENOBUFS; + } + + /* a entry has been fetched out, retry. */ + continue; + } + + in_next =3D in + 1; + } while (atomic_cmpxchg(&ring->in, in, in_next) !=3D in); + + index =3D ring_index(ring, in); + + /* + * smp_rmb() paired with the memory barrier of (A) in ring_mp_get() + * is implied in atomic_cmpxchg() as we should read ring->out first + * before fetching the entry, otherwise this assert will fail. + */ + assert(!atomic_read(&ring->data[index])); + + /* + * smp_mb() paired with the memory barrier of (B) in ring_mp_get() is + * implied in atomic_cmpxchg(), that is needed here as we should read + * ring->out before updating the entry, it is the same as we did in + * __ring_put(). + * + * smp_wmb() paired with the memory barrier of (C) in ring_mp_get() + * is implied in atomic_cmpxchg(), that is needed as we should increase + * ring->in before updating the entry. + */ + atomic_set(&ring->data[index], data); + + return 0; +} + +static inline void *ring_mp_get(Ring *ring) +{ + unsigned int index, in; + void *data; + + do { + in =3D atomic_read(&ring->in); + + /* + * (C) should read ring->in first to make sure the entry pointed b= y this + * index is available + */ + smp_rmb(); + + if (!__ring_is_empty(in, ring->out)) { + break; + } + + if (atomic_read(&ring->in) =3D=3D in) { + return NULL; + } + /* new entry has been added in, retry. */ + } while (1); + + index =3D ring_index(ring, ring->out); + + do { + data =3D atomic_read(&ring->data[index]); + if (data) { + break; + } + /* the producer is updating the entry, retry */ + cpu_relax(); + } while (1); + + atomic_set(&ring->data[index], NULL); + + /* + * (B) smp_mb() is needed as we should read the entry out before + * updating ring->out as we did in __ring_get(). + * + * (A) smp_wmb() is needed as we should make the entry be NULL before + * updating ring->out (which will make the entry be visible and usable= ). + */ + atomic_store_release(&ring->out, ring->out + 1); + + return data; +} + +static inline int ring_put(Ring *ring, void *data) +{ + if (ring->flags & RING_MULTI_PRODUCER) { + return ring_mp_put(ring, data); + } + return __ring_put(ring, data); +} + +static inline void *ring_get(Ring *ring) +{ + if (ring->flags & RING_MULTI_PRODUCER) { + return ring_mp_get(ring); + } + return __ring_get(ring); +} +#endif --=20 2.14.4 From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528106944663164.2075405675829; Mon, 4 Jun 2018 03:09:04 -0700 (PDT) Received: from localhost ([::1]:38677 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmQ2-0000w2-5R for importer@patchew.org; Mon, 04 Jun 2018 06:08:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46608) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmEB-0007py-0B for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmE8-0001Jx-QH for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:39 -0400 Received: from mail-pl0-x234.google.com ([2607:f8b0:400e:c01::234]:36248) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmE8-0001JI-GO for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:36 -0400 Received: by mail-pl0-x234.google.com with SMTP id v24-v6so19393304plo.3 for ; Mon, 04 Jun 2018 02:56:36 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.32 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NNnWBR7x+SYwivM69cBBfAsvoPEciR2hs8vCIDCdFh4=; b=QQFIDjRGQ3cam4QjxyhLCtVEcgoa0eskCC3kB+lcl2WOia4j4kaQKRnn6jiombeMbU nc5f6st7IgCYwQ3UhC8mCGISLZcj7y3BcWRLj4ul8bozXc8xy0J6Pv6w5NdIknWbmCtu 3dLNyE7EiLg/XiZLoUaLU7W/e0+T9K2DWieg5S4A83vQAIMdAYXg7wMvZ76/JzMY3nWp Kumh3mInQ4tk6g3pLbDWMBVMZxRX3J2qbLQOYpTJ35Pnok8Csqv+wbikwV+4aylm77uE YLoU0IP+LU//GFlXAR7QN+SCjaO5/IGN68tRXR3SAjNFKCDyM/cIftdtip14YserS1/i WdHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NNnWBR7x+SYwivM69cBBfAsvoPEciR2hs8vCIDCdFh4=; b=gJtM6Cymzx+m+42Fieb45QUYIsyEwGyMr01scmvWSKm3hzUgy+GZRODLZMHzFaRix+ 5r/pxZsQ28zvBIPua4VnWnVmf+lVQ6Zoz+BTz8mBllpMAIjEg6yirByzSxfvxrbH0ljA 21znnBctIEAgfhYl2H405Ksejvyuuxh+uC6XJazq4RymAz5PrlApgyj9yAGITcjAhREO LU6kbTsIQ+ZUfn0nmVguJE6FxPLtI+V4qDTHMhOugbc2HP/xatg8AS2KAoUQzrO8WzyC LpY6sdaZKRxZQkgdZ74TW7tE9Y/3wZhvUEkycEE5WctImcclbYNur009tHGZUHEfeKy/ hXfA== X-Gm-Message-State: APt69E1uQ++XRceDJsSC9uOsT68qPho8n0zLO98bcsoRIszCs+Fz6HHY OnifE3VbypFxEQ6TyVNiZHo= X-Google-Smtp-Source: ADUXVKJHYbdxnOilfiKN86byTrSubTApOWqwWxOhiA7gIPofkvK5K+ZW+7O0jFtX5L0Kz2CHkOQsug== X-Received: by 2002:a17:902:9b92:: with SMTP id y18-v6mr4408934plp.57.1528106195379; Mon, 04 Jun 2018 02:56:35 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:18 +0800 Message-Id: <20180604095520.8563-11-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::234 Subject: [Qemu-devel] [PATCH 10/12] migration: introduce lockless multithreads model X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 From: Xiao Guangrong Current implementation of compression and decompression are very hard to be enabled on productions. We noticed that too many wait-wakes go to kernel space and CPU usages are very low even if the system is really free The reasons are: 1) there are two many locks used to do synchronous=EF=BC=8Cthere =E3=80=80=E3=80=80is a global lock and each single thread has its own lock, =E3=80=80=E3=80=80migration thread and work threads need to go to sleep if =E3=80=80=E3=80=80these locks are busy 2) migration thread separately submits request to the thread however, only one request can be pended, that means, the thread has to go to sleep after finishing the request To make it work better, we introduce a new multithread model, the user, currently it is the migration thread, submits request to each thread with round-robin manner, the thread has its own ring whose capacity is 4 and puts the result to a global ring which is lockless for multiple producers, the user fetches result out from the global ring and do remaining operations for the request, e.g, posting the compressed data out for migration on the source QEMU Performance Result: The test was based on top of the patch: ring: introduce lockless ring buffer that means, previous optimizations are used for both of original case and applying the new multithread model We tested live migration on two hosts: Intel(R) Xeon(R) Gold 6142 CPU @ 2.60GHz * 64 + 256G memory to migration a VM between each other, which has 16 vCPUs and 60G memory, during the migration, multiple threads are repeatedly writing the memory in the VM We used 16 threads on the destination to decompress the data and on the source, we tried 8 threads and 16 threads to compress the data --- Before our work --- migration can not be finished for both 8 threads and 16 threads. The data is as followings: Use 8 threads to compress: - on the source: migration thread compress-threads CPU usage 70% some use 36%, others are very low ~20% - on the destination: main thread decompress-threads CPU usage 100% some use ~40%, other are very low ~2% Migration status (CAN NOT FINISH): info migrate globals: store-global-state: on only-migratable: off send-configuration: on send-section-footer: on capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks:= off compress: on events: off postcopy-ram: off x-colo: off release-ram: of= f block: off return-path: off pause-before-switchover: off x-multifd: off d= irty-bitmaps: off postcopy-blocktime: off Migration status: active total time: 1019540 milliseconds expected downtime: 2263 milliseconds setup: 218 milliseconds transferred ram: 252419995 kbytes throughput: 2469.45 mbps remaining ram: 15611332 kbytes total ram: 62931784 kbytes duplicate: 915323 pages skipped: 0 pages normal: 59673047 pages normal bytes: 238692188 kbytes dirty sync count: 28 page size: 4 kbytes dirty pages rate: 170551 pages compression pages: 121309323 pages compression busy: 60588337 compression busy rate: 0.36 compression reduced size: 484281967178 compression rate: 0.97 Use 16 threads to compress: - on the source: migration thread compress-threads CPU usage 96% some use 45%, others are very low ~6% - on the destination: main thread decompress-threads CPU usage 96% some use 58%, other are very low ~10% Migration status (CAN NOT FINISH): info migrate globals: store-global-state: on only-migratable: off send-configuration: on send-section-footer: on capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks:= off compress: on events: off postcopy-ram: off x-colo: off release-ram: of= f block: off return-path: off pause-before-switchover: off x-multifd: off d= irty-bitmaps: off postcopy-blocktime: off Migration status: active total time: 1189221 milliseconds expected downtime: 6824 milliseconds setup: 220 milliseconds transferred ram: 90620052 kbytes throughput: 840.41 mbps remaining ram: 3678760 kbytes total ram: 62931784 kbytes duplicate: 195893 pages skipped: 0 pages normal: 17290715 pages normal bytes: 69162860 kbytes dirty sync count: 33 page size: 4 kbytes dirty pages rate: 175039 pages compression pages: 186739419 pages compression busy: 17486568 compression busy rate: 0.09 compression reduced size: 744546683892 compression rate: 0.97 --- After our work --- Migration can be finished quickly for both 8 threads and 16 threads. The data is as followings: Use 8 threads to compress: - on the source: migration thread compress-threads CPU usage 30% 30% (all threads have same CPU usage) - on the destination: main thread decompress-threads CPU usage 100% 50% (all threads have same CPU usage) Migration status (finished in 219467 ms): info migrate globals: store-global-state: on only-migratable: off send-configuration: on send-section-footer: on capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks:= off compress: on events: off postcopy-ram: off x-colo: off release-ram: of= f block: off return-path: off pause-before-switchover: off x-multifd: off d= irty-bitmaps: off postcopy-blocktime: off Migration status: completed total time: 219467 milliseconds downtime: 115 milliseconds setup: 222 milliseconds transferred ram: 88510173 kbytes throughput: 3303.81 mbps remaining ram: 0 kbytes total ram: 62931784 kbytes duplicate: 2211775 pages skipped: 0 pages normal: 21166222 pages normal bytes: 84664888 kbytes dirty sync count: 15 page size: 4 kbytes compression pages: 32045857 pages compression busy: 23377968 compression busy rate: 0.34 compression reduced size: 127767894329 compression rate: 0.97 Use 16 threads to compress: - on the source: migration thread compress-threads CPU usage 60% 60% (all threads have same CPU usage) - on the destination: main thread decompress-threads CPU usage 100% 75% (all threads have same CPU usage) Migration status (finished in 64118 ms): info migrate globals: store-global-state: on only-migratable: off send-configuration: on send-section-footer: on capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks:= off compress: on events: off postcopy-ram: off x-colo: off release-ram: of= f block: off return-path: off pause-before-switchover: off x-multifd: off d= irty-bitmaps: off postcopy-blocktime: off Migration status: completed total time: 64118 milliseconds downtime: 29 milliseconds setup: 223 milliseconds transferred ram: 13345135 kbytes throughput: 1705.10 mbps remaining ram: 0 kbytes total ram: 62931784 kbytes duplicate: 574921 pages skipped: 0 pages normal: 2570281 pages normal bytes: 10281124 kbytes dirty sync count: 9 page size: 4 kbytes compression pages: 28007024 pages compression busy: 3145182 compression busy rate: 0.08 compression reduced size: 111829024985 compression rate: 0.97 Signed-off-by: Xiao Guangrong --- migration/Makefile.objs | 1 + migration/threads.c | 265 ++++++++++++++++++++++++++++++++++++++++++++= ++++ migration/threads.h | 116 +++++++++++++++++++++ 3 files changed, 382 insertions(+) create mode 100644 migration/threads.c create mode 100644 migration/threads.h diff --git a/migration/Makefile.objs b/migration/Makefile.objs index c83ec47ba8..bdb61a7983 100644 --- a/migration/Makefile.objs +++ b/migration/Makefile.objs @@ -7,6 +7,7 @@ common-obj-y +=3D qemu-file-channel.o common-obj-y +=3D xbzrle.o postcopy-ram.o common-obj-y +=3D qjson.o common-obj-y +=3D block-dirty-bitmap.o +common-obj-y +=3D threads.o =20 common-obj-$(CONFIG_RDMA) +=3D rdma.o =20 diff --git a/migration/threads.c b/migration/threads.c new file mode 100644 index 0000000000..eecd3229b7 --- /dev/null +++ b/migration/threads.c @@ -0,0 +1,265 @@ +#include "threads.h" + +/* retry to see if there is avilable request before actually go to wait. */ +#define BUSY_WAIT_COUNT 1000 + +static void *thread_run(void *opaque) +{ + ThreadLocal *self_data =3D (ThreadLocal *)opaque; + Threads *threads =3D self_data->threads; + void (*handler)(ThreadRequest *data) =3D threads->thread_request_handl= er; + ThreadRequest *request; + int count, ret; + + for ( ; !atomic_read(&self_data->quit); ) { + qemu_event_reset(&self_data->ev); + + count =3D 0; + while ((request =3D ring_get(self_data->request_ring)) || + count < BUSY_WAIT_COUNT) { + /* + * wait some while before go to sleep so that the user + * needn't go to kernel space to wake up the consumer + * threads. + * + * That will waste some CPU resource indeed however it + * can significantly improve the case that the request + * will be available soon. + */ + if (!request) { + cpu_relax(); + count++; + continue; + } + count =3D 0; + + handler(request); + + do { + ret =3D ring_put(threads->request_done_ring, request); + /* + * request_done_ring has enough room to contain all + * requests, however, theoretically, it still can be + * fail if the ring's indexes are overflow that would + * happen if there is more than 2^32 requests are + * handled between two calls of threads_wait_done(). + * So we do retry to make the code more robust. + * + * It is unlikely the case for migration as the block's + * memory is unlikely more than 16T (2^32 pages) memory. + */ + if (ret) { + fprintf(stderr, + "Potential BUG if it is triggered by migration= .\n"); + } + } while (ret); + } + + qemu_event_wait(&self_data->ev); + } + + return NULL; +} + +static void add_free_request(Threads *threads, ThreadRequest *request) +{ + QSLIST_INSERT_HEAD(&threads->free_requests, request, node); + threads->free_requests_nr++; +} + +static ThreadRequest *get_and_remove_first_free_request(Threads *threads) +{ + ThreadRequest *request; + + if (QSLIST_EMPTY(&threads->free_requests)) { + return NULL; + } + + request =3D QSLIST_FIRST(&threads->free_requests); + QSLIST_REMOVE_HEAD(&threads->free_requests, node); + threads->free_requests_nr--; + return request; +} + +static void uninit_requests(Threads *threads, int free_nr) +{ + ThreadRequest *request; + + /* + * all requests should be released to the list if threads are being + * destroyed, i,e. should call threads_wait_done() first. + */ + assert(threads->free_requests_nr =3D=3D free_nr); + + while ((request =3D get_and_remove_first_free_request(threads))) { + threads->thread_request_uninit(request); + } + + assert(ring_is_empty(threads->request_done_ring)); + ring_free(threads->request_done_ring); +} + +static int init_requests(Threads *threads) +{ + ThreadRequest *request; + unsigned int done_ring_size =3D pow2roundup32(threads->total_requests); + int i, free_nr =3D 0; + + threads->request_done_ring =3D ring_alloc(done_ring_size, + RING_MULTI_PRODUCER); + + QSLIST_INIT(&threads->free_requests); + for (i =3D 0; i < threads->total_requests; i++) { + request =3D threads->thread_request_init(); + if (!request) { + goto cleanup; + } + + free_nr++; + add_free_request(threads, request); + } + return 0; + +cleanup: + uninit_requests(threads, free_nr); + return -1; +} + +static void uninit_thread_data(Threads *threads) +{ + ThreadLocal *thread_local =3D threads->per_thread_data; + int i; + + for (i =3D 0; i < threads->threads_nr; i++) { + thread_local[i].quit =3D true; + qemu_event_set(&thread_local[i].ev); + qemu_thread_join(&thread_local[i].thread); + qemu_event_destroy(&thread_local[i].ev); + assert(ring_is_empty(thread_local[i].request_ring)); + ring_free(thread_local[i].request_ring); + } +} + +static void init_thread_data(Threads *threads) +{ + ThreadLocal *thread_local =3D threads->per_thread_data; + char *name; + int i; + + for (i =3D 0; i < threads->threads_nr; i++) { + qemu_event_init(&thread_local[i].ev, false); + + thread_local[i].threads =3D threads; + thread_local[i].self =3D i; + thread_local[i].request_ring =3D ring_alloc(threads->thread_ring_s= ize, 0); + name =3D g_strdup_printf("%s/%d", threads->name, thread_local[i].s= elf); + qemu_thread_create(&thread_local[i].thread, name, + thread_run, &thread_local[i], QEMU_THREAD_JOINA= BLE); + g_free(name); + } +} + +/* the size of thread local request ring */ +#define THREAD_REQ_RING_SIZE 4 + +Threads *threads_create(unsigned int threads_nr, const char *name, + ThreadRequest *(*thread_request_init)(void), + void (*thread_request_uninit)(ThreadRequest *reque= st), + void (*thread_request_handler)(ThreadRequest *requ= est), + void (*thread_request_done)(ThreadRequest *request= )) +{ + Threads *threads; + int ret; + + threads =3D g_malloc0(sizeof(*threads) + threads_nr * sizeof(ThreadLoc= al)); + threads->threads_nr =3D threads_nr; + threads->thread_ring_size =3D THREAD_REQ_RING_SIZE; + threads->total_requests =3D threads->thread_ring_size * threads_nr; + + threads->name =3D name; + threads->thread_request_init =3D thread_request_init; + threads->thread_request_uninit =3D thread_request_uninit; + threads->thread_request_handler =3D thread_request_handler; + threads->thread_request_done =3D thread_request_done; + + ret =3D init_requests(threads); + if (ret) { + g_free(threads); + return NULL; + } + + init_thread_data(threads); + return threads; +} + +void threads_destroy(Threads *threads) +{ + uninit_thread_data(threads); + uninit_requests(threads, threads->total_requests); + g_free(threads); +} + +ThreadRequest *threads_submit_request_prepare(Threads *threads) +{ + ThreadRequest *request; + unsigned int index; + + index =3D threads->current_thread_index % threads->threads_nr; + + /* the thread is busy */ + if (ring_is_full(threads->per_thread_data[index].request_ring)) { + return NULL; + } + + /* try to get the request from the list */ + request =3D get_and_remove_first_free_request(threads); + if (request) { + goto got_request; + } + + /* get the request already been handled by the threads */ + request =3D ring_get(threads->request_done_ring); + if (request) { + threads->thread_request_done(request); + goto got_request; + } + return NULL; + +got_request: + threads->current_thread_index++; + request->thread_index =3D index; + return request; +} + +void threads_submit_request_commit(Threads *threads, ThreadRequest *reques= t) +{ + int ret, index =3D request->thread_index; + ThreadLocal *thread_local =3D &threads->per_thread_data[index]; + + ret =3D ring_put(thread_local->request_ring, request); + + /* + * we have detected that the thread's ring is not full in + * threads_submit_request_prepare(), there should be free + * room in the ring + */ + assert(!ret); + /* new request arrived, notify the thread */ + qemu_event_set(&thread_local->ev); +} + +void threads_wait_done(Threads *threads) +{ + ThreadRequest *request; + +retry: + while ((request =3D ring_get(threads->request_done_ring))) { + threads->thread_request_done(request); + add_free_request(threads, request); + } + + if (threads->free_requests_nr !=3D threads->total_requests) { + cpu_relax(); + goto retry; + } +} diff --git a/migration/threads.h b/migration/threads.h new file mode 100644 index 0000000000..eced913065 --- /dev/null +++ b/migration/threads.h @@ -0,0 +1,116 @@ +#ifndef QEMU_MIGRATION_THREAD_H +#define QEMU_MIGRATION_THREAD_H + +/* + * Multithreads abstraction + * + * This is the abstraction layer for multithreads management which is + * used to speed up migration. + * + * Note: currently only one producer is allowed. + * + * Copyright(C) 2018 Tencent Corporation. + * + * Author: + * Xiao Guangrong + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or l= ater. + * See the COPYING.LIB file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/boards.h" + +#include "ring.h" + +/* + * the request representation which contains the internally used mete data, + * it can be embedded to user's self-defined data struct and the user can + * use container_of() to get the self-defined data + */ +struct ThreadRequest { + QSLIST_ENTRY(ThreadRequest) node; + unsigned int thread_index; +}; +typedef struct ThreadRequest ThreadRequest; + +struct Threads; + +struct ThreadLocal { + QemuThread thread; + + /* the event used to wake up the thread */ + QemuEvent ev; + + struct Threads *threads; + + /* local request ring which is filled by the user */ + Ring *request_ring; + + /* the index of the thread */ + int self; + + /* thread is useless and needs to exit */ + bool quit; +}; +typedef struct ThreadLocal ThreadLocal; + +/* + * the main data struct represents multithreads which is shared by + * all threads + */ +struct Threads { + const char *name; + unsigned int threads_nr; + /* the request is pushed to the thread with round-robin manner */ + unsigned int current_thread_index; + + int thread_ring_size; + int total_requests; + + /* the request is pre-allocated and linked in the list */ + int free_requests_nr; + QSLIST_HEAD(, ThreadRequest) free_requests; + + /* the constructor of request */ + ThreadRequest *(*thread_request_init)(void); + /* the destructor of request */ + void (*thread_request_uninit)(ThreadRequest *request); + /* the handler of the request which is called in the thread */ + void (*thread_request_handler)(ThreadRequest *request); + /* + * the handler to process the result which is called in the + * user's context + */ + void (*thread_request_done)(ThreadRequest *request); + + /* the thread push the result to this ring so it has multiple producer= s */ + Ring *request_done_ring; + + ThreadLocal per_thread_data[0]; +}; +typedef struct Threads Threads; + +Threads *threads_create(unsigned int threads_nr, const char *name, + ThreadRequest *(*thread_request_init)(void), + void (*thread_request_uninit)(ThreadRequest *reque= st), + void (*thread_request_handler)(ThreadRequest *requ= est), + void (*thread_request_done)(ThreadRequest *request= )); +void threads_destroy(Threads *threads); + +/* + * find a free request and associate it with a free thread. + * If no request or no thread is free, return NULL + */ +ThreadRequest *threads_submit_request_prepare(Threads *threads); +/* + * push the request to its thread's local ring and notify the thread + */ +void threads_submit_request_commit(Threads *threads, ThreadRequest *reques= t); + +/* + * wait all threads to complete the request filled in their local rings + * to make sure there is no previous request exists. + */ +void threads_wait_done(Threads *threads); +#endif --=20 2.14.4 From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528106840903434.68638696072355; Mon, 4 Jun 2018 03:07:20 -0700 (PDT) Received: from localhost ([::1]:38668 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmOV-00086b-VZ for importer@patchew.org; Mon, 04 Jun 2018 06:07:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46621) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmED-0007sN-Op for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmEB-0001L1-Uk for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:41 -0400 Received: from mail-pl0-x236.google.com ([2607:f8b0:400e:c01::236]:34075) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmEB-0001Ke-Lr for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:39 -0400 Received: by mail-pl0-x236.google.com with SMTP id g20-v6so1601618plq.1 for ; Mon, 04 Jun 2018 02:56:39 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.35 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qV513m9FAxyxQZDJwLFh1LA9QYIeomTdqUJmFxHv6zc=; b=Qc7ue+c/SjxUQNNYmr3xP13urZrXbdFXZ98txzgFa4pgzy87j1T4VTYm9uPN+Frw7/ Zl2+mIk3rS/kKeqko7KkJYahAuWjaKXanS5GyAbkkuilY3K5oW5rAEIpUCekFkFNGKqT ZHMrCsSpgrc+F8ai+QRSqRm0Da+LtSQ5to9sK5g1x819XTNL+tSa/pZ+zzvFeOP2Kzhv nNQRM+jMk3xSmw6AFU1PRXkbEW87SUzQnrfwVps3LiTpuge70JidHYAxZes28ZAOKJy/ hzQxP+XUFYEjrzGWQEgPY5NbmNOT3mc8wWSFEWF0A+jwgGXU9aaB9vmCGFQmQw0JIHw0 fFjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=qV513m9FAxyxQZDJwLFh1LA9QYIeomTdqUJmFxHv6zc=; b=s+JCrTXQsDp7VWMBaQqocRHJWEZw9GeBrC2YPGJilAv7P76JzBd1Dv6u326v2pDsei EQWFvVCOS+TqAR+eXbqO4PfMVS4UyOAtQTzczanSR5V0gfDB+abDNmHc1q1LwFQboYJ9 /SMEYrd/D46H0SPXmO3wCuMkfUwvfMKTUwj3lX96mTN7ITg5ga9yxZWPmd/xWEitqZo2 55yo/rh4YHmfPxdrpZ7rZLIRK8b+CtwAOnLrujTuzJM/yO+8TKlxLG76DOTEWjZ4YyEI TkW9hL2ce0hbjWFuKRgAds8mTPFf33k6Kh/gJ8r047GRyhbYeFQv6bLUViZMZ/mCCXIR r+ZQ== X-Gm-Message-State: ALKqPwfc/azKhL5goRB3gpBhfwbSe4/Ywl9We6QP/OyfapUIrhgyw9+j AZE4OTHNrfJGrP8NzeZJDHk= X-Google-Smtp-Source: ADUXVKJq8BD6pFXLis8Vyepv3yU+Y4b4CaZqge8XkksD5bpCkgAJ7kfI+wJCJxKRgheRFNn9KY7W4g== X-Received: by 2002:a17:902:a508:: with SMTP id s8-v6mr12606816plq.223.1528106198654; Mon, 04 Jun 2018 02:56:38 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:19 +0800 Message-Id: <20180604095520.8563-12-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::236 Subject: [Qemu-devel] [PATCH 11/12] migration: use lockless Multithread model for compression X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xiao Guangrong Adapt the compression code to the lockless multithread model Signed-off-by: Xiao Guangrong --- migration/ram.c | 412 ++++++++++++++++++++++------------------------------= ---- 1 file changed, 161 insertions(+), 251 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index 0a38c1c61e..58ecf5caa0 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -55,6 +55,7 @@ #include "sysemu/sysemu.h" #include "qemu/uuid.h" #include "savevm.h" +#include "migration/threads.h" =20 /***********************************************************/ /* ram save/restore */ @@ -340,21 +341,6 @@ typedef struct PageSearchStatus PageSearchStatus; =20 CompressionStats compression_counters; =20 -struct CompressParam { - bool done; - bool quit; - QEMUFile *file; - QemuMutex mutex; - QemuCond cond; - RAMBlock *block; - ram_addr_t offset; - - /* internally used fields */ - z_stream stream; - uint8_t *originbuf; -}; -typedef struct CompressParam CompressParam; - struct DecompressParam { bool done; bool quit; @@ -367,15 +353,6 @@ struct DecompressParam { }; typedef struct DecompressParam DecompressParam; =20 -static CompressParam *comp_param; -static QemuThread *compress_threads; -/* comp_done_cond is used to wake up the migration thread when - * one of the compression threads has finished the compression. - * comp_done_lock is used to co-work with comp_done_cond. - */ -static QemuMutex comp_done_lock; -static QemuCond comp_done_cond; -/* The empty QEMUFileOps will be used by file in CompressParam */ static const QEMUFileOps empty_ops =3D { }; =20 static QEMUFile *decomp_file; @@ -384,131 +361,6 @@ static QemuThread *decompress_threads; static QemuMutex decomp_done_lock; static QemuCond decomp_done_cond; =20 -static int do_compress_ram_page(QEMUFile *f, z_stream *stream, RAMBlock *b= lock, - ram_addr_t offset, uint8_t *source_buf); - -static void *do_data_compress(void *opaque) -{ - CompressParam *param =3D opaque; - RAMBlock *block; - ram_addr_t offset; - - qemu_mutex_lock(¶m->mutex); - while (!param->quit) { - if (param->block) { - block =3D param->block; - offset =3D param->offset; - param->block =3D NULL; - qemu_mutex_unlock(¶m->mutex); - - do_compress_ram_page(param->file, ¶m->stream, block, offse= t, - param->originbuf); - - qemu_mutex_lock(&comp_done_lock); - param->done =3D true; - qemu_cond_signal(&comp_done_cond); - qemu_mutex_unlock(&comp_done_lock); - - qemu_mutex_lock(¶m->mutex); - } else { - qemu_cond_wait(¶m->cond, ¶m->mutex); - } - } - qemu_mutex_unlock(¶m->mutex); - - return NULL; -} - -static inline void terminate_compression_threads(void) -{ - int idx, thread_count; - - thread_count =3D migrate_compress_threads(); - - for (idx =3D 0; idx < thread_count; idx++) { - qemu_mutex_lock(&comp_param[idx].mutex); - comp_param[idx].quit =3D true; - qemu_cond_signal(&comp_param[idx].cond); - qemu_mutex_unlock(&comp_param[idx].mutex); - } -} - -static void compress_threads_save_cleanup(void) -{ - int i, thread_count; - - if (!migrate_use_compression()) { - return; - } - terminate_compression_threads(); - thread_count =3D migrate_compress_threads(); - for (i =3D 0; i < thread_count; i++) { - /* - * we use it as a indicator which shows if the thread is - * properly init'd or not - */ - if (!comp_param[i].file) { - break; - } - qemu_thread_join(compress_threads + i); - qemu_mutex_destroy(&comp_param[i].mutex); - qemu_cond_destroy(&comp_param[i].cond); - deflateEnd(&comp_param[i].stream); - g_free(comp_param[i].originbuf); - qemu_fclose(comp_param[i].file); - comp_param[i].file =3D NULL; - } - qemu_mutex_destroy(&comp_done_lock); - qemu_cond_destroy(&comp_done_cond); - g_free(compress_threads); - g_free(comp_param); - compress_threads =3D NULL; - comp_param =3D NULL; -} - -static int compress_threads_save_setup(void) -{ - int i, thread_count; - - if (!migrate_use_compression()) { - return 0; - } - thread_count =3D migrate_compress_threads(); - compress_threads =3D g_new0(QemuThread, thread_count); - comp_param =3D g_new0(CompressParam, thread_count); - qemu_cond_init(&comp_done_cond); - qemu_mutex_init(&comp_done_lock); - for (i =3D 0; i < thread_count; i++) { - comp_param[i].originbuf =3D g_try_malloc(TARGET_PAGE_SIZE); - if (!comp_param[i].originbuf) { - goto exit; - } - - if (deflateInit(&comp_param[i].stream, - migrate_compress_level()) !=3D Z_OK) { - g_free(comp_param[i].originbuf); - goto exit; - } - - /* comp_param[i].file is just used as a dummy buffer to save data, - * set its ops to empty. - */ - comp_param[i].file =3D qemu_fopen_ops(NULL, &empty_ops); - comp_param[i].done =3D true; - comp_param[i].quit =3D false; - qemu_mutex_init(&comp_param[i].mutex); - qemu_cond_init(&comp_param[i].cond); - qemu_thread_create(compress_threads + i, "compress", - do_data_compress, comp_param + i, - QEMU_THREAD_JOINABLE); - } - return 0; - -exit: - compress_threads_save_cleanup(); - return -1; -} - /* Multiple fd's */ =20 #define MULTIFD_MAGIC 0x11223344U @@ -965,6 +817,151 @@ static void mig_throttle_guest_down(void) } } =20 +static void ram_release_pages(const char *rbname, uint64_t offset, int pag= es) +{ + if (!migrate_release_ram() || !migration_in_postcopy()) { + return; + } + + ram_discard_range(rbname, offset, pages << TARGET_PAGE_BITS); +} + +static int do_compress_ram_page(QEMUFile *f, z_stream *stream, RAMBlock *b= lock, + ram_addr_t offset, uint8_t *source_buf) +{ + RAMState *rs =3D ram_state; + int bytes_sent, blen; + uint8_t *p =3D block->host + (offset & TARGET_PAGE_MASK); + + bytes_sent =3D save_page_header(rs, f, block, offset | + RAM_SAVE_FLAG_COMPRESS_PAGE); + + /* + * copy it to a internal buffer to avoid it being modified by VM + * so that we can catch up the error during compression and + * decompression + */ + memcpy(source_buf, p, TARGET_PAGE_SIZE); + blen =3D qemu_put_compression_data(f, stream, source_buf, TARGET_PAGE_= SIZE); + if (blen < 0) { + bytes_sent =3D 0; + qemu_file_set_error(migrate_get_current()->to_dst_file, blen); + error_report("compressed data failed!"); + } else { + bytes_sent +=3D blen; + ram_release_pages(block->idstr, offset & TARGET_PAGE_MASK, 1); + } + + return bytes_sent; +} + +struct CompressData { + /* filled by migration thread.*/ + RAMBlock *block; + ram_addr_t offset; + + /* filled by compress thread. */ + QEMUFile *file; + z_stream stream; + uint8_t *originbuf; + + ThreadRequest request; +}; +typedef struct CompressData CompressData; + +static ThreadRequest *compress_thread_data_init(void) +{ + CompressData *cd =3D g_new0(CompressData, 1); + + cd->originbuf =3D g_try_malloc(TARGET_PAGE_SIZE); + if (!cd->originbuf) { + goto exit; + } + + if (deflateInit(&cd->stream, migrate_compress_level()) !=3D Z_OK) { + g_free(cd->originbuf); + goto exit; + } + + cd->file =3D qemu_fopen_ops(NULL, &empty_ops); + return &cd->request; + +exit: + g_free(cd); + return NULL; +} + +static void compress_thread_data_fini(ThreadRequest *request) +{ + CompressData *cd =3D container_of(request, CompressData, request); + + qemu_fclose(cd->file); + deflateEnd(&cd->stream); + g_free(cd->originbuf); + g_free(cd); +} + +static void compress_thread_data_handler(ThreadRequest *request) +{ + CompressData *cd =3D container_of(request, CompressData, request); + + /* + * if compression fails, it will be indicated by + * migrate_get_current()->to_dst_file. + */ + do_compress_ram_page(cd->file, &cd->stream, cd->block, cd->offset, + cd->originbuf); +} + +static void compress_thread_data_done(ThreadRequest *request) +{ + CompressData *cd =3D container_of(request, CompressData, request); + RAMState *rs =3D ram_state; + int bytes_xmit; + + bytes_xmit =3D qemu_put_qemu_file(rs->f, cd->file); + /* 8 means a header with RAM_SAVE_FLAG_CONTINUE */ + compression_counters.reduced_size +=3D TARGET_PAGE_SIZE - bytes_xmit += 8; + compression_counters.pages++; + ram_counters.transferred +=3D bytes_xmit; +} + +static Threads *compress_threads; + +static void flush_compressed_data(void) +{ + if (!migrate_use_compression()) { + return; + } + + threads_wait_done(compress_threads); +} + +static void compress_threads_save_cleanup(void) +{ + if (!compress_threads) { + return; + } + + threads_destroy(compress_threads); + compress_threads =3D NULL; +} + +static int compress_threads_save_setup(void) +{ + if (!migrate_use_compression()) { + return 0; + } + + compress_threads =3D threads_create(migrate_compress_threads(), + "compress", + compress_thread_data_init, + compress_thread_data_fini, + compress_thread_data_handler, + compress_thread_data_done); + return compress_threads ? 0 : -1; +} + /** * xbzrle_cache_zero_page: insert a zero page in the XBZRLE cache * @@ -1268,15 +1265,6 @@ static int save_zero_page(RAMState *rs, RAMBlock *bl= ock, ram_addr_t offset) return pages; } =20 -static void ram_release_pages(const char *rbname, uint64_t offset, int pag= es) -{ - if (!migrate_release_ram() || !migration_in_postcopy()) { - return; - } - - ram_discard_range(rbname, offset, pages << TARGET_PAGE_BITS); -} - /* * @pages: the number of pages written by the control path, * < 0 - error @@ -1391,99 +1379,22 @@ static int ram_save_page(RAMState *rs, PageSearchSt= atus *pss, bool last_stage) return pages; } =20 -static int do_compress_ram_page(QEMUFile *f, z_stream *stream, RAMBlock *b= lock, - ram_addr_t offset, uint8_t *source_buf) -{ - RAMState *rs =3D ram_state; - int bytes_sent, blen; - uint8_t *p =3D block->host + (offset & TARGET_PAGE_MASK); - - bytes_sent =3D save_page_header(rs, f, block, offset | - RAM_SAVE_FLAG_COMPRESS_PAGE); - - /* - * copy it to a internal buffer to avoid it being modified by VM - * so that we can catch up the error during compression and - * decompression - */ - memcpy(source_buf, p, TARGET_PAGE_SIZE); - blen =3D qemu_put_compression_data(f, stream, source_buf, TARGET_PAGE_= SIZE); - if (blen < 0) { - bytes_sent =3D 0; - qemu_file_set_error(migrate_get_current()->to_dst_file, blen); - error_report("compressed data failed!"); - } else { - bytes_sent +=3D blen; - ram_release_pages(block->idstr, offset & TARGET_PAGE_MASK, 1); - } - - return bytes_sent; -} - -static void flush_compressed_data(RAMState *rs) -{ - int idx, len, thread_count; - - if (!migrate_use_compression()) { - return; - } - thread_count =3D migrate_compress_threads(); - - qemu_mutex_lock(&comp_done_lock); - for (idx =3D 0; idx < thread_count; idx++) { - while (!comp_param[idx].done) { - qemu_cond_wait(&comp_done_cond, &comp_done_lock); - } - } - qemu_mutex_unlock(&comp_done_lock); - - for (idx =3D 0; idx < thread_count; idx++) { - qemu_mutex_lock(&comp_param[idx].mutex); - if (!comp_param[idx].quit) { - len =3D qemu_put_qemu_file(rs->f, comp_param[idx].file); - /* 8 means a header with RAM_SAVE_FLAG_CONTINUE. */ - compression_counters.reduced_size +=3D TARGET_PAGE_SIZE - len = + 8; - compression_counters.pages++; - ram_counters.transferred +=3D len; - } - qemu_mutex_unlock(&comp_param[idx].mutex); - } -} - -static inline void set_compress_params(CompressParam *param, RAMBlock *blo= ck, - ram_addr_t offset) -{ - param->block =3D block; - param->offset =3D offset; -} - static int compress_page_with_multi_thread(RAMState *rs, RAMBlock *block, ram_addr_t offset) { - int idx, thread_count, bytes_xmit =3D -1, pages =3D -1; + CompressData *cd; + ThreadRequest *request =3D threads_submit_request_prepare(compress_thr= eads); =20 - thread_count =3D migrate_compress_threads(); - qemu_mutex_lock(&comp_done_lock); - for (idx =3D 0; idx < thread_count; idx++) { - if (comp_param[idx].done) { - comp_param[idx].done =3D false; - bytes_xmit =3D qemu_put_qemu_file(rs->f, comp_param[idx].file); - qemu_mutex_lock(&comp_param[idx].mutex); - set_compress_params(&comp_param[idx], block, offset); - qemu_cond_signal(&comp_param[idx].cond); - qemu_mutex_unlock(&comp_param[idx].mutex); - pages =3D 1; - /* 8 means a header with RAM_SAVE_FLAG_CONTINUE. */ - compression_counters.reduced_size +=3D TARGET_PAGE_SIZE - - bytes_xmit + 8; - compression_counters.pages++; - ram_counters.transferred +=3D bytes_xmit; - break; - } - } - qemu_mutex_unlock(&comp_done_lock); + if (!request) { + compression_counters.busy++; + return -1; + } =20 - return pages; + cd =3D container_of(request, CompressData, request); + cd->block =3D block; + cd->offset =3D offset; + threads_submit_request_commit(compress_threads, request); + return 1; } =20 /** @@ -1522,7 +1433,7 @@ static bool find_dirty_block(RAMState *rs, PageSearch= Status *pss, bool *again) /* If xbzrle is on, stop using the data compression at this * point. In theory, xbzrle can do better than compression. */ - flush_compressed_data(rs); + flush_compressed_data(); } } /* Didn't find anything this time, but try again on the new block = */ @@ -1776,7 +1687,7 @@ static int ram_save_target_page(RAMState *rs, PageSea= rchStatus *pss, * much CPU resource. */ if (block !=3D rs->last_sent_block) { - flush_compressed_data(rs); + flush_compressed_data(); } else { /* * do not detect zero page as it can be handled very well @@ -1786,7 +1697,6 @@ static int ram_save_target_page(RAMState *rs, PageSea= rchStatus *pss, if (res > 0) { return res; } - compression_counters.busy++; } } =20 @@ -1994,7 +1904,7 @@ static void ram_save_cleanup(void *opaque) } =20 xbzrle_cleanup(); - flush_compressed_data(*rsp); + flush_compressed_data(); compress_threads_save_cleanup(); ram_state_cleanup(rsp); } @@ -2747,7 +2657,7 @@ static int ram_save_complete(QEMUFile *f, void *opaqu= e) } } =20 - flush_compressed_data(rs); + flush_compressed_data(); ram_control_after_iterate(f, RAM_CONTROL_FINISH); =20 rcu_read_unlock(); --=20 2.14.4 From nobody Sun Nov 2 12:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528107065331173.35101240027655; Mon, 4 Jun 2018 03:11:05 -0700 (PDT) Received: from localhost ([::1]:38692 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmS8-0002qD-In for importer@patchew.org; Mon, 04 Jun 2018 06:11:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46647) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPmEI-0007wh-SE for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPmEF-0001N6-4z for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:46 -0400 Received: from mail-pg0-x232.google.com ([2607:f8b0:400e:c05::232]:37681) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fPmEE-0001Md-Rd for qemu-devel@nongnu.org; Mon, 04 Jun 2018 05:56:43 -0400 Received: by mail-pg0-x232.google.com with SMTP id a13-v6so14249069pgu.4 for ; Mon, 04 Jun 2018 02:56:42 -0700 (PDT) Received: from localhost.localdomain ([203.205.141.35]) by smtp.gmail.com with ESMTPSA id h130-v6sm124502105pfc.98.2018.06.04.02.56.38 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Jun 2018 02:56:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=iZgOZ1AuEkabspkyAoobPcWdqMQd7mqyqIifUfGJFmo=; b=uBN+SjiVq9Wbpf6YzbsvDI4MjNA6b9hB8y8nH1lSXVWkfQQtqURZVKANsvrndYS9BO +NBGeFV1f9JNzemCE6cLMQflENJSp8i1NMN39jGZmYyDoteEK8F2/kYPWsBt44T4XtVa DbAphUwYL/vRw/8qafgSjVh5luTuHTxNKeSyie3c9YVAMbFvQqJn5CUNym6iYfm8iVfd ShhbWjGvJBmTt8r2MvspKoKStM6bhYahg/zPhLpRTqjZ40NkDKcTkwQEXmhOdTYVSUnR dn1XAEMAPT1N8Ba3f0hynEKXbsTQzLC5s7FBU8gB6E2DHcbwZDZbRqLghUKKczw9KkO4 f4cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=iZgOZ1AuEkabspkyAoobPcWdqMQd7mqyqIifUfGJFmo=; b=YL4FWtj98Eh6XGl82wJcTXieWQvbZRLUEP8lKIb7XUdLlRtExP4LWy4tAWDYui8CW/ WcsUK2eN29dVYXhfoUzbGodC4VoiwTy7VWvced2XtoA06Qj/apyzlF3/JyB4+CGQMk15 JnqIzV+2KjFsLpXje0Nz52tid5m7AzJdOb3GKx60hEwrdHOQJKrP052u7dX26swZ++a+ t4RqVMKYNKvTCKCavLRmaqEGwTRfNAEHLJdh17SWy1faEPrynY6w6VO2mXo5V6G4x2ZT egc7PvmZ8kDBfA9jUbO4LM/vx2bSqpuOX+uysrPwuvG3CUkMg/PZ3L+frLH4bPtok0DM amjA== X-Gm-Message-State: ALKqPwfZwMEdytdGSPUv7j4zwLDEEGE+MCKLBRWU1RPjoQNqanf4TWLl mwg2a/Q9ybt4rZmzkxeq9a4= X-Google-Smtp-Source: ADUXVKK4KgJP/9QYe9pJewDxmx5SUMiZaO/lQldN4FM0Vne5VFzrMfplyzLAXxnFkL56bgl6o0V32g== X-Received: by 2002:a65:438a:: with SMTP id m10-v6mr17054564pgp.315.1528106201916; Mon, 04 Jun 2018 02:56:41 -0700 (PDT) From: guangrong.xiao@gmail.com X-Google-Original-From: xiaoguangrong@tencent.com To: pbonzini@redhat.com, mst@redhat.com, mtosatti@redhat.com Date: Mon, 4 Jun 2018 17:55:20 +0800 Message-Id: <20180604095520.8563-13-xiaoguangrong@tencent.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180604095520.8563-1-xiaoguangrong@tencent.com> References: <20180604095520.8563-1-xiaoguangrong@tencent.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::232 Subject: [Qemu-devel] [PATCH 12/12] migration: use lockless Multithread model for decompression X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Xiao Guangrong , qemu-devel@nongnu.org, peterx@redhat.com, dgilbert@redhat.com, wei.w.wang@intel.com, jiang.biao2@zte.com.cn Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xiao Guangrong Adapt the compression code to the lockless multithread model Signed-off-by: Xiao Guangrong --- migration/ram.c | 381 ++++++++++++++++++++++++++--------------------------= ---- 1 file changed, 175 insertions(+), 206 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index 58ecf5caa0..0a0ef0ee57 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -341,25 +341,9 @@ typedef struct PageSearchStatus PageSearchStatus; =20 CompressionStats compression_counters; =20 -struct DecompressParam { - bool done; - bool quit; - QemuMutex mutex; - QemuCond cond; - void *des; - uint8_t *compbuf; - int len; - z_stream stream; -}; -typedef struct DecompressParam DecompressParam; - static const QEMUFileOps empty_ops =3D { }; =20 static QEMUFile *decomp_file; -static DecompressParam *decomp_param; -static QemuThread *decompress_threads; -static QemuMutex decomp_done_lock; -static QemuCond decomp_done_cond; =20 /* Multiple fd's */ =20 @@ -962,6 +946,178 @@ static int compress_threads_save_setup(void) return compress_threads ? 0 : -1; } =20 +/* return the size after decompression, or negative value on error */ +static int +qemu_uncompress_data(z_stream *stream, uint8_t *dest, size_t dest_len, + const uint8_t *source, size_t source_len) +{ + int err; + + err =3D inflateReset(stream); + if (err !=3D Z_OK) { + return -1; + } + + stream->avail_in =3D source_len; + stream->next_in =3D (uint8_t *)source; + stream->avail_out =3D dest_len; + stream->next_out =3D dest; + + err =3D inflate(stream, Z_NO_FLUSH); + if (err !=3D Z_STREAM_END) { + return -1; + } + + return stream->total_out; +} + +struct DecompressData { + /* filled by migration thread.*/ + void *des; + uint8_t *compbuf; + size_t len; + + z_stream stream; + ThreadRequest request; +}; +typedef struct DecompressData DecompressData; + +static ThreadRequest *decompress_thread_data_init(void) +{ + DecompressData *dd =3D g_new0(DecompressData, 1); + + if (inflateInit(&dd->stream) !=3D Z_OK) { + g_free(dd); + return NULL; + } + + dd->compbuf =3D g_malloc0(compressBound(TARGET_PAGE_SIZE)); + return &dd->request; +} + +static void decompress_thread_data_fini(ThreadRequest *request) +{ + DecompressData *dd =3D container_of(request, DecompressData, request); + + inflateEnd(&dd->stream); + g_free(dd->compbuf); + g_free(dd); +} + +static void decompress_thread_data_handler(ThreadRequest *request) +{ + DecompressData *dd =3D container_of(request, DecompressData, request); + unsigned long pagesize =3D TARGET_PAGE_SIZE; + int ret; + + ret =3D qemu_uncompress_data(&dd->stream, dd->des, pagesize, + dd->compbuf, dd->len); + if (ret < 0) { + error_report("decompress data failed"); + qemu_file_set_error(decomp_file, ret); + } +} + +static void decompress_thread_data_done(ThreadRequest *data) +{ +} + +struct CompressLoad { + Threads *decompress_threads; + + /* + * used to decompress data in migration thread if + * decompress threads are busy. + */ + z_stream stream; + uint8_t *compbuf; +}; +typedef struct CompressLoad CompressLoad; + +static CompressLoad compress_load; + +static int decompress_init(QEMUFile *f) +{ + Threads *threads; + + threads =3D threads_create(migrate_decompress_threads(), "decompress", + decompress_thread_data_init, + decompress_thread_data_fini, + decompress_thread_data_handler, + decompress_thread_data_done); + if (!threads) { + return -1; + } + + if (inflateInit(&compress_load.stream) !=3D Z_OK) { + threads_destroy(threads); + return -1; + } + + compress_load.decompress_threads =3D threads; + compress_load.compbuf =3D g_malloc0(compressBound(TARGET_PAGE_SIZE)); + decomp_file =3D f; + return 0; +} + +static void decompress_fini(void) +{ + if (!compress_load.compbuf) { + return; + } + + threads_destroy(compress_load.decompress_threads); + compress_load.decompress_threads =3D NULL; + g_free(compress_load.compbuf); + compress_load.compbuf =3D NULL; + inflateEnd(&compress_load.stream); + decomp_file =3D NULL; +} + +static int flush_decompressed_data(void) +{ + if (!migrate_use_compression()) { + return 0; + } + + threads_wait_done(compress_load.decompress_threads); + return qemu_file_get_error(decomp_file); +} + +static void decompress_data_with_multi_threads(QEMUFile *f, + void *host, size_t len) +{ + ThreadRequest *request; + Threads *threads =3D compress_load.decompress_threads; + unsigned long pagesize =3D TARGET_PAGE_SIZE; + uint8_t *compbuf =3D compress_load.compbuf; + int ret; + + request =3D threads_submit_request_prepare(threads); + if (request) { + DecompressData *dd; + + dd =3D container_of(request, DecompressData, request); + dd->des =3D host; + dd->len =3D len; + qemu_get_buffer(f, dd->compbuf, len); + threads_submit_request_commit(threads, request); + return; + } + + /* load data and decompress in the main thread */ + + /* it can change compbuf to point to an internal buffer */ + qemu_get_buffer_in_place(f, &compbuf, len); + + ret =3D qemu_uncompress_data(&compress_load.stream, host, pagesize, + compbuf, len); + if (ret < 0) { + error_report("decompress data failed"); + qemu_file_set_error(decomp_file, ret); + } +} + /** * xbzrle_cache_zero_page: insert a zero page in the XBZRLE cache * @@ -2794,193 +2950,6 @@ void ram_handle_compressed(void *host, uint8_t ch, = uint64_t size) } } =20 -/* return the size after decompression, or negative value on error */ -static int -qemu_uncompress_data(z_stream *stream, uint8_t *dest, size_t dest_len, - const uint8_t *source, size_t source_len) -{ - int err; - - err =3D inflateReset(stream); - if (err !=3D Z_OK) { - return -1; - } - - stream->avail_in =3D source_len; - stream->next_in =3D (uint8_t *)source; - stream->avail_out =3D dest_len; - stream->next_out =3D dest; - - err =3D inflate(stream, Z_NO_FLUSH); - if (err !=3D Z_STREAM_END) { - return -1; - } - - return stream->total_out; -} - -static void *do_data_decompress(void *opaque) -{ - DecompressParam *param =3D opaque; - unsigned long pagesize; - uint8_t *des; - int len, ret; - - qemu_mutex_lock(¶m->mutex); - while (!param->quit) { - if (param->des) { - des =3D param->des; - len =3D param->len; - param->des =3D 0; - qemu_mutex_unlock(¶m->mutex); - - pagesize =3D TARGET_PAGE_SIZE; - - ret =3D qemu_uncompress_data(¶m->stream, des, pagesize, - param->compbuf, len); - if (ret < 0) { - error_report("decompress data failed"); - qemu_file_set_error(decomp_file, ret); - } - - qemu_mutex_lock(&decomp_done_lock); - param->done =3D true; - qemu_cond_signal(&decomp_done_cond); - qemu_mutex_unlock(&decomp_done_lock); - - qemu_mutex_lock(¶m->mutex); - } else { - qemu_cond_wait(¶m->cond, ¶m->mutex); - } - } - qemu_mutex_unlock(¶m->mutex); - - return NULL; -} - -static int wait_for_decompress_done(void) -{ - int idx, thread_count; - - if (!migrate_use_compression()) { - return 0; - } - - thread_count =3D migrate_decompress_threads(); - qemu_mutex_lock(&decomp_done_lock); - for (idx =3D 0; idx < thread_count; idx++) { - while (!decomp_param[idx].done) { - qemu_cond_wait(&decomp_done_cond, &decomp_done_lock); - } - } - qemu_mutex_unlock(&decomp_done_lock); - return qemu_file_get_error(decomp_file); -} - -static void compress_threads_load_cleanup(void) -{ - int i, thread_count; - - if (!migrate_use_compression()) { - return; - } - thread_count =3D migrate_decompress_threads(); - for (i =3D 0; i < thread_count; i++) { - /* - * we use it as a indicator which shows if the thread is - * properly init'd or not - */ - if (!decomp_param[i].compbuf) { - break; - } - - qemu_mutex_lock(&decomp_param[i].mutex); - decomp_param[i].quit =3D true; - qemu_cond_signal(&decomp_param[i].cond); - qemu_mutex_unlock(&decomp_param[i].mutex); - } - for (i =3D 0; i < thread_count; i++) { - if (!decomp_param[i].compbuf) { - break; - } - - qemu_thread_join(decompress_threads + i); - qemu_mutex_destroy(&decomp_param[i].mutex); - qemu_cond_destroy(&decomp_param[i].cond); - inflateEnd(&decomp_param[i].stream); - g_free(decomp_param[i].compbuf); - decomp_param[i].compbuf =3D NULL; - } - g_free(decompress_threads); - g_free(decomp_param); - decompress_threads =3D NULL; - decomp_param =3D NULL; - decomp_file =3D NULL; -} - -static int compress_threads_load_setup(QEMUFile *f) -{ - int i, thread_count; - - if (!migrate_use_compression()) { - return 0; - } - - thread_count =3D migrate_decompress_threads(); - decompress_threads =3D g_new0(QemuThread, thread_count); - decomp_param =3D g_new0(DecompressParam, thread_count); - qemu_mutex_init(&decomp_done_lock); - qemu_cond_init(&decomp_done_cond); - decomp_file =3D f; - for (i =3D 0; i < thread_count; i++) { - if (inflateInit(&decomp_param[i].stream) !=3D Z_OK) { - goto exit; - } - - decomp_param[i].compbuf =3D g_malloc0(compressBound(TARGET_PAGE_SI= ZE)); - qemu_mutex_init(&decomp_param[i].mutex); - qemu_cond_init(&decomp_param[i].cond); - decomp_param[i].done =3D true; - decomp_param[i].quit =3D false; - qemu_thread_create(decompress_threads + i, "decompress", - do_data_decompress, decomp_param + i, - QEMU_THREAD_JOINABLE); - } - return 0; -exit: - compress_threads_load_cleanup(); - return -1; -} - -static void decompress_data_with_multi_threads(QEMUFile *f, - void *host, int len) -{ - int idx, thread_count; - - thread_count =3D migrate_decompress_threads(); - qemu_mutex_lock(&decomp_done_lock); - while (true) { - for (idx =3D 0; idx < thread_count; idx++) { - if (decomp_param[idx].done) { - decomp_param[idx].done =3D false; - qemu_mutex_lock(&decomp_param[idx].mutex); - qemu_get_buffer(f, decomp_param[idx].compbuf, len); - decomp_param[idx].des =3D host; - decomp_param[idx].len =3D len; - qemu_cond_signal(&decomp_param[idx].cond); - qemu_mutex_unlock(&decomp_param[idx].mutex); - break; - } - } - if (idx < thread_count) { - break; - } else { - qemu_cond_wait(&decomp_done_cond, &decomp_done_lock); - } - } - qemu_mutex_unlock(&decomp_done_lock); -} - /** * ram_load_setup: Setup RAM for migration incoming side * @@ -2991,7 +2960,7 @@ static void decompress_data_with_multi_threads(QEMUFi= le *f, */ static int ram_load_setup(QEMUFile *f, void *opaque) { - if (compress_threads_load_setup(f)) { + if (decompress_init(f)) { return -1; } =20 @@ -3004,7 +2973,7 @@ static int ram_load_cleanup(void *opaque) { RAMBlock *rb; xbzrle_load_cleanup(); - compress_threads_load_cleanup(); + decompress_fini(); =20 RAMBLOCK_FOREACH(rb) { g_free(rb->receivedmap); @@ -3346,7 +3315,7 @@ static int ram_load(QEMUFile *f, void *opaque, int ve= rsion_id) } } =20 - ret |=3D wait_for_decompress_done(); + ret |=3D flush_decompressed_data(); rcu_read_unlock(); trace_ram_load_complete(ret, seq_iter); return ret; --=20 2.14.4