We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ENH] More accurate memory stats using memory.stat in cgroup
Given kernel doc https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt, we may use ``/sys/fs/cgroup/memory/memory.stat`` to provide more accurate memory size estimations in Docker. Note that parsing this file is not supported in ``psutil`` now, thus we may parse it ourselves.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mars/resource.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # Copyright 1999-2018 Alibaba Group Holding Ltd.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #      http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 import os
17 import subprocess  # nosec
18 import sys
19 import time
20 from collections import namedtuple
21 
22 import psutil
23 
24 from .lib import nvutils
25 
26 _proc = psutil.Process()
27 _timer = getattr(time, 'monotonic', time.time)
28 
29 _cpu_use_process_stat = bool(int(os.environ.get('MARS_CPU_USE_PROCESS_STAT', '0').strip('"')))
30 _mem_use_process_stat = bool(int(os.environ.get('MARS_MEM_USE_PROCESS_STAT', '0').strip('"')))
31 
32 if 'MARS_USE_PROCESS_STAT' in os.environ:
33     _cpu_use_process_stat = _mem_use_process_stat = \
34         bool(int(os.environ['MARS_USE_PROCESS_STAT'].strip('"')))
35 
36 if 'MARS_CPU_TOTAL' in os.environ:
37     _cpu_total = int(os.environ['MARS_CPU_TOTAL'].strip('"'))
38 else:
39     _cpu_total = psutil.cpu_count(logical=True)
40 
41 if 'MARS_MEMORY_TOTAL' in os.environ:
42     _mem_total = int(os.environ['MARS_MEMORY_TOTAL'].strip('"'))
43 else:
44     _mem_total = None
45 
46 _virt_memory_stat = namedtuple('virtual_memory', 'total available percent used free')
47 
48 _shm_path = [pt.mountpoint for pt in psutil.disk_partitions(all=True)
49              if pt.mountpoint in ('/tmp', '/dev/shm') and pt.fstype == 'tmpfs']
50 if not _shm_path:
51     _shm_path = None
52 else:
53     _shm_path = _shm_path[0]
54 
55 
56 def virtual_memory():
57     sys_mem = psutil.virtual_memory()
58     if not _mem_use_process_stat:
59         total = sys_mem.total
60         used = sys_mem.used + getattr(sys_mem, 'shared', 0)
61         available = sys_mem.available
62         free = sys_mem.free
63         percent = 100.0 * (total - available) / total
64         return _virt_memory_stat(total, available, percent, used, free)
65     else:
66         used = 0
67         for p in psutil.process_iter():
68             try:
69                 used += p.memory_info().rss
70             except (psutil.NoSuchProcess, psutil.AccessDenied):
71                 pass
72 
73         if _shm_path:
74             shm_stats = psutil.disk_usage(_shm_path)
75             used += shm_stats.used
76 
77         total = min(_mem_total or sys_mem.total, sys_mem.total)
78         # TODO sys_mem.available does not work in container
79         # available = min(sys_mem.available, total - used)
80         available = total - used
81         free = min(sys_mem.free, total - used)
82         percent = 100.0 * (total - available) / total
83         return _virt_memory_stat(total, available, percent, used, free)
84 
85 
86 def cpu_count():
87     return _cpu_total
88 
89 
90 _last_cpu_measure = None
91 
92 
93 def _take_process_cpu_snapshot():
94     num_cpus = cpu_count() or 1
95 
96     def timer():
97         return _timer() * num_cpus
98 
99     processes = [p for p in psutil.process_iter() if p.pid != _proc.pid]
100 
101     pts = dict()
102     sts = dict()
103     for p in processes:
104         try:
105             pts[p.pid] = p.cpu_times()
106             sts[p.pid] = timer()
107         except (psutil.NoSuchProcess, psutil.AccessDenied):
108             pass
109 
110     pts[_proc.pid] = _proc.cpu_times()
111     sts[_proc.pid] = timer()
112     return pts, sts
113 
114 
115 def cpu_percent():
116     global _last_cpu_measure
117     if not _cpu_use_process_stat:
118         return sum(psutil.cpu_percent(percpu=True))
119 
120     num_cpus = cpu_count() or 1
121     pts, sts = _take_process_cpu_snapshot()
122 
123     if _last_cpu_measure is None:
124         _last_cpu_measure = (pts, sts)
125         return None
126 
127     old_pts, old_sts = _last_cpu_measure
128 
129     percents = []
130     for pid in pts:
131         if pid not in old_pts:
132             continue
133         pt1 = old_pts[pid]
134         pt2 = pts[pid]
135         delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system)
136         delta_time = sts[pid] - old_sts[pid]
137 
138         try:
139             overall_cpus_percent = (delta_proc / delta_time) * 100
140         except ZeroDivisionError:
141             percents.append(0.0)
142         else:
143             single_cpu_percent = overall_cpus_percent * num_cpus
144             percents.append(single_cpu_percent)
145     _last_cpu_measure = (pts, sts)
146     return round(sum(percents), 1)
147 
148 
149 def disk_usage(d):
150     return psutil.disk_usage(d)
151 
152 
153 def iowait():
154     cpu_percent = psutil.cpu_times_percent()
155     try:
156         return cpu_percent.iowait
157     except AttributeError:
158         return None
159 
160 
161 _last_disk_io_meta = None
162 _win_diskperf_called = False
163 
164 
165 def disk_io_usage():
166     global _last_disk_io_meta, _win_diskperf_called
167 
168     # Needed by psutil.disk_io_counters() under newer version of Windows.
169     # diskperf -y need to be called or no disk information can be found.
170     if sys.platform == 'win32' and not _win_diskperf_called:  # pragma: no cover
171         CREATE_NO_WINDOW = 0x08000000
172         try:
173             proc = subprocess.Popen(['diskperf', '-y'], shell=False,
174                                     creationflags=CREATE_NO_WINDOW)  # nosec
175             proc.wait()
176         except (subprocess.CalledProcessError, OSError):
177             pass
178         _win_diskperf_called = True
179 
180     disk_counters = psutil.disk_io_counters()
181     tst = time.time()
182 
183     read_bytes = disk_counters.read_bytes
184     write_bytes = disk_counters.write_bytes
185     if _last_disk_io_meta is None:
186         _last_disk_io_meta = (read_bytes, write_bytes, tst)
187         return None
188 
189     last_read_bytes, last_write_bytes, last_time = _last_disk_io_meta
190     delta_time = tst - last_time
191     read_speed = (read_bytes - last_read_bytes) / delta_time
192     write_speed = (write_bytes - last_write_bytes) / delta_time
193 
194     _last_disk_io_meta = (read_bytes, write_bytes, tst)
195     return read_speed, write_speed
196 
197 
198 _last_net_io_meta = None
199 
200 
201 def net_io_usage():
202     global _last_net_io_meta
203 
204     net_counters = psutil.net_io_counters()
205     tst = time.time()
206 
207     send_bytes = net_counters.bytes_sent
208     recv_bytes = net_counters.bytes_recv
209     if _last_net_io_meta is None:
210         _last_net_io_meta = (send_bytes, recv_bytes, tst)
211         return None
212 
213     last_send_bytes, last_recv_bytes, last_time = _last_net_io_meta
214     delta_time = tst - last_time
215     recv_speed = (recv_bytes - last_recv_bytes) / delta_time
216     send_speed = (send_bytes - last_send_bytes) / delta_time
217 
218     _last_net_io_meta = (send_bytes, recv_bytes, tst)
219     return recv_speed, send_speed
220 
221 
222 _cuda_info = namedtuple('cuda_info', 'driver_version cuda_version products gpu_count')
223 _cuda_card_stat = namedtuple('cuda_card_stat', 'product_name gpu_usage temperature fb_mem_info')
224 
225 
226 def cuda_info():  # pragma: no cover
227     driver_info = nvutils.get_driver_info()
228     if not driver_info:
229         return
230     gpu_count = nvutils.get_device_count()
231     return _cuda_info(
232         driver_version=driver_info.driver_version,
233         cuda_version=driver_info.cuda_version,
234         products=[nvutils.get_device_info(idx).name for idx in range(gpu_count)],
235         gpu_count=gpu_count,
236     )
237 
238 
239 def cuda_card_stats():  # pragma: no cover
240     infos = []
241     device_count = nvutils.get_device_count()
242     if not device_count:
243         return
244     for device_idx in range(device_count):
245         device_info = nvutils.get_device_info(device_idx)
246         device_status = nvutils.get_device_status(device_idx)
247 
248         infos.append(_cuda_card_stat(
249             product_name=device_info.name,
250             gpu_usage=device_status.gpu_util,
251             temperature=device_status.temperature,
252             fb_mem_info=_virt_memory_stat(
253                 total=device_status.fb_total_mem, used=device_status.fb_used_mem,
254                 free=device_status.fb_free_mem, available=device_status.fb_free_mem,
255                 percent=device_status.mem_util,
256             )
257         ))
258     return infos
259
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mars/resource.py b/mars/resource.py
--- a/mars/resource.py
+++ b/mars/resource.py
@@ -23,22 +23,25 @@
 
 from .lib import nvutils
 
