What is quantity? quantity is a string representation of some countable resources, comprised by a number, either an int64 or a bigint value, and a unit suffix. for example 100Mi, 1000m, 100. The resources can be cpu, gpu, memory, pods, ephemeral-storage, etc, we can get the full resources list from the nodes.Status.Capacity.
In this article, we mainly talk about how to use quantity in client-go library. First, let’s see how Quantity is represented in golang:
type Quantity struct {
i int64Amount
d infDecAmount
// cache String() result
s string
// string, available values are: DecimalSI, BinarySI, DecimalExponent
Format
}
This struct has a s
field, used for caching String() method return value. the Format
field indicates the quantity number type, may be decimal, binary and decimal exponent. the int64Amount
and infDecAmount
both have a value field and a scale field. The value field stores the corresponding number without any unit suffix, and the scale field stores the multiplication times / shift bits number to convert the origin value to a unit-less form.
int64Amount represents a fixed precision numerator and arbitrary scale exponent. It is faster than operations on inf.Dec for values that can be represented as int64.
type int64Amount struct {
value int64
scale Scale
}
type infDecAmount struct {
*inf.Dec
}
infDecAmount implements common operations over an inf.Dec that are specific to the quantity representation.
type Dec struct {
unscaled big.Int
scale Scale
}
Now, let’s create some quantity values using different methods, and print their number value and string representation.
package main
import (
"fmt"
"gopkg.in/inf.v0"
"k8s.io/apimachinery/pkg/api/resource"
)
func main() {
q1, _ := resource.ParseQuantity("1100000m")
fmt.Println(q1.Value(), q1.String(), q1.Format)
q11, _ := resource.ParseQuantity("11.1111k")
fmt.Println(q11.Value(), q11.String(), q11.Format)
q2 := resource.NewMilliQuantity(1100001, resource.BinarySI)
fmt.Println(q2.Value(), q2.String(), q2.Format)
q3 := resource.NewQuantity(1024, resource.BinarySI)
fmt.Println(q3.Value(), q3.String())
// Flowing two functions seldom used in kubernetes
q4 := resource.NewDecimalQuantity(*inf.NewDec(103000, -3), resource.DecimalExponent)
fmt.Println(q4.Value(), q4.String())
q5 := resource.NewScaledQuantity(1100, -3)
fmt.Println(q5.Value(), q5.String(), q5.Format)
}
By running this brief program, we can get the following results:
1100 1100 DecimalSI
11112 11111100m DecimalSI
1101 1100001m BinarySI
1024 1Ki
103000000 103e6
2 1100m DecimalSI
There a few notable points:
- we can see the Value() of 1100000m is 1100, because the meaning of m is milli, so it is divided by 1000
- the String() value of 1100000m is also 1100
- the String() value will use a best unit automatically, the value of 11000000m will be 11k
- the milli value of 1100001’s Value() is 1101, it is rounded up
- the exponent value 103000000’s String() representation is 103e6, here the “e6” can be regarded as the unit
For all supported units, corresponding scale value, and formats, please refer the following tables.
Unit | Scale | Format |
Ki | 210 | BinarySI |
Mi | 220 | BinarySI |
Gi | 230 | BinarySI |
Ti | 240 | BinarySI |
Pi | 250 | BinarySI |
Ei | 260 | BinarySI |
n | 10-9 | DecimalSI |
u | 10-6 | DecimalSI |
m | 10-3 | DecimalSI |
“” empty | 100 | DecimalSI |
k | 103 | DecimalSI |
M | 106 | DecimalSI |
G | 109 | DecimalSI |
T | 1012 | DecimalSI |
P | 1015 | DecimalSI |
E | 1018 | DecimalSI |
Ex or ex, exponent format, e.g. e3 | 10x | DecimalExponent |
The last, NewDecimalQuantity() and NewScaledQuantity() functions are seldom used in kubernetnes. For cpu resource, it is reported as milli value, and for memory resource, it reported as a byte (unit-less) value, both cpu and memory resource are reported by kubelet. If you want to use the quantities, it is best to use the form as they reported to make the value more precise.
Note: client-go version is v0.29.1.