149 lines
4.1 KiBLFS
Python
149 lines
4.1 KiBLFS
Python
from collections import namedtuple
|
|
import subprocess
|
|
import time
|
|
import _xxsubinterpreters as _interpreters
|
|
import interpreters
|
|
|
|
|
|
def iter_counter(maxi=1000):
|
|
for i in range(1, maxi+1):
|
|
text = '.'
|
|
if i % 100 == 0:
|
|
text += '\n'
|
|
elif i % 20 == 0:
|
|
text += ' '
|
|
elif i % 5 == 0:
|
|
text += ' '
|
|
if i % 1000 == 0:
|
|
text += f'<{i}>\n'
|
|
if i % 500 == 0:
|
|
text += '\n'
|
|
yield i, text
|
|
|
|
|
|
#class MemoryUsage(namedtuple('MemoryUsage', 'kind total used free')):
|
|
#
|
|
# KINDS = ['mem', 'swap']
|
|
# COLUMNS = 'total used free shared buff/cache available'.split()
|
|
#
|
|
# _extra = None
|
|
#
|
|
# @classmethod
|
|
# def from_host(self):
|
|
# proc = subprocess.run('free', shell=True, capture_output=True, text=True)
|
|
# if proc.returncode != 0:
|
|
# return None, None
|
|
# line1, line2, line3 = proc.stdout.splitlines()
|
|
# assert line1.split() == cls.COLUMNS, repr(proc.stdout)
|
|
# mem = cls.parse(line2)
|
|
# swap = cls.parse(line3)
|
|
# return mem, swap
|
|
#
|
|
# @classmethod
|
|
# def parse(cls, line):
|
|
# values = line.split()
|
|
# data = [int(v) for v in values[1:]]
|
|
# if values[0] == 'Mem:':
|
|
# kind = 'mem'
|
|
# extra = data[3:]
|
|
# assert len(extra) == 3, repr(line)
|
|
# elif values[0] == 'Swap:':
|
|
# kind = 'swap'
|
|
# extra = None
|
|
# else:
|
|
# raise NotImplementedError(repr(line))
|
|
# self = cls(kind, *data[:3])
|
|
# self._extra = extra
|
|
# return self
|
|
#
|
|
# @property
|
|
# def shared(self):
|
|
# if self._extra is None:
|
|
# return None
|
|
# return self._extra[0]
|
|
#
|
|
# @property
|
|
# def buff_cache(self):
|
|
# if self._extra is None:
|
|
# return None
|
|
# return self._extra[1]
|
|
#
|
|
# @property
|
|
# def available(self):
|
|
# if self._extra is None:
|
|
# return None
|
|
# return self._extra[2]
|
|
|
|
|
|
def get_memory_usage():
|
|
#return MemoryUsage.from_host()[0].used
|
|
proc = subprocess.run('free', shell=True, capture_output=True, text=True)
|
|
if proc.returncode != 0:
|
|
return None
|
|
cols = 'total used free shared buff/cache available'.split()
|
|
line1, line2, line3 = proc.stdout.splitlines()
|
|
assert line1.split() == cols, repr(proc.stdout)
|
|
assert line2.startswith('Mem:')
|
|
_, total, used, free, *_ = line2.split()
|
|
return int(used)
|
|
|
|
|
|
def create_interpreters(maxnum=1000):
|
|
mem_before = get_memory_usage()
|
|
|
|
# Create the interpreters, one at a time.
|
|
print(f'creating {maxnum} interpreters...')
|
|
total_create_time = 0
|
|
cached = []
|
|
for i, text in iter_counter(maxnum):
|
|
print(text, end='', flush=True)
|
|
start = time.time()
|
|
interp = interpreters.create()
|
|
end = time.time()
|
|
total_create_time += end - start
|
|
# Keep a reference.
|
|
cached.append(interp)
|
|
if i % 100 != 0:
|
|
print()
|
|
print()
|
|
|
|
mem_after = get_memory_usage()
|
|
|
|
# Destroy them, one at a time.
|
|
print(f'destroying {maxnum} interpreters...')
|
|
total_destroy_time = 0
|
|
while cached:
|
|
interp = cached.pop()
|
|
start = time.time()
|
|
#interp.destroy()
|
|
_interpreters.destroy(interp.id)
|
|
end = time.time()
|
|
total_destroy_time += end - start
|
|
print()
|
|
|
|
# Show the results:
|
|
create_time = total_create_time / maxnum
|
|
destroy_time = total_destroy_time / maxnum
|
|
if mem_before and mem_after:
|
|
mem_used = (mem_after - mem_before) / maxnum
|
|
if mem_used >= 1000:
|
|
mem_used = f'{mem_used/1000:,.2f} MB'
|
|
elif mem_used >= 100:
|
|
mem_used = f'{int(mem_used)} kB'
|
|
else:
|
|
mem_used = f'{mem_used:,.2f} kB'
|
|
else:
|
|
mem_used = ' ???'
|
|
print('##### results ######')
|
|
print(f'# interpreters: {maxnum}')
|
|
print(f'avg. create time: {create_time:.3f} s')
|
|
print(f'avg. destroy time: {destroy_time:.3f} s')
|
|
print(f'avg. memory used: {mem_used}')
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
import sys
|
|
maxarg = int(sys.argv[1]) if len(sys.argv) > 1 else 100 # 1000 is too much
|
|
create_interpreters(maxarg)
|