Google Groepen ondersteunt geen nieuwe Usenet-berichten of -abonnementen meer. Historische content blijft zichtbaar.

Getting frequncy out of /proc/cpuinfo

49 weergaven
Naar het eerste ongelezen bericht

Cecil Westerhof

ongelezen,
1 dec 2017, 08:28:0701-12-2017
aan
I want to fetch the frequencies out of /proc/cpuinfo.

This information is in line like:
cpu MHz : 1400.000

What is the best way to retrieve this information?

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

Rich

ongelezen,
1 dec 2017, 08:55:5401-12-2017
aan
Cecil Westerhof <Ce...@decebal.nl> wrote:
> I want to fetch the frequencies out of /proc/cpuinfo.
>
> This information is in line like:
> cpu MHz : 1400.000
>
> What is the best way to retrieve this information?

"Best" is somewhat of an 'opinion' type item.

One way to do so would be to read the file line by line, pattern
matching each line against "cpu MHz", then when a match is found,
extract the numerical value.

Whether that is 'best' is quite subjective.

Cecil Westerhof

ongelezen,
1 dec 2017, 09:44:0601-12-2017
aan
That is what I do at the moment:
set filename "/proc/cpuinfo"
set pattern "^cpu MHz."
set count 0

set fid [open ${filename} r]
while {[gets ${fid} line] != -1} {
if {[regexp -all -- ${pattern} ${line}]} {
set frequency [lindex ${line} 3]
incr count
puts ${line}
puts [lindex ${line} 3]
if {${count} == 1} {
set max ${frequency}
set min ${frequency}
set sigma ${frequency}
} else {
if {${frequency} < ${min}} {
set min ${frequency}
} elseif {${frequency} > ${max}} {
set max ${frequency}
}
set sigma [expr ${sigma} + ${frequency}]
}
}
}
close ${fid}
puts [format "total: %f\nmin: %f\nmax: %f\navg: %f" \
${sigma} \
${min} \
${max} \
[expr ${sigma} / ${count}]]

But it seems a bit verbose. I was wondering if there was a way to have
an expression and a filename and return an array of matches.

Also: I would like to use something like:
set pattern "^cpu MHz.\S+: [0-9.]$"
instead of:
set pattern "^cpu MHz."

But that does not work. Even:
set pattern "^cpu MHz.\S+"
does not work.

What am I doing wrong?

Ashok

ongelezen,
1 dec 2017, 10:46:1301-12-2017
aan
If you are willing to use tcllib you can try fileutil::grep

Rich

ongelezen,
1 dec 2017, 13:29:0201-12-2017
aan
Cecil Westerhof <Ce...@decebal.nl> wrote:
> Rich <ri...@example.invalid> writes:
>
>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>> I want to fetch the frequencies out of /proc/cpuinfo.
>>>
>>> This information is in line like:
>>> cpu MHz : 1400.000
>>>
>>> What is the best way to retrieve this information?
>>
>> "Best" is somewhat of an 'opinion' type item.
>>
>> One way to do so would be to read the file line by line, pattern
>> matching each line against "cpu MHz", then when a match is found,
>> extract the numerical value.
>
> That is what I do at the moment:
[long code block elided - see prior post for details]
>
> But it seems a bit verbose. I was wondering if there was a way to
> have an expression and a filename and return an array of matches.

Install tcllib, then you can have a tcl level 'grep' where you pass it
a pattern and a set of filenames.

> Also: I would like to use something like:
> set pattern "^cpu MHz.\S+: [0-9.]$"
> instead of:
> set pattern "^cpu MHz."
>
> But that does not work. Even:
> set pattern "^cpu MHz.\S+"
> does not work.
>
> What am I doing wrong?

You forgot a + on your bracket expression, so it only matches a single
character.

The \S escape is "not whitespace" - you want \s

$ rlwrap tclsh
% set line "cpu MHz : 1400.000"
cpu MHz : 1400.000
% regexp {^cpu MHz.\s+: [0-9.]$} $line -> freq
0
% regexp {^cpu MHz.\s+: [0-9.]+$} $line -> freq
1
% regexp {^cpu MHz.\s+: [0-9.]+$} $line
1

