On Sat, 28 Jan 2012 07:19:42 -0700
Eric Blake <eblake(a)redhat.com> wrote:
On 01/27/2012 11:20 PM, KAMEZAWA Hiroyuki wrote:
>
> add new API virDomainGetCPUStats() for getting cpu accounting information
> per real cpus which is used by a domain.
>
> based on ideas by Lai Jiangshan and Eric Blake.
> Proposed API is a bit morified to be able to return max cpu ID.
s/morified/modified/
> (max cpu ID != cpu num.)
Nice extension to my proposal. And you made it - I'm going to push this
today, so your API is definitely in 0.9.10, even if we need a few
touchups discovered during testing during the freeze.
Thank you. good news :)
For example, it's fine if you don't have the Python
implementation done before
the freeze; that's something I don't mind taking during the freeze week on the
grounds that it is rounding out a feature that we have committed to, and
that it won't be altering the API itself. But of course, sooner means
more review time and testing :)
I'm hoisting the hunk from 4/5 on libvirt.h.in, where you define the
first stat, "cpu_time".
Thanks.
> +++ b/src/libvirt.c
> @@ -18017,3 +18017,139 @@ error:
> virDispatchError(dom->conn);
> return -1;
> }
> +
> +/**
> + * virDomainGetCPUStats:
> + * @domain: domain to query
> + * @params: array to populate on output
> + * @nparams: number of parameters per cpu
> + * @start_cpu: which cpu to start with, or -1 for summary
> + * @ncpus: how many cpus to query
> + * @flags: unused for now
This should use the common text we have elsewhere.
Sure.
> + *
> + * Get statistics relating to CPU usage attributable to a single
> + * domain (in contrast to the statistics returned by
> + * virNodeGetCPUStats() for all processes on the host). @dom
> + * must be running (an inactive domain has no attributable cpu
> + * usage). On input, @params must contain at least @nparams * @ncpus
> + * entries, allocated by the caller.
> + *
> + * Now, @ncpus is limited to be <= 128. If you want to get
> + * values in a host with more cpus, you need to call multiple times.
> + *
> + * @nparams are limited to be <= 16 but maximum params per cpu
> + * provided by will be smaller than this.
I'd combine these limits, and mention that they mainly apply to remote
protocols.
Ok, it will be better.
> + *
> + *
> + * If @start_cpu is -1, then @ncpus must be 1, and the returned
> + * results reflect the statistics attributable to the entire
> + * domain (such as user and system time for the process as a
> + * whole). Otherwise, @start_cpu represents which cpu to start
> + * with, and @ncpus represents how many consecutive processors to
> + * query, with statistics attributable per processor (such as
> + * per-cpu usage).
> + *
> + * As a special case, if @params is NULL and @nparams is 0 and
> + * @ncpus is 1, and the return value will be how many
> + * statistics are available for the given @start_cpu. This number
> + * may be different for @start_cpu of -1 than for any non-negative
> + * value, but will be the same for all non-negative @start_cpu.
> + *
> + * And, if @param is NULL and @ncparam is 0 and @ncpus is 0,
s/ncparam/nparams/
> + * Max cpu id of the node is returned. (considering cpu hotplug,
> + * max cpu id may be different from the number of cpu on a host.)
Yes, this is useful.
> + *
> + * For now, @flags is unused, and the statistics all relate to the
> + * usage from the host perspective; the number of cpus available to
> + * query can be determined by the cpus member of the result of
> + * virNodeGetInfo(),
but it means this information is not quite right.
We'll check other users of calculation as max_cpu = sockets*cores*threads.
I wonder it may be better that NodeGetInfo() returns max_cpu "ID", online
cpu map etc..but I can't change the interface _virNodeInfo, right ?
> even if the domain has had vcpus pinned to only
> + * use a subset of overall host cpus. It is possible that a future
> + * version will support a flag that queries the cpu usage from the
> + * guest's perspective, using the number of vcpus available to the
> + * guest, found by virDomainGetVcpusFlags(). An individual guest
> + * vcpu cannot be reliably mapped back to a specific host cpu unless
> + * a single-processor vcpu pinning was used, but when @start_cpu is -1,
> + * any difference in usage between a host and guest perspective would
> + * serve as a measure of hypervisor overhead.
> + *
> + * Returns -1 on failure, or the number of statistics that were
> + * populated per cpu on success (this will be less than the total
> + * number of populated @params, unless @ncpus was 1; and may be
> + * less than @nparams). The populated parameters start at each
> + * stride of @nparams; any unpopulated parameters will be zeroed
> + * on success. The caller is responsible for freeing any returned
> + * string parameters.
The return paragraph should be last.
Okay.
> + *
> + * Note:
> + * Because cpu ids may be discontig, retuned @param array may contain
> + * zero-filled entry in the middle.
This repeats part of the return paragraph.
Sorry.
> + * All time related values are represented in ns, using
UULONG.
This should be documented by the various macros for well-defined stat names.
> + *
> + * Typical use sequence is below.
> + *
> + * getting total stats: set start_cpu as -1, ncpus 1
> + * virDomainGetCPUStats(dom, NULL, 0, -1, 1, 0) => nparams
> + * VIR_ALLOC_N(params, nparams)
Example code is written for apps that aren't using libvirt internals,
therefore it must use calloc instead of VIR_ALLOC_N.
> + * virDomainGetCPUStats(dom, parasm, nparams, -1, 1, 0) => total stats.
s/parasm/params/
> + *
> + * getting percpu stats:
> + * virDomainGetCPUStats(dom, NULL, 0, 0, 0, 0) => max_cpu_id
> + * virDomainGetCPUStats(dom, NULL, 0, 0, 1, 0) => nparams
> + * VIR_ALLOC_N(params, max_cpu_id * nparams)
> + * virDomainGetCPUStats(dom, params, nparams, 0, max_cpu_id, 0) => percpu stats
This should be moved up right after the documentation of special casing.
That sounds better.
> + *
> + */
> +
> +int virDomainGetCPUStats(virDomainPtr domain,
> + virTypedParameterPtr params,
> + unsigned int nparams,
> + int start_cpu,
> + unsigned int ncpus,
> + unsigned int flags)
> +{
> + virConnectPtr conn;
> +
> + VIR_DOMAIN_DEBUG(domain, "nparams=%d, start_cpu=%d, ncpu=%d,
flags=%x",
Missing params.
Ah, yes.
> + nparams, start_cpu, ncpus, flags);
> + virResetLastError();
> +
> + if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
> + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
> + virDispatchError(NULL);
> + return -1;
> + }
> +
> + conn = domain->conn;
> + /* start_cpu == -1 is a special case. ncpus must be 1 */
> + if ((start_cpu == -1) && (ncpus != 1)) {
> + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
> + goto error;
We can further check that start_cpu is -1 or non-negative.
> + }
> + /* if params == NULL, nparams must be 0 */
> + if ((params == NULL) && ((nparams != 0))) {
> + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
> + goto error;
We can further check that nparams is non-zero if params is non-NULL.
We can further check that ncpus is non-zero unless params is NULL.
Since we don't distinguish the error message, we could join these
conditionals.
I see.
> + }
> +
> + /* remote protocol doesn't welcome big args in one shot */
> + if ((nparams > 16) || (ncpus > 128)) {
> + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
> + goto error;
> + }
This restriction should only be forced by the remote protocol. See
virDomainMemoryPeek for an example of a documented RPC limitation, but
which is only enforced in the RPC code.
Hmm, ok.
> +++ b/src/libvirt_public.syms
> @@ -520,6 +520,7 @@ LIBVIRT_0.9.10 {
> global:
> virDomainShutdownFlags;
> virStorageVolWipePattern;
> + virDomainGetCPUStats;
I like to keep this sorted.
Overall, ACK - you picked up on the review suggestions, and the API
looks good enough now to commit to. Here's what I'm squashing before
pushing, which means we now have the API in place before the freeze!
I'm not sure if I will finish reviewing the rest of the series today,
seeing as it is my weekend, but we'll certainly get it all in before the
release.
Thank you for pushing and lots of fixes.
Regards,
-Kame