+CGROUP_MEM_STAT_FILE = '/sys/fs/cgroup/memory/memory.stat'
+
 _proc = psutil.Process()
 _timer = getattr(time, 'monotonic', time.time)
 
 _cpu_use_process_stat = bool(int(os.environ.get('MARS_CPU_USE_PROCESS_STAT', '0').strip('"')))
 _mem_use_process_stat = bool(int(os.environ.get('MARS_MEM_USE_PROCESS_STAT', '0').strip('"')))
+_mem_use_cgroup_stat = bool(int(os.environ.get('MARS_MEM_USE_CGROUP_STAT', '0').strip('"')))
 
 if 'MARS_USE_PROCESS_STAT' in os.environ:
     _cpu_use_process_stat = _mem_use_process_stat = \
         bool(int(os.environ['MARS_USE_PROCESS_STAT'].strip('"')))
 
-if 'MARS_CPU_TOTAL' in os.environ:
+if _cpu_use_process_stat and 'MARS_CPU_TOTAL' in os.environ:
     _cpu_total = int(os.environ['MARS_CPU_TOTAL'].strip('"'))
 else:
     _cpu_total = psutil.cpu_count(logical=True)
 
-if 'MARS_MEMORY_TOTAL' in os.environ:
+if _mem_use_process_stat and 'MARS_MEMORY_TOTAL' in os.environ:
     _mem_total = int(os.environ['MARS_MEMORY_TOTAL'].strip('"'))
 else:
     _mem_total = None