But you can also do more in the regexp. Change it to this one:

^cpu MHz\s+:\s([0-9.]+)$

And call the regexp command this way:

% regexp {^cpu MHz\s+:\s([0-9.]+)$} $line -> freq
1
% set freq
1400.000
%

And the regex engine also returns the frequency already extracted for
you. The parenthesis do the extraction.

Cecil Westerhof

ongelezen,
1 dec 2017, 18:59:0601-12-2017
aan
Rich <ri...@example.invalid> writes:

> Cecil Westerhof <Ce...@decebal.nl> wrote:
>> Rich <ri...@example.invalid> writes:
>>
>>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>>> I want to fetch the frequencies out of /proc/cpuinfo.
>>>>
>>>> This information is in line like:
>>>> cpu MHz : 1400.000
>>>>
>>>> What is the best way to retrieve this information?
>>>
>>> "Best" is somewhat of an 'opinion' type item.
>>>
>>> One way to do so would be to read the file line by line, pattern
>>> matching each line against "cpu MHz", then when a match is found,
>>> extract the numerical value.
>>
>> That is what I do at the moment:
> [long code block elided - see prior post for details]
>>
>> But it seems a bit verbose. I was wondering if there was a way to
>> have an expression and a filename and return an array of matches.
>
> Install tcllib, then you can have a tcl level 'grep' where you pass it
> a pattern and a set of filenames.

I will look into that. But that would make my code depending on an
extra library?


>> Also: I would like to use something like:
>> set pattern "^cpu MHz.\S+: [0-9.]$"
>> instead of:
>> set pattern "^cpu MHz."
>>
>> But that does not work. Even:
>> set pattern "^cpu MHz.\S+"
>> does not work.
>>
>> What am I doing wrong?
>
> You forgot a + on your bracket expression, so it only matches a single
> character.

That was not very smart. :'-(


> The \S escape is "not whitespace" - you want \s
>
> $ rlwrap tclsh
> % set line "cpu MHz : 1400.000"
> cpu MHz : 1400.000
> % regexp {^cpu MHz.\s+: [0-9.]$} $line -> freq
> 0
> % regexp {^cpu MHz.\s+: [0-9.]+$} $line -> freq
> 1
> % regexp {^cpu MHz.\s+: [0-9.]+$} $line
> 1
>
> But you can also do more in the regexp. Change it to this one:
>
> ^cpu MHz\s+:\s([0-9.]+)$

I did it a bit different:
set pattern {^cpu MHz\s+: ([0-9]+)\.0+$}

There should be exactly one space after the ':'.
I only want the integral part.
After the point there are only zeros.


> And call the regexp command this way:
>
> % regexp {^cpu MHz\s+:\s([0-9.]+)$} $line -> freq
> 1
> % set freq
> 1400.000
> %
>
> And the regex engine also returns the frequency already extracted for
> you. The parenthesis do the extraction.

I thought something like this should be possible. ;-)

