LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-28-2012, 07:22 PM   #1
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Need algorithm help... I'm not good with "numbers".


Hi Everyone,

I've been assigned a (difficult) task of maintaining/augmenting existing spaghetti code which, amongst many other new features that need to be added, requires me to develop an algorithm to deduce the maximum throughput demand (ie rate) at which I can send network packets from one system to another using various middlewares (e.g. ActiveMQ, Websphere, native sockets).

Basically, I need to test sending messages using a start rate, then escalate that rate periodically until I find the max rate that the middleware cannot support. Once I find that maximum rate, I then need to scale down the rate to find that "magic" sweet spot, or asymptote, where data flows without a hitch.

I've come up with a simple algorithm, where I increase the demand by factors of 2, until I reach throughput demand where the packet receiver(s) can no longer receive packets at the desired rate. Once this demand is reached, I would throttle it back (using a quasi binary search pattern) to find the optimal rate that the receiver(s) can support.


Below is a simple C++ program that I used to test this algorithm (please don't laugh!). Can someone suggest an alternative or more optimal approach for this algorithm?
Code:
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>

bool performDemand(int demand)
{
    // perform task...

    // Pretend we get results that validates/invalidates current demand.
    return (demand < 4000) || (rand() % 2 == 1);
}

int main(int argc, char** argv)
{
    srand(time(0));

    int curDemand = 1000;
    int prvDemand = 0;
    int badDemand = 0;

    while ((curDemand - prvDemand) > 1)
    {
        std::cout << "curDemand: " << curDemand << "\tprvDemand: " << prvDemand << std::endl;

        bool success = performDemand(curDemand);

        if (success)
        {
            prvDemand = curDemand;

            if (badDemand == 0)
            {
                curDemand *= 2;
            }
            else
            {
                curDemand = curDemand + (badDemand - curDemand) / 2;
            }
        }
        else
        {
            badDemand = curDemand;
            curDemand = curDemand - (curDemand - prvDemand) / 2;
        }
    }
    std::cout << "\nAll done!" << std::endl;
}
 
Old 08-29-2012, 04:34 AM   #2
Snark1994
Senior Member
 
Registered: Sep 2010
Distribution: Debian
Posts: 1,632
Blog Entries: 3

Rep: Reputation: 346Reputation: 346Reputation: 346Reputation: 346
What information do you have? Do you just get a boolean value as to whether or not the demand is good, or do you get a measure of how much it failed by?

If you don't have any other information, then I think your binary search idea is probably optimal-ish - the only thing that's really going to affect it is how good your guess is for the initial value to try (though this is going on a slightly stale memory of the algorithmics I've done). I would code the binary search slightly differently, but that's probably more down to personal taste. The only problem I can see is the fact that (as your 'rand()' call demonstrates) that there's some error in the result of 'performDemand'. I'm not sure the model you've got for it is very accurate (i.e. it fails 1/2 the time if we're above the bad demand threshold) - I would expect a more bell-shaped curve. In any case, you can't use a strict binary search, because there's no way for it to 'backtrack' if it gets a bad result. For example:

Code:
bad at 10000
0 - 10000 range: good at 5000 (by chance and sod's law)
5000 - 10000 range: etc.
As you see, your code will never be able to backtrack and you will end up with a very wrong answer (definitely not 4000 - I believe the average value you would get is 7500 by symmetry, but don't quote me on that). I think the best solution would be to run the test many times (I don't know how many is suitable) and then take an average over that dataset for a more reliable answer as to whether or not that demand is good or bad.



On the other hand, if you do, I think you could get a much more efficient algorithm. I don't have the details (I could do some research on it if you do have this information) but essentially, by looking at how much it fails by, you can then make an educated guess as to how far away from the ideal value you are: if it completely chokes up, then you want to take it down a whole load, but if you're only losing a couple of packets then you're quite close and you only want to change it a little bit.



As you may well have guessed by now, I know very little about networks - so apologies if what I said makes no sense in the context you're working with

Hope this helps,

Last edited by Snark1994; 08-29-2012 at 04:36 AM.
 
Old 08-29-2012, 05:36 AM   #3
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Original Poster
Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
@ Snark1994 -- Thanks for your reply.

Quote:
Originally Posted by Snark1994 View Post
What information do you have? Do you just get a boolean value as to whether or not the demand is good, or do you get a measure of how much it failed by?
The boolean value will probably be it, although the information used to derive that value will be related as to whether the receiver(s), over a period of time, successfully or not receive packets in a "reasonable time". Calculating the latency of whether a receiver has failed to collect packets in a timely manner is another facet of the task I'm facing.

Quote:
Originally Posted by Snark1994 View Post
The only problem I can see is the fact that (as your 'rand()' call demonstrates) that there's some error in the result of 'performDemand'.
The use of rand() will not be used in the production code; I merely used it in the example so that I could randomize my test results (and mimic a test demand failing after some period).

Quote:
Originally Posted by Snark1994 View Post
I'm not sure the model you've got for it is very accurate (i.e. it fails 1/2 the time if we're above the bad demand threshold) - I would expect a more bell-shaped curve
I did not put too much thought into the conditional statement; I merely want to see if the algorithm would backtrack to some degree.

Quote:
Originally Posted by Snark1994 View Post
In any case, you can't use a strict binary search, because there's no way for it to 'backtrack' if it gets a bad result. For example:
Code:
bad at 10000
0 - 10000 range: good at 5000 (by chance and sod's law)
5000 - 10000 range: etc.
I agree, but I do not know what else to do. I cannot increase the rate by a count of 1 for each iteration, so I have to increase it by a certain factor, then when a bad limit has been detected, I need to back it down. Perhaps I should keep track of the highest rate that was successful, and then from there, increase it by a smaller factor?

Quote:
Originally Posted by Snark1994 View Post
As you see, your code will never be able to backtrack and you will end up with a very wrong answer (definitely not 4000 - I believe the average value you would get is 7500 by symmetry, but don't quote me on that). I think the best solution would be to run the test many times (I don't know how many is suitable) and then take an average over that dataset for a more reliable answer as to whether or not that demand is good or bad.
Bingo! That's why I created this thread. I do need a better algorithm. As for running the test multiple times, that capability for the network analysis tool is also in the works.

Quote:
Originally Posted by Snark1994 View Post
On the other hand, if you do, I think you could get a much more efficient algorithm. I don't have the details (I could do some research on it if you do have this information) but essentially, by looking at how much it fails by, you can then make an educated guess as to how far away from the ideal value you are: if it completely chokes up, then you want to take it down a whole load, but if you're only losing a couple of packets then you're quite close and you only want to change it a little bit.
The crux of the issue I'm trying to solve is how to determine if a particular demand rate is possible or not. After each attempt, the software I currently have does its "magic" to sync the times on each system being used for the test. This is done because packets are sent asynchronously; that is, the sender places a timestamp in the packet, and then the receiver places its own timestamp. The timestamp is based on CPU clock time, which no doubt differs from one system to another.

So after the timing has been synchronized, and the metrics within the packets that have been received are collated, it is then time to generate the timing report. Once the report is generated, then the timing analysis can begin. Essentially, all of this timing collection, analysis, etc. will be setup (some as separate threads) by the performDemand() method.

Anyhow, I need to return to my work... I have a design review due tomorrow! There's nothing better (sarcastically speaking) than inheriting spaghetti code and then being asked to augment it to perform various tasks, that in retrospect, should have been considered from the inception of the project.


P.S. The project I'm working on is actually developed in Java, not C++.

Last edited by dwhitney67; 08-29-2012 at 05:37 AM.
 
Old 08-29-2012, 01:29 PM   #4
Snark1994
Senior Member
 
Registered: Sep 2010
Distribution: Debian
Posts: 1,632
Blog Entries: 3

Rep: Reputation: 346Reputation: 346Reputation: 346Reputation: 346
Quote:
Originally Posted by dwhitney67 View Post
The boolean value will probably be it, although the information used to derive that value will be related as to whether the receiver(s), over a period of time, successfully or not receive packets in a "reasonable time". Calculating the latency of whether a receiver has failed to collect packets in a timely manner is another facet of the task I'm facing.
So... couldn't you use information about the time it took (or the difference between this time and the 'reasonable time') as a metric? Or have I misunderstood you?


Quote:
The use of rand() will not be used in the production code; I merely used it in the example so that I could randomize my test results (and mimic a test demand failing after some period).
Sorry, I understood that, I was just saying that the rand() call showed that you had understood the test wouldn't be consistent, and there would be experimental error associated with performDemand().

Quote:
I agree, but I do not know what else to do. I cannot increase the rate by a count of 1 for each iteration, so I have to increase it by a certain factor, then when a bad limit has been detected, I need to back it down. Perhaps I should keep track of the highest rate that was successful, and then from there, increase it by a smaller factor?
Hm, an idea which has just occurred to me is that you could start out with a guess value, and a reasonably large "delta value". If the test is successful, you add the delta, if the test is unsuccessful, you subtract the delta, and if the test changes value (i.e. last time it succeeded, this time it failed) then you reduce the delta. Carry on until the delta is very small, and you've found your value. This will mean that it can quite quickly home in on the place where it changes over, and if there are a couple of (un)lucky results, it shouldn't affect the likelihood of the algorithm finding the correct value too much.

Quote:
As for running the test multiple times, that capability for the network analysis tool is also in the works.
Couldn't you just have

Code:
bool success = performDemand(curDemand) && performDemand(curDemand) && performDemand(curDemand);
?

Also, I guess another important question is "how does the f(curDemand) behave?" (sorry for my mathsy way of thinking about it...). What I mean is, is it the case that:
  • below the threshold value, it will always, 100% of the time, return true, and for the values above it, it will 100% of the time return false? (obviously not)
  • below the threshold value, it will always return true, and the further above the threshold value, the less likely it is to return true?
  • the lower curDemand is, the more likely it is to return true - but this probability is very very high and doesn't change much until the threshold value is reached, and then tails of quite quickly (what I suspect is the case)

And then ideally you would want to know what shape the 'tail off' takes. As far as I can see, the sharper the tail-off (I suppose you could even say the closer it approximates a boolean value) the easier it is to work out the threshold in an efficient manner.

Last edited by Snark1994; 08-29-2012 at 01:35 PM.
 
Old 08-30-2012, 03:06 AM   #5
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
It could depend on network traffic and load on the target servers for a start and the NICs between machines.
Is this a real world problem or just research?
 
Old 08-30-2012, 04:57 AM   #6
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Original Poster
Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by bigearsbilly View Post
It could depend on network traffic and load on the target servers for a start and the NICs between machines.
Is this a real world problem or just research?
It's a real world problem; my employer has an existing tool that they would merely like to augment to support other capabilities. Currently the tool supports the measuring of network traffic performance at designated (ie specified in a config file) data rates. They would like to automate this particular test to determine the maximum throughput that the middleware (transport s/w) will permit. The computers, NICs, OS, environment, etc. are all the same for every test.
 
Old 09-01-2012, 09:24 AM   #7
Snark1994
Senior Member
 
Registered: Sep 2010
Distribution: Debian
Posts: 1,632
Blog Entries: 3

Rep: Reputation: 346Reputation: 346Reputation: 346Reputation: 346
Did you manage to get my 'delta value' idea working?

Compared to your algorithm, it's much more consistent (it seems to overestimate by 0 - 500, compared to -2 - 11000) though it takes longer (41-50 tests compared to 13-15) based on the test programme you posted, but I don't know how they'd perform in a real test.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Linux kernel "tcp_cubic" algorithm for congestion control pologuy Linux - Kernel 0 04-20-2012 09:53 AM
doubts about "internet checksum algorithm" in rfc 1071 saga_uni Programming 4 04-18-2012 11:29 PM
casting problem or "puzzle" regarding hex numbers aryan1 Programming 1 08-03-2009 09:38 AM
Transformers "even with brute force algorithm..." CRC123 General 18 08-14-2008 01:25 PM
"bad algorithm" error trying to start named esanchez Linux - Networking 2 04-20-2004 01:36 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:52 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration