Wert von MAXCPU in C auf amd64 (prometheus cpu collector)

From: Marian Hettwer <mh(at)kernel32.de>
Date: Fri, 02 Dec 2016 21:24:54 +0100

Hallo Liste,

ich knobel an einer compile Frage, in die ich reingestolpert bin,
nachdem ich mir Prometheus auf meinem Server installiert habe.
Der Autor des cpu collectors probiert scheinbar rauszubekommen, wie groß
die maximale Anzahl an CPUs ist.

https://github.com/prometheus/node_exporter/blob/master/collector/cpu_freebsd.go#L106

Zeile 109: const maxCPUTimesLen = C.MAXCPU * C.CPUSTATES

MAXCPU ist wohl als konstante in /usr/include/machine/params.h
definiert. Unter amd64, wenn SMP definiert ist, dann 64, else 1.
Was mich wundert ist, dass auf meinem 10.3-RELEASE das ganze im else
part landet. Obwohl amd64.

[prometheus ~]$ uname -srm
FreeBSD 10.3-RELEASE-p11 amd64

Wenn ich den Golang (oder halb C halb cgo halb golang?!) code richtig
verstehe, will er diese Berechnung moeglichst genau machen, damit er
keinen unnötig großen Array in go anlegt:

Zeile 159 und 160

        // Convert C.double array to Go array
(https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices).
        cpuTimes :=
(*[maxCPUTimesLen]C.double)(unsafe.Pointer(cpuTimesC))[:cpuTimesLength:cpuTimesLength]

Das ist ja an sich erstmal löblich.
Ich finde nur keinen Weg, wie C.MAXCPU auf 64 kommt, ausser über Zeile
30 in seinem Code ein '#define SMP 1' reinzuwerfen.
Aber das kann ja nicht die Lösung sein.

So wie es jetzt ist, egal ob node_exporter via package oder via github
und go build installiert wird, kann es nur funktionieren, falls das
system nur 1 Prozessor hat. Ansonsten geht sein vergleich in Zeile 154
bis 157:
        defer C.freeCPUTimes(cpuTimesC)
        if cpuTimesLength > maxCPUTimesLen {
                return errors.New("more CPU's than MAXCPU?")
        }
einfach schief und falls man node_exporter startet und dann via curl
http://...:9100/metrics abfragt, endet das mit:
More CPU's than MAXCPU?
Weil er CPU's tatsächlich richtig berechnet. In meinem Fall bei
hw.ncpu=8 kommt sein Code auf 40. Aber maxCPUTimesLen nur bei 1 * 5
landet.
Und 40 ist ja tatsache größer als 5 :)

Hat jemand ne Idee warum MAXCPU 1 ist, bzw wie man das sauber lösen
kann?

BeSDe Grüße,
Marian

PS: Spaß am Rande. Was die go Leute unter
https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices
angeben klingt auch eher abenteuerlich:
To create a Go slice backed by a C array (without copying the original
data), one needs to acquire this length at runtime and use a type
conversion to a pointer to a very big array and then slice it to the
length that you want.
Klingt wie ein Backrezept: Man nehme eine große Schüssel (a pointer to a
very big array), werfe die Zutaten da rein und messe dann mal nach (and
slice it to the length that you want).
Immerhin wollte der Autor von cpu_freebsd.go scheinbar die Schüsselgröße
nicht zu groß dimensionieren.
Mein workaround mit dem #define SMP 1 macht halt ne große Schüssel. Aber
als pr will ich das auf github eigentlich nicht rübergeben...

-- 
the problem with troubleshooting is that trouble shoots back.
To Unsubscribe: send mail to majordomo(at)de.FreeBSD.org
with "unsubscribe de-bsd-questions" in the body of the message
Received on Fri 02 Dec 2016 - 21:25:01 CET

search this site