Subscribe to RSS Feed
The Mendicant Bug
Wanderings into computational linguistics, science, social media and life...

Bandwidth Simulation Python Code


bandwidth, code, python, simulations
Published: 09 Jan 2009

This code accompanies this post on my blog.

#!/usr/bin/env python

# Bandwidth Simulator

import sys
import numpy


class Download(object):
    
    def __init__(self, size):
        self.size = size
        self.size_left = size
        self.elapsed = 0.0
        
    
    def decrement(self, bytes):
        if bytes > self.size_left:
            self.elapsed += self.size_left / float(bytes)
            self.size_left = 0.0
        else:
            self.elapsed += 1.0
            self.size_left = self.size_left - bytes
        
        
    def __repr__(self):
        return "Download(%d of %d):  %d s" % (self.size_left, self.size, self.elapsed)
        
        
    def average_speed(self):
        if self.elapsed > 0.0:
            return (self.size - self.size_left) / self.elapsed
        else:
            return 0.0
            
            
class SurfingDownload(Download):
    def __init__(self):
        Download.__init__(self, 75000.0 + numpy.random.uniform(0, 50000))
        # print "Generated %s." % (str(self))


class BigDownload(Download):
    def __init__(self):
        Download.__init__(self, numpy.random.uniform(0, 10) * 1024.0 * 1024.0)
        # print "Generated %s." % (str(self))
        


class WebSurfer(object):
    
    def __init__(self):
        """Create a random web surfer with various surfing habits.
        """
        self.prob_download = numpy.random.uniform(0, 5) / 28800.0     # 0 - 5 / work day
        self.prob_surfing = numpy.random.uniform(0, 200) / 3600.0     # 0 - 200 / hour
        
    
    def act(self):
        """Generate a download or do nothing.
        """
        chance = numpy.random.uniform(0, 1)
        if chance < self.prob_download:
            return BigDownload()
        elif chance < self.prob_surfing:
            return SurfingDownload()
        else:
            return None
        

    
class Scheduler(object):
    
    def __init__(self, users, max_bandwidth):
        self.users              = users
        self.max_bandwidth      = max_bandwidth
        
        self.download_queue     = list()
        self.done_queue         = list()
        self.total_downloads    = 0
        

    def simulate(self, timespan=100):
        for i in xrange(timespan):
            self.single_step()
            if i + 1 % 1000 == 0:
                print "%d seconds have elapsed." % (i + 1)
        
    
    def single_step(self):
        new_download_queue = list()
        if len(self.download_queue) > 0:
            bandwidth_available = self.max_bandwidth / len(self.download_queue)
        else:
            bandwidth_available = self.max_bandwidth
        
        for download in self.download_queue:
            download.decrement(bandwidth_available)
            if download.size_left > 0:
                new_download_queue.append(download)
            else:
                self.done_queue.append(download)
        
        self.download_queue = new_download_queue
        
        # generate new items
        for user in self.users:
            new_download = user.act()
            if new_download is not None:
                self.total_downloads += 1
                self.download_queue.append(new_download)
                
    
    def summarize(self):
        averages = list()
        sizes = list()
        for download in self.done_queue:
            averages.append(download.average_speed() / 1024.0)
            sizes.append(download.size)
        
        print "  Total downloads completed:  %d" % (len(averages))
        print "       Incomplete downlaods:  %d" % (self.total_downloads - len(averages))
        print "          Average file size:  %.3f" % (sum(sizes) / float(len(sizes)))
        avgds = sum(averages) / float(len(averages))
        print "     Average download speed:  %.3f" % (avgds)
        print "Percentage of max bandwidth:  %.3f%%" % (100.0 * avgds / (self.max_bandwidth / 1024.0))



if __name__ == '__main__':
    if len(sys.argv) < 4:
        print "Usage:  %s <# users> <timespan> <max bandwidth in KB>"
        sys.exit(0)
    num_users       = int(sys.argv[1])
    total_time      = int(sys.argv[2])
    max_bandwidth   = int(sys.argv[3]) * 1024
        
    users = list()
    for i in xrange(num_users):
        users.append(WebSurfer())
    
    s = Scheduler(users, max_bandwidth)
    s.simulate(total_time)
    s.summarize()

This code is distributed under the BSD license BSD license.


blog comments powered by Disqus
Fork me on GitHub