Benchmarking MongoDB in a container

The database layer for an application is one of the most crucial part because believe it or not it effects the performance of your application, now with micro-services getting the attention I was just wondering if having a database container will make a difference.

As we have popularly seen most of the containers used are stateless containers that means that they don’t retain the data they generate but there is a way to have stateful containers and that is by mounting a host volume in the container. Having said this there could be an issue with the latency in the database request, I wanted to measure how much will this latency be and what difference will it make if the installation is done natively verses if the installation is done in a container.

I am going to run a simple benchmarking scheme I will make 200 insert request that is write request keeping all other factors constant and will plot the time taken for these request and see what comes out of it.

I borrowed a quick script to do the same from this blog. The script is simple it just uses pymongo the python MongoDB driver to connect to the database and make 200 entries in a random database.


import time
import pymongo
m = pymongo.MongoClient()

doc = {'a': 1, 'b': 'hat'}

i = 0

while (i < 200):

start = time.time()
m.tests.insertTest.insert(doc, manipulate=False, w=1)
end = time.time()

executionTime = (end - start) * 1000 # Convert to ms

print executionTime

i = i + 1

So I went to install MongoDB natively first I ran the above script twice and took the second result into consideration. Once I did that I plotted the graph with value against the number of request. The first request takes time because it requires to make connection and all the over head and the plot I got looked like this.

 

Native
MongoDb Native Time taken in ms v/s Number of request

The graph shows that the first request took about 6 ms but the consecutive requests took way lesser time.

Now it was time I try the same to do it in a container so I did a docker pull mongo and then I mounted a local volume in the container and started the container by

docker run --name some-mongo -v /Users/farhaanbukhsh/mongo-bench/db:/data/db -d mongo

This mounts the volume I specified to /data/db in the container then I did a docker cp of the script and installed the dependencies and ran the script again twice so that file creation doesn’t manipulate the time.

To my surprise the first request took about 4ms but subsequent requests took a lot of time.

Containered
MongoDB running in a container(Time in ms v/s Number of Requests)

 

And when I compared them the time time difference for each write or the latency for each write operation was ​considerable.

MongoDB bench mark
Comparison between Native and Containered MongoDB

I had this thought that there will be difference in time and performance but never thought that it would be this huge, now I am wondering what is the solution to this performance issue, can we reach a point where the containered performance will be as good as native.

Let me know what do you think about it.

Happy Hacking!

Advertisements

Dockah! Dockah! Dockah!

Dockah! Dockah! Dockah!

I have been dabbling with docker for quite sometime, to be honest when it was introduced to me I didn’t understand it much but as time passed and I started experimenting with it I got to know the technology better and better. This made me understand various concepts better. I understood virtualization, containerization, sandboxing and got to appreciate how docker solves the problem of works on my machine.

When I started using docker I use to just run few commands and I could get the server running, this I could access through browser that was more than enough for me. When I use to make changes to the code I could see it getting reflected in the way I am running the application and I was a happy man.

This was all abstract thinking and I was not worried about what was going inside the container, it was a black box for me. This went on for a while but it shouldn’t have, I have the right to know things and how they work. So I started exploring about the realm and the more I read about it the more I fell in love with it. I eventually landed up on Jessie’s blog. The amount of things she and Gautham has taught me is crazy. I could never think that docker being a headless server could actually be used to captivate an application in such a way that you decide how much resources should be given to it. We at jnaapti have been working on various other possibilities but that for some other time.

So yeah there is more to just starting the application using docker and get things to work. So let’s try to understand few things with respect to docker, this is purely from my experience and how I understood things. So containers are virtual environments which share some of the resource of your host operating system. Containers are just like Airbnb guest for which the host is the Operating System. Containers are allowed to use the resources only when the user of Operating System gives them permission to use. Now the way I use them is basically in two ways, Stateful containers or Stateless containers, stateful being the one which has some data generated and stored in them while stateless is the one which doesn’t have any dependency on data.

Let me show you one of the use case that I generally use containers for; Now people may disagree and say I am exploiting it or using the power for wrong purpose but to be very frank if it solves my problem why should I care XD. Now, imagine I want to learn to write Go and I don’t want to install it on my system but have an isolated environment for it. There are two ways I can pull a docker image which has Go in it or get a normal image and install go in it. An image here is just like an iso file which is used to help you install an Operating System on your machine. Let’s see what all images I have on my machine,

I would run docker images and the output looks like this:

docker-images
docker-images

This shows that I have a znc image I use it to run a znc bouncer. Let’s try and pull a ubuntu image and install golang in it.  The command goes docker pull ubuntu.

docker-pull
docker-pull

Now we need to run a docker container and get a shell access to the container. For that we run command docker run -it --name="golang" ubuntu:latest /bin/bash

Let’s break it down and see what is going on here, run tells the docker to start the container -it option tells that this is going to be an interactive session and we need to attach a tty to this, --name is the option to give name to the docker container and ubuntu:latest is the name of the image and /bin/bash is the process that needs to be run.

Once you run this command you will that you will get a root prompt something like this:

docker-prompt
docker-prompt

 

Now you can run any command inside it and you will be totally isolated from your host machine. For installing golang let’s follow these instruction from Digital Ocean. You should ignore the ssh instruction instead run apt update and apt install curl nano. Follow the rest normally and you will see it working like this:

go-docker
go-docker

 

You can play around with golang in the docker and when you are done you can exit. The docker stays it’s just that you are out of it. You want the shell again you can run,

docker exec -it golang /bin/bash

You will get the shell again, this is what is called stateful container since it will have all the files that you have created. You can go ahead and mount a volume to the container using -v option in the docker run statement, this will act as if you plugged in a pen-drive in the docker storage being a directory you have created on the host machine.

docker exec -it -v /home/fhackdroid/go-data:/go-data golang /bin/bash

This will mount the /home/fhackdroid/go-data to ​/go-data in the docker container.

These are the few ways I use docker in my daily life, if you use it in any other way and you want to share do write it to me I would be more than happy to know.

Happy Hacking Folks!