def test_ramused(self): v1 = memory.total_ram() - memory.free_ram() v2 = memory.used_ram() self.assertApproximates(v1, v2, 5)
def fake_render(): process = psutil.Process() memory_used_at_start = memory.used_ram() logger.info("sys.argv: %r", sys.argv) # build parser parser = argparse.ArgumentParser( description="Very basic command line tool which vaguely simulates a " "render.") parser.add_argument( "--ram", type=int, default=25, help="How much ram in megabytes the fake command should consume") parser.add_argument( "--duration", type=int, default=5, help="How many seconds it should take to run this command") parser.add_argument( "--return-code", type=int, action="append", default=[0], help="The return code to return, declaring this flag multiple times " "will result in a random return code. [default: %(default)s]") parser.add_argument( "--duration-jitter", type=int, default=5, help="Randomly add or subtract this amount to the total duration") parser.add_argument( "--ram-jitter", type=int, default=None, help="Randomly add or subtract this amount to the ram") parser.add_argument( "-s", "--start", type=int, required=True, help="The start frame. If no other flags are provided this will also " "be the end frame.") parser.add_argument( "-e", "--end", type=int, help="The end frame") parser.add_argument( "-b", "--by", type=int, help="The by frame", default=1) parser.add_argument( "--spew", default=False, action="store_true", help="Spews lots of random output to stdout which is generally " "a decent stress test for log processing issues. Do note however " "that this will disable the code which is consuming extra CPU " "cycles. Also, use this option with care as it can generate " "several gigabytes of data per frame.") parser.add_argument( "--segfault", action="store_true", help="If provided then there's a 25%% chance of causing a segmentation " "fault.") args = parser.parse_args() if args.end is None: args.end = args.start if args.ram_jitter is None: args.ram_jitter = int(args.ram / 2) assert args.end >= args.start and args.by >= 1 random_output = None if args.spew: random_output = list(os.urandom(1024).encode("hex") for _ in xrange(15)) errors = 0 if isinstance(args.start, float): logger.warning( "Truncating `start` to an integer (float not yet supported)") args.start = int(args.start) if isinstance(args.end, float): logger.warning( "Truncating `end` to an integer (float not yet supported)") args.end = int(args.end) if isinstance(args.by, float): logger.warning( "Truncating `by` to an integer (float not yet supported)") args.by = int(args.by) for frame in xrange(args.start, args.end + 1, args.by): duration = args.duration + randint( -args.duration_jitter, args.duration_jitter) ram_usage = max( 0, args.ram + randint(-args.ram_jitter, args.ram_jitter)) logger.info("Starting frame %04d", frame) # Warn if we're already using more memory if ram_usage < memory_used_at_start: logger.warning( "Memory usage starting up is higher than the value provided, " "defaulting --ram to %s", memory_used_at_start) # Consume the requested memory (or close to) # TODO: this is unrealistic, majority of renders don't eat ram like this memory_to_consume = int(ram_usage - memory.used_ram()) big_string = " " * 1048576 # ~ 1MB of memory usage if memory_to_consume > 0: start = time.time() logger.debug( "Consuming %s megabytes of memory", memory_to_consume) try: big_string += big_string * memory_to_consume except MemoryError: logger.error("Cannot render, not enough memory") errors += 1 continue logger.debug( "Finished consumption of memory in %s seconds. Off from " "target memory usage by %sMB.", time.time() - start, memory.used_ram() - ram_usage) # Decently guaranteed to cause a segmentation fault. Originally from: # https://wiki.python.org/moin/CrashingPython#ctypes if args.segfault and random() > .25: i = ctypes.c_char('a') j = ctypes.pointer(i) c = 0 while True: j[c] = 'a' c += 1 j # Continually hash a part of big_string to consume # cpu cycles end_time = time.time() + duration last_percent = None while time.time() < end_time: if args.spew: print >> sys.stdout, choice(random_output) else: hashlib.sha1(big_string[:4096]) # consume CPU cycles progress = (1 - (end_time - time.time()) / duration) * 100 percent, _ = divmod(progress, 5) if percent != last_percent: last_percent = percent logger.info("Progress %03d%%", progress) if last_percent is None: logger.info("Progress 100%%") logger.info("Finished frame %04d in %s seconds", frame, duration) if errors: logger.error("Render finished with errors") sys.exit(1) else: return_code = choice(args.return_code) logger.info("exit %s", return_code)