I built an algorithm (sieve of Eratosthenes
) for finding primes, but it consumes a lot of memory. Currently, my code uses a decorator to monitor the time eclipsed. Could you come up with a similar decorator to evaluate the memory consumed by my program?
import math
import time
def time_usage(func):
def wrapper(*args, **kwargs):
beg_ts = time.time()
result = func(*args, **kwargs)
end_ts = time.time()
print("[INFO] elapsed time: %f" % (end_ts - beg_ts))
return result
return wrapper
@time_usage
def find_prime(n):
is_composite = [False for _ in range(n + 1)]
# Cross out multiples of 2
for i in range(4, n, 2):
is_composite[i] = True
# Cross out multiples of primes found so far
next_prime = 3
stop_at = math.sqrt(n)
while next_prime < stop_at:
# Cross out multiples of this prime
for i in range(next_prime * 2, n, next_prime):
is_composite[i] = True
# Move the next prime, skipping the even number
next_prime += 2
while next_prime <= n and is_composite[next_prime]:
next_prime += 2
# Copy the primes into a list
primes = []
for i in range(2, n):
if not is_composite[i]:
primes.append(i)
return primes
if __name__ == '__main__':
print(find_prime(100000))
One suggestion is to use a third party library to profile the memory usage. I used the memory_profiler
as it offers a nice decorator implementation however I cannot use both time_usage
decorator and the memory profile.
Here I can see that @profile
is actually profiling the memory of time_usage
.
import math
import time
from memory_profiler import profile
def time_usage(func):
def wrapper(*args, **kwargs):
beg_ts = time.time()
result = func(*args, **kwargs)
end_ts = time.time()
print("[INFO] elapsed time: %f" % (end_ts - beg_ts))
return result
return wrapper
@profile
@time_usage
def find_prime(n):
is_composite = [False for _ in range(n + 1)]
# Cross out multiples of 2
for i in range(4, n, 2):
is_composite[i] = True
# Cross out multiples of primes found so far
next_prime = 3
stop_at = math.sqrt(n)
while next_prime < stop_at:
# Cross out multiples of this prime
for i in range(next_prime * 2, n, next_prime):
is_composite[i] = True
# Move the next prime, skipping the even number
next_prime += 2
while next_prime <= n and is_composite[next_prime]:
next_prime += 2
# Copy the primes into a list
primes = []
for i in range(2, n):
if not is_composite[i]:
primes.append(i)
return primes
if __name__ == '__main__':
print(find_prime(100000))
Produce this :
Line # Mem usage Increment Line Contents
7 27.4 MiB 0.0 MiB def wrapper(*args, **kwargs): 8 27.4 MiB 0.0 MiB beg_ts = time.time() 9 28.3 MiB 0.9 MiB result = func(*args, **kwargs) 10 28.3 MiB 0.0 MiB end_ts = time.time() 11 28.3 MiB 0.0 MiB print("[INFO] elapsed time: %f" % (end_ts - beg_ts)) 12 28.3 MiB 0.0 MiB return result
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, ..., 99989, 99991]