amanusk / s-tui

Terminal-based CPU stress and monitoring utility
https://amanusk.github.io/s-tui/
GNU General Public License v2.0
4.07k stars 140 forks source link

get_avarage_cpu_freq() gives "TypeError: unsupported operand type(s) for /: 'str' and 'int'" on 1-core VPS #30

Closed sanderjo closed 7 years ago

sanderjo commented 7 years ago

On my 1-core VPS (Ubuntu), s_tui does not show any frequency info, so I did some analysis, which resulted in this Traceback

sander@haring:~/git/s-tui$ python s_tui/HelperFunctions.py
Traceback (most recent call last):
  File "s_tui/HelperFunctions.py", line 173, in <module>
    avg = get_avarage_cpu_freq()
  File "s_tui/HelperFunctions.py", line 40, in get_avarage_cpu_freq
    return round(reduce(lambda x, y: float(x) + float(y), cores_freq) / len(cores_freq), 1)
TypeError: unsupported operand type(s) for /: 'str' and 'int'
sander@haring:~/git/s-tui$ 

/proc/cpuinfo does contain frequency / MHz (although it seems fixed at this value):

 cat /proc/cpuinfo | grep -i mhz
cpu MHz     : 1999.999

image

sanderjo commented 7 years ago

Yeah, the single-core must be the problem: the reduce() with x and y won't work when the list cores_freq has only one entry.

Some hacking:

def get_avarage_cpu_freq():
    with open("/proc/cpuinfo") as cpuinfo:
        cores_freq = []
        for line in cpuinfo:
            if "cpu MHz" in line:
                core_freq = re.findall("\d+\.\d+", line)
                cores_freq += core_freq
        #print "SJ:", cores_freq, len(cores_freq)
        if len(cores_freq) == 1:
                return round(float(cores_freq[0]), 1)
        else:
                return round(reduce(lambda x, y: float(x) + float(y), cores_freq) / len(cores_freq), 1)

Now i have freq line, although only at '100' (not 2000 Mhz): image

sanderjo commented 7 years ago

... or less high-tech and thus easier to read:

def get_avarage_cpu_freq():
    with open("/proc/cpuinfo") as cpuinfo:
        cores = 0
        totalfreq = 0.0
        for line in cpuinfo:
            if "cpu MHz" in line:
                core_freq = re.findall("\d+\.\d+", line)[0]    # only first occurence, to avoid list
                cores += 1
                totalfreq += float(core_freq)
        return round(totalfreq/cores, 1)

Do you want a PR for this?

amanusk commented 7 years ago

You are right, there is a problem with the single core.
Try this instead:

        def get_avarage_cpu_freq():
            with open("/proc/cpuinfo") as cpuinfo:
                cores_freq = []
                for line in cpuinfo:
                    if "cpu MHz" in line:
                        core_freq = re.findall("\d+\.\d+", line)
                        cores_freq += core_freq
            return round(sum(float(x) for x in cores_freq) / len(cores_freq), 1)
sanderjo commented 7 years ago

Yes, that works.

sanderjo commented 7 years ago

FWIW I tried this on my ARM64 system, and there is traceback (but the GUI is OK, so you could ignore this):

sander@nanopineo2:~/git/s-tui/s_tui$ python HelperFunctions.py
Traceback (most recent call last):
  File "HelperFunctions.py", line 172, in <module>
    avg = get_avarage_cpu_freq()
  File "HelperFunctions.py", line 40, in get_avarage_cpu_freq
    return round(sum(float(x) for x in cores_freq) / len(cores_freq), 1)
ZeroDivisionError: integer division or modulo by zero

Cause: the file /proc/cpuinfo of this ARM64 board has zero lines with "Hz" (ignore case) in it ... :-1:

$ cat /proc/cpuinfo | grep -i hz
$
$ cat /proc/cpuinfo 
processor   : 0
Processor   : AArch64 Processor rev 4 (aarch64)
Hardware    : sun50iw1p1
BogoMIPS    : 48.00
Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part    : 0xd03
CPU revision    : 4

processor   : 1
Processor   : AArch64 Processor rev 4 (aarch64)
Hardware    : sun50iw1p1
BogoMIPS    : 48.00
Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part    : 0xd03
CPU revision    : 4

processor   : 2
Processor   : AArch64 Processor rev 4 (aarch64)
Hardware    : sun50iw1p1
BogoMIPS    : 48.00
Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part    : 0xd03
CPU revision    : 4

processor   : 3
Processor   : AArch64 Processor rev 4 (aarch64)
Hardware    : sun50iw1p1
BogoMIPS    : 48.00
Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part    : 0xd03
CPU revision    : 4
amanusk commented 7 years ago

It would be difficult to test a different method without the hardware. If you have a different method of getting the frequency in this system, please try it and issue a PR.

sanderjo commented 7 years ago

The current git version now works on my 1-core VPS. See screenshot. Nice!

FWIW: I now get

sander@haring:~/git/s-tui$ python s_tui/HelperFunctions.py
Traceback (most recent call last):
  File "s_tui/HelperFunctions.py", line 150, in <module>
    avg = get_avarage_cpu_freq()
NameError: name 'get_avarage_cpu_freq' is not defined
sander@haring:~/git/s-tui$ 

image

amanusk commented 7 years ago

Good to hear. Thank you for your help in this.
The error is only when running the module as main, the function was moved. Shouldn't be a problem.
I'll close the issue.

sanderjo commented 7 years ago

If you have a different method of getting the frequency in this system, please try it and issue a PR.

I tried to find a way to find the freq, but so far no luck

FWIW: s_tui now works nice on my 4-core ARM64: image