16
Day 7 homework Sloejtes
xuanyi.wang edited this page 2023-04-13 00:54:31 +02:00

Sloetjes_Day-7_Homework_04/12/23

1. Use the time.perf_counter_ns() method to measure how many nanoseconds it takes for time.sleep() to run for the following durations: 10 milliseconds, 100 milliseconds, 1 second. Repeat for 100 times for each of those durations. The variation in timing is called jitter. Can you find any pattern to how the jitter varies for each of the different sleep durations? Binning the results and creating a histogram may help.

import time

durations = [0.01, 0.1, 1]
repeats = 100

for duration in durations:
    times = []
    for i in range(repeats):
        start_time = time.perf_counter_ns()
        time.sleep(duration)
        end_time = time.perf_counter_ns()
        times.append(end_time - start_time)
    print(f"Duration: {duration}s, Mean: {sum(times)/len(times)} ns, Max: {max(times)} ns, Min: {min(times)} ns")
Output:
Duration: 0.01s, Mean: 12103232.93 ns, Max: 12948458 ns, Min: 10101042 ns
Duration: 0.1s, Mean: 103480802.47 ns, Max: 107881250 ns, Min: 100116125 ns
Duration: 1s, Mean: 1003430530.03 ns, Max: 1005073459 ns, Min: 1000114667 ns

Visualization of the jitter:

import matplotlib.pyplot as plt

bins = 10

for duration in durations:
    times = []
    for i in range(repeats):
        start_time = time.perf_counter_ns()
        time.sleep(duration)
        end_time = time.perf_counter_ns()
        times.append(end_time - start_time)
    plt.hist(times, bins=bins)
    plt.title(f"Duration: {duration}s")
    plt.xlabel("Time difference (ns)")
    plt.ylabel("Frequency")
    plt.show()

images

2. Create a dict with 1 million integer keys, each with 64 bytes of random values.

import random

# Create an empty dictionary
my_dict = {}

# Loop 1 million times
for i in range(1000000):
    # Generate 64 random bytes
    value = bytes(random.getrandbits(8) for _ in range(64))
    # Add the key-value pair to the dictionary
    my_dict[i] = value

3. Now that we know how to precisely time how long it takes for Python to do something, measure how long it takes to look up 1,000, 10,000, and 100,000 random integer keys, and repeat each experiment 100 times. Does the amount of time per key lookup change?

import random
import time

# Create the dictionary with 1 million integer keys and random values
my_dict = {}
for i in range(1000000):
    value = bytes(random.getrandbits(8) for _ in range(64))
    my_dict[i] = value

# Measure the time it takes to look up 1,000, 10,000, and 100,000 random integer keys
for n in [1000, 10000, 100000]:
    total_time = 0
    for i in range(100):
        keys = random.sample(range(1000000), n)  # Get n random keys
        start_time = time.perf_counter_ns()
        for key in keys:
            value = my_dict[key]  # Look up the value for the key
        end_time = time.perf_counter_ns()
        total_time += end_time - start_time
    average_time = total_time / 100
    print(f"Average time to look up {n} keys: {average_time} nanoseconds")
Output:
Average time to look up 1000 keys: 393492.47 nanoseconds
Average time to look up 10000 keys: 3014112.11 nanoseconds
Average time to look up 100000 keys: 32564415.87 nanoseconds

4. The ABC module can be used to create so-called virtual base classes, similar to the Simulator.py file from day 4. Look around you, and find two related objects. Create a virtual base class by inheriting from the ABC module and using the @abstractmethod and @property decorators to define the shared methods and properties of the class, and non-abstract methods and properties which are the same for the two objects.

from abc import ABC, abstractmethod

class Vehicle(ABC):
    
    @property
    @abstractmethod
    def num_wheels(self):
        pass
    
    @abstractmethod
    def start(self):
        pass
    
    def stop(self):
        print("Stopping the vehicle.")

5. Create concrete classes which inherit from your virtual base class from the previous task, and define the non-abstract methods and properties which are different for each of the two objects. I'm deliberately omitting an example here to incentivize you to read the documentation on the ABC module: https://docs.python.org/3/library/abc.html#module-abc

class Car(Vehicle):
    
    def __init__(self):
        self._num_wheels = 4
        
    @property
    def num_wheels(self):
        return self._num_wheels
    
    def start(self):
        print("Starting the car engine.")
        
class Bike(Vehicle):
    
    def __init__(self):
        self._num_wheels = 2
        
    @property
    def num_wheels(self):
        return self._num_wheels
    
    def start(self):
        print("Starting the bike engine.")
Answer:
  • In this example, Vehicle class is the virtual base class that defines the shared methods and properties of the Car and Bike classes. The num_wheels property and start method are abstract methods that must be implemented in the concrete classes. The stop method is a non-abstract method that is the same for both Car and Bike objects.

  • The Car and Bike classes inherit from Vehicle and define the non-abstract methods and properties that are specific to each object. The num_wheels property and start method are implemented differently in each class.

Implementation:

obj_car = Car()
obj_bike = Bike()

print(obj_car.start())
print(obj_bike.start())

print(obj_car.num_wheels)
print(obj_bike.num_wheels)

print(obj_car.stop())
print(obj_bike.stop())
Output:
Starting the car engine.
None
Starting the bike engine.
None

4
2

Stopping the vehicle.
None
Stopping the vehicle.
None

6. What happens when you try to call an abstract method, or access an abstract property in the base class?

Answer:

  • When trying to call an abstract method or access an abstract property in the base class, we will get a TypeError with a message indicating that the abstract method or property was not implemented in the subclass because abstract methods and properties in Python are meant to be overridden and implemented in subclasses.

Example:

v = Vehicle()
Output:
TypeError                                 Traceback (most recent call last)
Input In [50], in <cell line: 1>()
----> 1 v = Vehicle()

TypeError: Can't instantiate abstract class Vehicle with abstract methods num_wheels, start