2016-11-27 2 views
0

私はフラスコのアプリケーションは、それが現在のパーセンテージとして使用しているどのくらいのCP​​Uとメモリを報告したいと思いますが返されますcpu_percentのために0.0を返します。しかしpsutilのcpu_percentは常に0.0

$ while true; do curl http://127.0.0.1:8000/test &>/dev/null; done & 
$ curl http://127.0.0.1:8000/stats 
{ 
    "cpu_percent": 0.0, 
    "cpu_times": [ 
    4.97, 
    1.28, 
    0.0, 
    0.0 
    ], 
    "mem_info": [ 
    19652608, 
    243068928, 
    4292608, 
    4096, 
    0, 
    14675968, 
    0 
    ], 
    "mem_percent": 1.8873787935409003 
} 

、私は手動でipython使用してチェックした場合:

import psutil 
p = psutil.Process(10993) 
p.cpu_percent() 

これは、0.0より大きい値を正しく返します。

+0

これは一種の自己参照です。アプリケーションは余分なサイクルとメモリを消費し、すでに消費されているサイクル数とメモリ数を報告するだけです。これは、他のプロセス監視アプリケーションおよびサービスで実現できます。なぜあなたのアプリでこれをしたいですか? – Makoto

答えて

1

"p = psutil.Process()"を(stat()関数の外で)グローバルに定義するだけです。 cpu_percent()は前回の呼び出しからのCPU時間を記録しており、それがパーセンテージをどのように決定できるかを示しています。

計算のパーセンテージは時間の経過とともに2つの値を比較する必要があるため、時間が経過する必要があるため、最初の呼び出しは常に0.0になります。

1

Giampaoloが指摘したように、Processのインスタンスは、以前の呼び出しに基づいてインスタンスを追跡するために状態を追跡するため、グローバルスコープにする必要があります。

CPUのパーセンテージはある瞬間から別の瞬間に大きく変動する可能性があります。特に、その間に計算された時間が非常に混乱する場合があります。設定された時間範囲に渡ってCPUの平均パーセンテージを計算するバックグラウンドスレッドを使用する方がよいでしょう。

私が手元に起こったいくつかのコードが対象となり得る:

from __future__ import print_function 

import os 
import time 
import atexit 

import threading 

try: 
    import Queue as queue 
except ImportError: 
    import queue 

import psutil 

_running = False 
_queue = queue.Queue() 
_lock = threading.Lock() 

_cpu_percentage = 1800 * [0.0] 
_processes = {} 

def _monitor(): 
    global _cpu_percentage 
    global _processes 

    while True: 
     marker = time.time() 

     total = 0.0 
     pids = psutil.pids() 

     processes = {} 

     for pid in pids: 
      process = _processes.get(pid) 
      if process is None: 
       process = psutil.Process(pid) 
      processes[pid] = process 
      total += process.cpu_percent() 

     _processes = processes 

     _cpu_percentage.insert(0, total) 

     _cpu_percentage = _cpu_percentage[:1800] 

     duration = max(0.0, 1.0 - (time.time() - marker)) 

     try: 
      return _queue.get(timeout=duration) 

     except queue.Empty: 
      pass 

_thread = threading.Thread(target=_monitor) 
_thread.setDaemon(True) 

def _exiting(): 
    try: 
     _queue.put(True) 
    except Exception: 
     pass 
    _thread.join() 

def track_changes(path): 
    if not path in _files: 
     _files.append(path) 

def start_monitor(): 
    global _running 
    _lock.acquire() 
    if not _running: 
     prefix = 'monitor (pid=%d):' % os.getpid() 
     print('%s Starting CPU monitor.' % prefix) 
     _running = True 
     _thread.start() 
     atexit.register(_exiting) 
    _lock.release() 

def cpu_averages(): 
    values = _cpu_percentage[:60] 

    averages = {} 

    def average(secs): 
     return min(100.0, sum(values[:secs])/secs) 

    averages['cpu.average.1s'] = average(1) 
    averages['cpu.average.5s'] = average(5) 
    averages['cpu.average.15s'] = average(15) 
    averages['cpu.average.30s'] = average(30) 
    averages['cpu.average.1m'] = average(60) 
    averages['cpu.average.5m'] = average(300) 
    averages['cpu.average.15m'] = average(900) 
    averages['cpu.average.30m'] = average(1800) 

    return averages 

私は削除これで他のものを持っていたので、できればどのような残っているのは、使用可能な状態のままです。

ファイルを使用するには、ファイルmonitor.pyに追加し、メインにモジュールをインポートし、監視ループを開始します。あなたが理にかなっていると思うの期間の

monitor.cpu_averages() 

と抽出値:各要求の呼び出しに続いて

import monitor 
monitor.start_monitor() 

関連する問題