Introduction
These days new dns servers are multithreaded so if you want to test your brand new dns server and compare it to your single threaded dns server here is a tool to help you.
Background
Usually what separates different versions of DNS servers is some security fixes. This is also true about BIND. For instance every release of BIND 9 contains some bug fixes. So in this area it is actually hard to satisfy IT managers to upgrade because they usually trust their firewall mechanism and security features or they don't just want to deal with new configurations. Part of what they say is right because BIND versions only differ in bug fixes. For example there are lots of DNS servers out there that use BIND 4.9 and don't have any plan to upgrade.
The BIND community always had this problem as of now they have to release a documentation for every BIND version they released since version 4 every time they release a new security fix let alone the fact that they have to work on all 6 major releases to fix their security hole.
I personally think that it's hugely changed since the release of BIND 9. from this version BIND support multithreading which means no more queuing involved. Prior to this version if you sent a dozen of packets at the same time to it it would queue them and answer them one by one. But in BIND 9 it has multithreading built in.
We at IUT wanted to refresh our DNS server because they were really old so we decided to use BIND on FreeBSD But actually we didn't know which version to use as the most popular one is 8 and the newest one is 9.
There was an article about version 9 being a multithread DNS server so we wanted to test the performance gain.
From the test I've done on a 2 core server the first packets were faster answered on old versions but when it got to the 10th or 12th packet the multithreaded DNS server answered way sooner than old versions.
so finally I wrote this program based on Charles Putney's DNS tester. I hope it's useful
Using the code
Well although lot's of code lines are changed but the already popular DNS tester has a really neat and efficient way to test DNS servers. The only problem it has is that it sends packets one by one so it gives the server some time to think about each of them.
I think it really doesn't test the capabilities of new multithread DNS servers. So I've rewritten it to use threads.
I made a thread pool and changed some functions to delegate in order to make them run parallel. This made the program really memory hungry but we are talking about 20MB of RAM which is still a lot for such a program but I needed to copy the list of remote hosts and some variables like time for each thread.
For example I've made a function called dnscheck which does everything as before except that it only processes it's own remote host and sends the packet to it and waits for an answer. Of course it has to have it's own copy of names,time and so on.
As you can see it only accepts one object. It actually has everything in it because I pass a class that I made for this purpose as it's variable. But it has to be this way because for multithreading it has to be a delegate function to be able to run multiple times at the same time.
I also made a dummy delegate function. all it does is that it passes my object to dnscheck:
private delegate void _dnscheck(object me);
private void dnscheck(object me){}
So here I make an object of the delegate function for each thread and pass my function as its parameter. Then I initialize my class called me which contains the needed information and then I pass it to my delegate function's object:
for (i=0;i<URLNamescount;i++)
{
_dnscheck ddnscheck = new _dnscheck(dnscheck);
me = new mine(URLNames, URLNamescount, DNSAddress1, DNSAddress2, i);
ThreadPool.QueueUserWorkItem(new WaitCallback(ddnscheck), me);
}
I had some trouble showing exceptions in status box. Because in .net you can't normally access an object which is created in other threads in your current thread. Your function has to be delegate and also you have to ask that object whether or not invoke is required:
private delegate void _StatusBoxPrint(object obj);
private void StatusBoxPrint(object obj)
{
string LogText = (string)obj;
StatusBox.Items.Add(DateTime.Now+" "+LogText);
StatusBox.TopIndex=StatusBox.Items.Count-1;
if (StatusBox.Items.Count > 5000)
{
StatusBox.Items.RemoveAt(0);
}
StatusBox.Update();
}
And I also added the line below to the exception handling code:
StatusBox.Invoke(status,e.Message);
And did the same thing for ResultView which is a listview object and has some serious childhood issues!(It made me to actually learn these threading tricks the hard way as the program generated 57 exceptions the first time I launched it!):
if (ResultView.InvokeRequired)
{
changeListViewItems my = new changeListViewItems(_changeListViewItems);
ResultView.Invoke(my, mi);
}
Here changeListViewItems is a delegate function that receives an object and then passes it to my.
Points of Interest
I really liked to experience some multithread application and I did with this as it was really interesting handling so many threads.
It is actually an easy task : you have to create a delegate function and the create an instance of it for everythread. You also have to make your function accept only one object as it normally pass one object.
I also learned that if you want to use an object which is created in another thread in the thread which it's not created in you have to call the invoke function of that object of the class and it simply gives you access to that object as I mentioned it above.
But the most important thing happened when I compared our old single threaded BIND to our newest one. Maybe it was an accident(it happened ten times!) but the first packets were answered faster by the old one but the last ones were answered faster by the new one! here is a picture of my tests:
The first one is multithreaded and the second one is single threaded:
History
uploaded the source: 11/3/2012
updated the source: 1/7/2013 - added stress test to test DNS under stressful conditions
added binary installation: 1/7/2013
updated: 1/11/2013 - fixed lots of bugs - now has stop button and status bar
code optimization: 1/23/2013