@@ -53,9 +56,28 @@
     _shm_path = _shm_path[0]
 
 
+def _read_cgroup_stat_file():
+    with open(CGROUP_MEM_STAT_FILE, 'r') as cg_file:
+        contents = cg_file.read()
+    kvs = dict()
+    for l in contents.splitlines():
+        parts = l.split(' ')
+        if len(parts) == 2:
+            kvs[parts[0]] = int(parts[1])
+    return kvs
+
+
 def virtual_memory():
     sys_mem = psutil.virtual_memory()
-    if not _mem_use_process_stat:
+    if _mem_use_cgroup_stat:
+        # see section 5.5 in https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt
+        cgroup_mem_info = _read_cgroup_stat_file()
+        total = cgroup_mem_info['hierarchical_memory_limit']
+        used = cgroup_mem_info['cache'] + cgroup_mem_info['rss'] + cgroup_mem_info.get('swap', 0)
+        available = free = total - used
+        percent = 100.0 * (total - available) / total
+        return _virt_memory_stat(total, available, percent, used, free)
+    elif not _mem_use_process_stat:
         total = sys_mem.total
         used = sys_mem.used + getattr(sys_mem, 'shared', 0)
         available = sys_mem.available

{"golden_diff": "diff --git a/mars/resource.py b/mars/resource.py\n--- a/mars/resource.py\n+++ b/mars/resource.py\n@@ -23,22 +23,25 @@\n \n from .lib import nvutils\n \n+CGROUP_MEM_STAT_FILE = '/sys/fs/cgroup/memory/memory.stat'\n+\n _proc = psutil.Process()\n _timer = getattr(time, 'monotonic', time.time)\n \n _cpu_use_process_stat = bool(int(os.environ.get('MARS_CPU_USE_PROCESS_STAT', '0').strip('\"')))\n _mem_use_process_stat = bool(int(os.environ.get('MARS_MEM_USE_PROCESS_STAT', '0').strip('\"')))\n+_mem_use_cgroup_stat = bool(int(os.environ.get('MARS_MEM_USE_CGROUP_STAT', '0').strip('\"')))\n \n if 'MARS_USE_PROCESS_STAT' in os.environ:\n     _cpu_use_process_stat = _mem_use_process_stat = \\\n         bool(int(os.environ['MARS_USE_PROCESS_STAT'].strip('\"')))\n \n-if 'MARS_CPU_TOTAL' in os.environ:\n+if _cpu_use_process_stat and 'MARS_CPU_TOTAL' in os.environ:\n     _cpu_total = int(os.environ['MARS_CPU_TOTAL'].strip('\"'))\n else:\n     _cpu_total = psutil.cpu_count(logical=True)\n \n-if 'MARS_MEMORY_TOTAL' in os.environ:\n+if _mem_use_process_stat and 'MARS_MEMORY_TOTAL' in os.environ:\n     _mem_total = int(os.environ['MARS_MEMORY_TOTAL'].strip('\"'))\n else:\n     _mem_total = None\n@@ -53,9 +56,28 @@\n     _shm_path = _shm_path[0]\n \n \n+def _read_cgroup_stat_file():\n+    with open(CGROUP_MEM_STAT_FILE, 'r') as cg_file:\n+        contents = cg_file.read()\n+    kvs = dict()\n+    for l in contents.splitlines():\n+        parts = l.split(' ')\n+        if len(parts) == 2:\n+            kvs[parts[0]] = int(parts[1])\n+    return kvs\n+\n+\n def virtual_memory():\n     sys_mem = psutil.virtual_memory()\n-    if not _mem_use_process_stat:\n+    if _mem_use_cgroup_stat:\n+        # see section 5.5 in https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt\n+        cgroup_mem_info = _read_cgroup_stat_file()\n+        total = cgroup_mem_info['hierarchical_memory_limit']\n+        used = cgroup_mem_info['cache'] + cgroup_mem_info['rss'] + cgroup_mem_info.get('swap', 0)\n+        available = free = total - used\n+        percent = 100.0 * (total - available) / total\n+        return _virt_memory_stat(total, available, percent, used, free)\n+    elif not _mem_use_process_stat:\n         total = sys_mem.total\n         used = sys_mem.used + getattr(sys_mem, 'shared', 0)\n         available = sys_mem.available\n", "issue": "[ENH] More accurate memory stats using memory.stat in cgroup\nGiven kernel doc https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt, we may use ``/sys/fs/cgroup/memory/memory.stat`` to provide more accurate memory size estimations in Docker. Note that parsing this file is not supported in ``psutil`` now, thus we may parse it ourselves.\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport os\nimport subprocess  # nosec\nimport sys\nimport time\nfrom collections import namedtuple\n\nimport psutil\n\nfrom .lib import nvutils\n\n_proc = psutil.Process()\n_timer = getattr(time, 'monotonic', time.time)\n\n_cpu_use_process_stat = bool(int(os.environ.get('MARS_CPU_USE_PROCESS_STAT', '0').strip('\"')))\n_mem_use_process_stat = bool(int(os.environ.get('MARS_MEM_USE_PROCESS_STAT', '0').strip('\"')))\n\nif 'MARS_USE_PROCESS_STAT' in os.environ:\n    _cpu_use_process_stat = _mem_use_process_stat = \\\n        bool(int(os.environ['MARS_USE_PROCESS_STAT'].strip('\"')))\n\nif 'MARS_CPU_TOTAL' in os.environ:\n    _cpu_total = int(os.environ['MARS_CPU_TOTAL'].strip('\"'))\nelse:\n    _cpu_total = psutil.cpu_count(logical=True)\n\nif 'MARS_MEMORY_TOTAL' in os.environ:\n    _mem_total = int(os.environ['MARS_MEMORY_TOTAL'].strip('\"'))\nelse:\n    _mem_total = None\n\n_virt_memory_stat = namedtuple('virtual_memory', 'total available percent used free')\n\n_shm_path = [pt.mountpoint for pt in psutil.disk_partitions(all=True)\n             if pt.mountpoint in ('/tmp', '/dev/shm') and pt.fstype == 'tmpfs']\nif not _shm_path:\n    _shm_path = None\nelse:\n    _shm_path = _shm_path[0]\n\n\ndef virtual_memory():\n    sys_mem = psutil.virtual_memory()\n    if not _mem_use_process_stat:\n        total = sys_mem.total\n        used = sys_mem.used + getattr(sys_mem, 'shared', 0)\n        available = sys_mem.available\n        free = sys_mem.free\n        percent = 100.0 * (total - available) / total\n        return _virt_memory_stat(total, available, percent, used, free)\n    else:\n        used = 0\n        for p in psutil.process_iter():\n            try:\n                used += p.memory_info().rss\n            except (psutil.NoSuchProcess, psutil.AccessDenied):\n                pass\n\n        if _shm_path:\n            shm_stats = psutil.disk_usage(_shm_path)\n            used += shm_stats.used\n\n        total = min(_mem_total or sys_mem.total, sys_mem.total)\n        # TODO sys_mem.available does not work in container\n        # available = min(sys_mem.available, total - used)\n        available = total - used\n        free = min(sys_mem.free, total - used)\n        percent = 100.0 * (total - available) / total\n        return _virt_memory_stat(total, available, percent, used, free)\n\n\ndef cpu_count():\n    return _cpu_total\n\n\n_last_cpu_measure = None\n\n\ndef _take_process_cpu_snapshot():\n    num_cpus = cpu_count() or 1\n\n    def timer():\n        return _timer() * num_cpus\n\n    processes = [p for p in psutil.process_iter() if p.pid != _proc.pid]\n\n    pts = dict()\n    sts = dict()\n    for p in processes:\n        try:\n            pts[p.pid] = p.cpu_times()\n            sts[p.pid] = timer()\n        except (psutil.NoSuchProcess, psutil.AccessDenied):\n            pass\n\n    pts[_proc.pid] = _proc.cpu_times()\n    sts[_proc.pid] = timer()\n    return pts, sts\n\n\ndef cpu_percent():\n    global _last_cpu_measure\n    if not _cpu_use_process_stat:\n        return sum(psutil.cpu_percent(percpu=True))\n\n    num_cpus = cpu_count() or 1\n    pts, sts = _take_process_cpu_snapshot()\n\n    if _last_cpu_measure is None:\n        _last_cpu_measure = (pts, sts)\n        return None\n\n    old_pts, old_sts = _last_cpu_measure\n\n    percents = []\n    for pid in pts:\n        if pid not in old_pts:\n            continue\n        pt1 = old_pts[pid]\n        pt2 = pts[pid]\n        delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system)\n        delta_time = sts[pid] - old_sts[pid]\n\n        try:\n            overall_cpus_percent = (delta_proc / delta_time) * 100\n        except ZeroDivisionError:\n            percents.append(0.0)\n        else:\n            single_cpu_percent = overall_cpus_percent * num_cpus\n            percents.append(single_cpu_percent)\n    _last_cpu_measure = (pts, sts)\n    return round(sum(percents), 1)\n\n\ndef disk_usage(d):\n    return psutil.disk_usage(d)\n\n\ndef iowait():\n    cpu_percent = psutil.cpu_times_percent()\n    try:\n        return cpu_percent.iowait\n    except AttributeError:\n        return None\n\n\n_last_disk_io_meta = None\n_win_diskperf_called = False\n\n\ndef disk_io_usage():\n    global _last_disk_io_meta, _win_diskperf_called\n\n    # Needed by psutil.disk_io_counters() under newer version of Windows.\n    # diskperf -y need to be called or no disk information can be found.\n    if sys.platform == 'win32' and not _win_diskperf_called:  # pragma: no cover\n        CREATE_NO_WINDOW = 0x08000000\n        try:\n            proc = subprocess.Popen(['diskperf', '-y'], shell=False,\n                                    creationflags=CREATE_NO_WINDOW)  # nosec\n            proc.wait()\n        except (subprocess.CalledProcessError, OSError):\n            pass\n        _win_diskperf_called = True\n\n    disk_counters = psutil.disk_io_counters()\n    tst = time.time()\n\n    read_bytes = disk_counters.read_bytes\n    write_bytes = disk_counters.write_bytes\n    if _last_disk_io_meta is None:\n        _last_disk_io_meta = (read_bytes, write_bytes, tst)\n        return None\n\n    last_read_bytes, last_write_bytes, last_time = _last_disk_io_meta\n    delta_time = tst - last_time\n    read_speed = (read_bytes - last_read_bytes) / delta_time\n    write_speed = (write_bytes - last_write_bytes) / delta_time\n\n    _last_disk_io_meta = (read_bytes, write_bytes, tst)\n    return read_speed, write_speed\n\n\n_last_net_io_meta = None\n\n\ndef net_io_usage():\n    global _last_net_io_meta\n\n    net_counters = psutil.net_io_counters()\n    tst = time.time()\n\n    send_bytes = net_counters.bytes_sent\n    recv_bytes = net_counters.bytes_recv\n    if _last_net_io_meta is None:\n        _last_net_io_meta = (send_bytes, recv_bytes, tst)\n        return None\n\n    last_send_bytes, last_recv_bytes, last_time = _last_net_io_meta\n    delta_time = tst - last_time\n    recv_speed = (recv_bytes - last_recv_bytes) / delta_time\n    send_speed = (send_bytes - last_send_bytes) / delta_time\n\n    _last_net_io_meta = (send_bytes, recv_bytes, tst)\n    return recv_speed, send_speed\n\n\n_cuda_info = namedtuple('cuda_info', 'driver_version cuda_version products gpu_count')\n_cuda_card_stat = namedtuple('cuda_card_stat', 'product_name gpu_usage temperature fb_mem_info')\n\n\ndef cuda_info():  # pragma: no cover\n    driver_info = nvutils.get_driver_info()\n    if not driver_info:\n        return\n    gpu_count = nvutils.get_device_count()\n    return _cuda_info(\n        driver_version=driver_info.driver_version,\n        cuda_version=driver_info.cuda_version,\n        products=[nvutils.get_device_info(idx).name for idx in range(gpu_count)],\n        gpu_count=gpu_count,\n    )\n\n\ndef cuda_card_stats():  # pragma: no cover\n    infos = []\n    device_count = nvutils.get_device_count()\n    if not device_count:\n        return\n    for device_idx in range(device_count):\n        device_info = nvutils.get_device_info(device_idx)\n        device_status = nvutils.get_device_status(device_idx)\n\n        infos.append(_cuda_card_stat(\n            product_name=device_info.name,\n            gpu_usage=device_status.gpu_util,\n            temperature=device_status.temperature,\n            fb_mem_info=_virt_memory_stat(\n                total=device_status.fb_total_mem, used=device_status.fb_used_mem,\n                free=device_status.fb_free_mem, available=device_status.fb_free_mem,\n                percent=device_status.mem_util,\n            )\n        ))\n    return infos\n", "path": "mars/resource.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport os\nimport subprocess  # nosec\nimport sys\nimport time\nfrom collections import namedtuple\n\nimport psutil\n\nfrom .lib import nvutils\n\nCGROUP_MEM_STAT_FILE = '/sys/fs/cgroup/memory/memory.stat'\n\n_proc = psutil.Process()\n_timer = getattr(time, 'monotonic', time.time)\n\n_cpu_use_process_stat = bool(int(os.environ.get('MARS_CPU_USE_PROCESS_STAT', '0').strip('\"')))\n_mem_use_process_stat = bool(int(os.environ.get('MARS_MEM_USE_PROCESS_STAT', '0').strip('\"')))\n_mem_use_cgroup_stat = bool(int(os.environ.get('MARS_MEM_USE_CGROUP_STAT', '0').strip('\"')))\n\nif 'MARS_USE_PROCESS_STAT' in os.environ:\n    _cpu_use_process_stat = _mem_use_process_stat = \\\n        bool(int(os.environ['MARS_USE_PROCESS_STAT'].strip('\"')))\n\nif _cpu_use_process_stat and 'MARS_CPU_TOTAL' in os.environ:\n    _cpu_total = int(os.environ['MARS_CPU_TOTAL'].strip('\"'))\nelse:\n    _cpu_total = psutil.cpu_count(logical=True)\n\nif _mem_use_process_stat and 'MARS_MEMORY_TOTAL' in os.environ:\n    _mem_total = int(os.environ['MARS_MEMORY_TOTAL'].strip('\"'))\nelse:\n    _mem_total = None\n\n_virt_memory_stat = namedtuple('virtual_memory', 'total available percent used free')\n\n_shm_path = [pt.mountpoint for pt in psutil.disk_partitions(all=True)\n             if pt.mountpoint in ('/tmp', '/dev/shm') and pt.fstype == 'tmpfs']\nif not _shm_path:\n    _shm_path = None\nelse:\n    _shm_path = _shm_path[0]\n\n\ndef _read_cgroup_stat_file():\n    with open(CGROUP_MEM_STAT_FILE, 'r') as cg_file:\n        contents = cg_file.read()\n    kvs = dict()\n    for l in contents.splitlines():\n        parts = l.split(' ')\n        if len(parts) == 2:\n            kvs[parts[0]] = int(parts[1])\n    return kvs\n\n\ndef virtual_memory():\n    sys_mem = psutil.virtual_memory()\n    if _mem_use_cgroup_stat:\n        # see section 5.5 in https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt\n        cgroup_mem_info = _read_cgroup_stat_file()\n        total = cgroup_mem_info['hierarchical_memory_limit']\n        used = cgroup_mem_info['cache'] + cgroup_mem_info['rss'] + cgroup_mem_info.get('swap', 0)\n        available = free = total - used\n        percent = 100.0 * (total - available) / total\n        return _virt_memory_stat(total, available, percent, used, free)\n    elif not _mem_use_process_stat:\n        total = sys_mem.total\n        used = sys_mem.used + getattr(sys_mem, 'shared', 0)\n        available = sys_mem.available\n        free = sys_mem.free\n        percent = 100.0 * (total - available) / total\n        return _virt_memory_stat(total, available, percent, used, free)\n    else:\n        used = 0\n        for p in psutil.process_iter():\n            try:\n                used += p.memory_info().rss\n            except (psutil.NoSuchProcess, psutil.AccessDenied):\n                pass\n\n        if _shm_path:\n            shm_stats = psutil.disk_usage(_shm_path)\n            used += shm_stats.used\n\n        total = min(_mem_total or sys_mem.total, sys_mem.total)\n        # TODO sys_mem.available does not work in container\n        # available = min(sys_mem.available, total - used)\n        available = total - used\n        free = min(sys_mem.free, total - used)\n        percent = 100.0 * (total - available) / total\n        return _virt_memory_stat(total, available, percent, used, free)\n\n\ndef cpu_count():\n    return _cpu_total\n\n\n_last_cpu_measure = None\n\n\ndef _take_process_cpu_snapshot():\n    num_cpus = cpu_count() or 1\n\n    def timer():\n        return _timer() * num_cpus\n\n    processes = [p for p in psutil.process_iter() if p.pid != _proc.pid]\n\n    pts = dict()\n    sts = dict()\n    for p in processes:\n        try:\n            pts[p.pid] = p.cpu_times()\n            sts[p.pid] = timer()\n        except (psutil.NoSuchProcess, psutil.AccessDenied):\n            pass\n\n    pts[_proc.pid] = _proc.cpu_times()\n    sts[_proc.pid] = timer()\n    return pts, sts\n\n\ndef cpu_percent():\n    global _last_cpu_measure\n    if not _cpu_use_process_stat:\n        return sum(psutil.cpu_percent(percpu=True))\n\n    num_cpus = cpu_count() or 1\n    pts, sts = _take_process_cpu_snapshot()\n\n    if _last_cpu_measure is None:\n        _last_cpu_measure = (pts, sts)\n        return None\n\n    old_pts, old_sts = _last_cpu_measure\n\n    percents = []\n    for pid in pts:\n        if pid not in old_pts:\n            continue\n        pt1 = old_pts[pid]\n        pt2 = pts[pid]\n        delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system)\n        delta_time = sts[pid] - old_sts[pid]\n\n        try:\n            overall_cpus_percent = (delta_proc / delta_time) * 100\n        except ZeroDivisionError:\n            percents.append(0.0)\n        else:\n            single_cpu_percent = overall_cpus_percent * num_cpus\n            percents.append(single_cpu_percent)\n    _last_cpu_measure = (pts, sts)\n    return round(sum(percents), 1)\n\n\ndef disk_usage(d):\n    return psutil.disk_usage(d)\n\n\ndef iowait():\n    cpu_percent = psutil.cpu_times_percent()\n    try:\n        return cpu_percent.iowait\n    except AttributeError:\n        return None\n\n\n_last_disk_io_meta = None\n_win_diskperf_called = False\n\n\ndef disk_io_usage():\n    global _last_disk_io_meta, _win_diskperf_called\n\n    # Needed by psutil.disk_io_counters() under newer version of Windows.\n    # diskperf -y need to be called or no disk information can be found.\n    if sys.platform == 'win32' and not _win_diskperf_called:  # pragma: no cover\n        CREATE_NO_WINDOW = 0x08000000\n        try:\n            proc = subprocess.Popen(['diskperf', '-y'], shell=False,\n                                    creationflags=CREATE_NO_WINDOW)  # nosec\n            proc.wait()\n        except (subprocess.CalledProcessError, OSError):\n            pass\n        _win_diskperf_called = True\n\n    disk_counters = psutil.disk_io_counters()\n    tst = time.time()\n\n    read_bytes = disk_counters.read_bytes\n    write_bytes = disk_counters.write_bytes\n    if _last_disk_io_meta is None:\n        _last_disk_io_meta = (read_bytes, write_bytes, tst)\n        return None\n\n    last_read_bytes, last_write_bytes, last_time = _last_disk_io_meta\n    delta_time = tst - last_time\n    read_speed = (read_bytes - last_read_bytes) / delta_time\n    write_speed = (write_bytes - last_write_bytes) / delta_time\n\n    _last_disk_io_meta = (read_bytes, write_bytes, tst)\n    return read_speed, write_speed\n\n\n_last_net_io_meta = None\n\n\ndef net_io_usage():\n    global _last_net_io_meta\n\n    net_counters = psutil.net_io_counters()\n    tst = time.time()\n\n    send_bytes = net_counters.bytes_sent\n    recv_bytes = net_counters.bytes_recv\n    if _last_net_io_meta is None:\n        _last_net_io_meta = (send_bytes, recv_bytes, tst)\n        return None\n\n    last_send_bytes, last_recv_bytes, last_time = _last_net_io_meta\n    delta_time = tst - last_time\n    recv_speed = (recv_bytes - last_recv_bytes) / delta_time\n    send_speed = (send_bytes - last_send_bytes) / delta_time\n\n    _last_net_io_meta = (send_bytes, recv_bytes, tst)\n    return recv_speed, send_speed\n\n\n_cuda_info = namedtuple('cuda_info', 'driver_version cuda_version products gpu_count')\n_cuda_card_stat = namedtuple('cuda_card_stat', 'product_name gpu_usage temperature fb_mem_info')\n\n\ndef cuda_info():  # pragma: no cover\n    driver_info = nvutils.get_driver_info()\n    if not driver_info:\n        return\n    gpu_count = nvutils.get_device_count()\n    return _cuda_info(\n        driver_version=driver_info.driver_version,\n        cuda_version=driver_info.cuda_version,\n        products=[nvutils.get_device_info(idx).name for idx in range(gpu_count)],\n        gpu_count=gpu_count,\n    )\n\n\ndef cuda_card_stats():  # pragma: no cover\n    infos = []\n    device_count = nvutils.get_device_count()\n    if not device_count:\n        return\n    for device_idx in range(device_count):\n        device_info = nvutils.get_device_info(device_idx)\n        device_status = nvutils.get_device_status(device_idx)\n\n        infos.append(_cuda_card_stat(\n            product_name=device_info.name,\n            gpu_usage=device_status.gpu_util,\n            temperature=device_status.temperature,\n            fb_mem_info=_virt_memory_stat(\n                total=device_status.fb_total_mem, used=device_status.fb_used_mem,\n                free=device_status.fb_free_mem, available=device_status.fb_free_mem,\n                percent=device_status.mem_util,\n            )\n        ))\n    return infos\n", "path": "mars/resource.py"}]}