I now have:
while {[gets ${fid} line] != -1} {
if {[regexp ${pattern} ${line} -> frequency] == 1} {
incr count
if {${count} == 1} {
set max ${frequency}
.
.
.

And my format string is of-course now:
"total: %d\nmin: %d\nmax: %d\navg: %d\n"

Rich

ongelezen,
1 dec 2017, 20:30:4901-12-2017
aan
Cecil Westerhof <Ce...@decebal.nl> wrote:
> Rich <ri...@example.invalid> writes:
>
>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>> Rich <ri...@example.invalid> writes:
>>>
>>>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>>>> I want to fetch the frequencies out of /proc/cpuinfo.
>>>>>
>>>>> This information is in line like:
>>>>> cpu MHz : 1400.000
>>>>>
>>>>> What is the best way to retrieve this information?
>>>>
>>>> "Best" is somewhat of an 'opinion' type item.
>>>>
>>>> One way to do so would be to read the file line by line, pattern
>>>> matching each line against "cpu MHz", then when a match is found,
>>>> extract the numerical value.
>>>
>>> That is what I do at the moment:
>> [long code block elided - see prior post for details]
>>>
>>> But it seems a bit verbose. I was wondering if there was a way to
>>> have an expression and a filename and return an array of matches.
>>
>> Install tcllib, then you can have a tcl level 'grep' where you pass it
>> a pattern and a set of filenames.
>
> I will look into that. But that would make my code depending on an
> extra library?

Yes. But it is a pure Tcl library so 'distributing' both parts
together is not hard. But the 'grep' library routine would simply give
you the lines of interest, you'd still need to pull out the number of
interest anyway. So your snippet below may be the better variant in
this case.

>> The \S escape is "not whitespace" - you want \s
>>
>> $ rlwrap tclsh
>> % set line "cpu MHz : 1400.000"
>> cpu MHz : 1400.000
>> % regexp {^cpu MHz.\s+: [0-9.]+$} $line
>> 1
>>
>> But you can also do more in the regexp. Change it to this one:
>>
>> ^cpu MHz\s+:\s([0-9.]+)$
>
> I did it a bit different:
> set pattern {^cpu MHz\s+: ([0-9]+)\.0+$}
>
> There should be exactly one space after the ':'.
> I only want the integral part.
> After the point there are only zeros.

That works. I did not know if you wanted the full string or the
integral part when I wrote mine.

>> And call the regexp command this way:
>>
>> % regexp {^cpu MHz\s+:\s([0-9.]+)$} $line -> freq
>> 1
>> % set freq
>> 1400.000
>> %
>>
>> And the regex engine also returns the frequency already extracted for
>> you. The parenthesis do the extraction.
>
> I thought something like this should be possible. ;-)
>
> I now have:
> while {[gets ${fid} line] != -1} {
> if {[regexp ${pattern} ${line} -> frequency] == 1} {
> incr count
> if {${count} == 1} {
> set max ${frequency}
> .
> .
> .
>
> And my format string is of-course now:
> "total: %d\nmin: %d\nmax: %d\navg: %d\n"

One little extra tip. That -> is actually a variable assignment. The
third parameter returns the full match, so it would contain the whole
line. You could access it using the ${} notation (${->}) if you really
wanted its contents. The "->" variable name just makes for a nice look
when one only wants the sub-matches instead of the full match.

Schelte Bron

ongelezen,
2 dec 2017, 07:23:3902-12-2017
aan
Cecil Westerhof wrote:
> Rich <ri...@example.invalid> writes:
>> Install tcllib, then you can have a tcl level 'grep' where you
>> pass it a pattern and a set of filenames.
>
> I will look into that. But that would make my code depending on an
> extra library?
>
I would use [scan] rather than [regexp]:

namespace path {tcl::mathfunc tcl::mathop}

set fd [open /proc/cpuinfo]
set list {}
while {[gets $fd line] != -1} {
if {[scan $line {cpu MHz : %f} speed] == 1} {
lappend list $speed
}
}
close $fd

puts [format "total: %.3f\nmin: %.3f\nmax: %.3f\navg: %.3f" \
[set sigma [+ {*}$list]] \
[min {*}$list] \
[max {*}$list] \
[/ $sigma [llength $list]]]


Schelte.

Cecil Westerhof

ongelezen,
2 dec 2017, 16:44:0602-12-2017
aan
Rich <ri...@example.invalid> writes:

>>> But you can also do more in the regexp. Change it to this one:
>>>
>>> ^cpu MHz\s+:\s([0-9.]+)$
>>
>> I did it a bit different:
>> set pattern {^cpu MHz\s+: ([0-9]+)\.0+$}
>>
>> There should be exactly one space after the ':'.
>> I only want the integral part.
>> After the point there are only zeros.
>
> That works. I did not know if you wanted the full string or the
> integral part when I wrote mine.

I did not tell. ;-) But it are always big numbers without anything
after the comma, so it is not really useful to use floats I think.

But you set me on the right track.


> One little extra tip. That -> is actually a variable assignment. The
> third parameter returns the full match, so it would contain the whole
> line. You could access it using the ${} notation (${->}) if you really
> wanted its contents. The "->" variable name just makes for a nice look
> when one only wants the sub-matches instead of the full match.

Yep, that was very useful.
0 nieuwe berichten