How to clump a series of messages - c#

I am writing a test application for stress-testing a server. I have a list of messages which I need to send in a given time interval, but I am interested in not just sending them with a uniform gap, but "clumping" messages together to simulate bursts. This will be controlled by a slider in the UI - at one end is uniform, at the other is "clumpy". Is there a neat mathematical way to do this?

So lets say that you have slider, max, a time interval T that you can cut up in to N divisions, and a total number of message M you want to send. Then at time division N, I would send
(M/N)*(max(1-slider/max)+k*(slider/max)cosine(PI*N/T))
When slider=0, this will give total uniformity, with M/N messages arriving each interval. When slider=max, the uniformity will be completely damped, and you can adjust the parameter k to make the clumping even more extreme.

Here's what I think could work:
var rngClumpMax = new Random();
var clumpMin = 1;
var clumpMax = 1;
var clumpSize = 1;
clumpSize = rngClumpMax.Next(clumpMin, clumpMax);
while (true)
{
List<string> messages = FetchMessages(clumpSize);
if (messages.Count > 0)
{
SendMessages(messages);
}
else
{
break;
}
}
The scrollbar could set the value of clumpMax, so you can generate clumps between sizes of 1 and some N value from the scrollbar.
If you had a control with double scrolls, you could set even clumpMin and generate a random clumpSize between clumpMin and clumpMax.

Related

How to implement threading in Xamarin.Android?

I'm trying to send/publish at 100ms, and the message looks like this
x.x.x.x.x.x.x.x.x.x
So every 100ms or so subscribe will be called. My problem is that I think, it's not fast enough, (i.e if the current subscribe is not yet done and another subscribe is being called/message being published)
I was thinking, on how could I keep on populating the list, at the same time graph with Oxyplot. Can I use threading for this?
var x = 0;
channel.Subscribe(message =>
{
this.RunOnUiThread(() =>
{
var sample = message.Data;
byte[] data = (byte[])sample;
var data1 = System.Text.Encoding.ASCII.GetString(data);
var splitData = data1.Split('-');
foreach(string s in splitData) //Contains 10
{
double y = double.Parse(s);
y /= 100;
series1.Points.Add(new DataPoint(x, y));
MyModel.InvalidatePlot(true);
x++;
}
if (x >= xaxis.Maximum)
{
xaxis.Pan(xaxis.Transform(-1 + xaxis.Offset));
}
});
});
Guaranteeing a minimum execution time goes into Realtime Programming. And with a App on a Smartphone OS you are about as far from that I can imagine you to be. The only thing farther "off" would be any interpreted langauge (PHP, Python).
The only thing you can do is define a minimum time between itterations. I did once wrote some example code for doing that from within a alternative thread. A basic rate limiting code:
integer interval = 20;
DateTime dueTime = DateTime.Now.AddMillisconds(interval);
while(true){
if(DateTime.Now >= dueTime){
//insert code here
//Update next dueTime
dueTime = DateTime.Now.AddMillisconds(interval);
}
else{
//Just yield to not tax out the CPU
Thread.Sleep(1);
}
}
Note that DateTime.Now only resturns something new about every 18 ms, so anything less then 20 would be too little.
If you think you can not afford a minimum time, you may need to read the Speed Rant.

Calculating the approximate run time of a for loop

I have a piece of code in my C# Windows Form Application that looks like below:
List<string> RESULT_LIST = new List<string>();
int[] arr = My_LIST.ToArray();
string s = "";
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < arr.Length; i++)
{
int counter = i;
for (int j = 1; j <= arr.Length; j++)
{
counter++;
if (counter == arr.Length)
{
counter = 0;
}
s += arr[counter].ToString();
RESULT_LIST.Add(s);
}
s = "";
}
sw.Stop();
TimeSpan ts = sw.Elapsed;
string elapsedTime = String.Format("{0:00}", ts.TotalMilliseconds * 1000);
MessageBox.Show(elapsedTime);
I use this code to get any combination of the numbers of My list. I have behaved with My_LIST like a recursive one. The image below demonstrates my purpose very clearly:
All I need to do is:
Making a formula to calculate the approximate run time of these two
nested for loops to guess the run time for any length and help the
user know the approximate time that he/she must wait.
I have used a C# Stopwatch like this: Stopwatch sw = new Stopwatch(); to show the run time and below are the results(Note that in order to reduce the chance of error I've repeated the calculation three times for each length and the numbers show the time in nano seconds for the first, second and third attempt respectively.):
arr.Length = 400; 127838 - 107251 - 100898
arr.Length = 800; 751282 - 750574 - 739869
arr.Length = 1200; 2320517 - 2136107 - 2146099
arr.Length = 2000; 8502631 - 7554743 - 7635173
Note that there are only one-digit numbers in My_LIST to make the time
of adding numbers to the list approximately equal.
How can I find out the relation between arr.Length and run time?
First, let's suppose you have examined the algorithm and noticed that it appears to be quadratic in the array length. This suggests to us that the time taken to run should be a function of the form
t = A + B n + C n2
You've gathered some observations by running the code multiple times with different values for n and measuring t. That's a good approach.
The question now is: what are the best values for A, B and C such that they match your observations closely?
This problem can be solved in a variety of ways; I would suggest to you that the least-squares method of regression would be the place to start, and see if you get good results. There's a page on it here:
www.efunda.com/math/leastsquares/lstsqr2dcurve.cfm
UPDATE: I just looked at your algorithm again and realized it is cubic because you have a quadratic string concat in the inner loop. So this technique might not work so well. I suggest you use StringBuilder to make your algorithm quadratic.
Now, suppose you did not know ahead of time that the problem was quadratic. How would you determine the formula then? A good start would be to graph your points on log scale paper; if they roughly form a straight line then the slope of the line gives you a clue as to the power of the polynomial. If they don't form a straight line -- well, cross that bridge when you come to it.
Well you gonna do some math here.
Since the total number of runs is exactly n^2, not O(n^2) but exactly n^2 times.
Then what you could do is to keep a counter variable for the number of items processed and use math to find out an estimate
int numItemProcessed;
int timeElapsed;//read from stop watch
int totalItems = n * n;
int remainingEstimate = ((float) totalItems - numItemProcessed) / numItemProcessed) * timeElapsed
Don't assume the algorithm is necessarily N^2 in time complexity.
Take the averages of your numbers, and plot the best fit on a log-log plot, then measure the gradient. This will give you an idea as to the largest term in the polynomial. (see wikipedia log-log plot)
Once you have that, you can do a least-squares regression to work out the coefficients of the polynomial of the correct order. This will allow an estimate from the data, of the time taken for an unseen problem.
Note: As Eric Lippert said, it depends on what you want to measure - averaging may not be appropriate depending on your use case - the first run time might be more correct.
This method will work for any polynomial algorithm. It will also tell you if the algorithm is polynomial (non-polynomial running times will not give straight lines on the log-log plot).

c# Normalized power for Polar cycle

List<int> NPower = new List<int>();
List<double> list = new List<double>();
try
{
for (int i = 1; i < dataGridView1.Rows.Count; i++)
{
for (int n = 0; n < i + 30; n++)
{
NPower.Add(Convert.ToInt32(dataGridView1.Rows[i + n].Cells[6].Value));
}
}
average = NPower.Average();
total = Math.Pow(average, 4);
NPower.Clear();
}
catch (Exception)
{
average = NPower.Average();
NP = Convert.ToInt32(Math.Pow(average, (1.0 / 3.0)));
label19.Text = "Normalised Power: " + NP.ToString();
NPower.Clear();
}
Hi so i'm trying to calculate the normalized power for a cycling polar cycle. I know that for the normalized power you need to:
1) starting at the 30 s mark, calculate a rolling 30 s average (of the preceeding time points, obviously).
2) raise all the values obtained in step #1 to the 4th power.
3) take the average of all of the values obtained in step #2.
4) take the 4th root of the value obtained in step #3.
I think i have done that but the normalized power comes up with 16 which isnt correct. Could anyone look at my code to see if they could figure out a solution. Thankyou, sorry for my code i'm still quite new to this so my code might be in the incorrect format.
I'm not sure that I understand your requirements or code completely, but a few things I noticed:
Since you're supposed to start taking the rolling average after 30 seconds, shouldn't i be initialized to 30 instead of 1?
Since it's a rolling average, shouldn't n be initialized to the value of i instead of 0?
Why is the final result calculated inside a catch block?
Shouldn't it be Math.Pow(average, (1.0 / 4.0)) since you want the fourth root, not the third?

Generate an event X numbers of times per second but not evenly spaced within each second

I'd like to write a class that will fire an event x a pre-defined numbers of times per second call it n.
However, I would like x NOT to fire evenly spaced within each second.
So, say n = 100, 25 might fire in the first 300ms then a further 50 over the next 600ms and the final 25 in the remaining 100ms.
Ideally, I'd like better granularity then that presented above and a greater range of spacing within each second.
I'm wondering if I would be able to create an array with defined millisecond and how many events to fire. Then use a loop and the Stopwatch class to determine whether the defined events for that millisecond waypoint should be fired.
The question is, could the array be calculated for each second fast enough, each second should have random spacing.
Obviously, the event would need to be Asynchronous to avoid getting delayed by what ever is wired up to it.
Anyone come across any similar need?
UPDATE
I thought I'd at least put my initial effort on here.
So I found that there is enough resolution to check which millisecond you are currently in and which second. Basically, each second I rebuild my spacing each millisecond gets an entry in the array and each entry says how many times to fire the event that millisecond.
My issue is the spacing...I needs a better way to try and clump the event count, currently this jsut seems to plonk them in evenly spaced in either 0, 1 or 2.
public delegate void EmptyEventDelegate();
public class RandEvent
{
public event EmptyEventDelegate OnEvent = delegate { };
private bool running = false;
Random r = new Random();
private int eventsPS;
public RandEvent(int eventsPS = 1)
{
this.eventsPS = eventsPS;
}
public void Start()
{
running = true;
Task.Factory.StartNew(() =>
{
Run();
});
}
private void Run()
{
var sw = new Stopwatch();
sw.Start();
int currentSecond = 0;
int[] eventCount = BuildEventSpacing();
while(running)
{
if (currentSecond != sw.Elapsed.Seconds)
{
currentSecond = sw.Elapsed.Seconds;
eventCount = BuildEventSpacing();
}
else
{
for(int i = 0; i < eventCount[sw.Elapsed.Milliseconds]; i++)
OnEvent();
}
}
sw.Stop();
}
private int[] BuildEventSpacing()
{
var array = new int[1000];
for (int i = 0; i < eventsPS; i++)
{
array[r.Next(0, 999)]++;
}
return array;
}
public void Stop()
{
running = false;
}
}
To create the array of random event times:
Choose a minimum time interval between events, and fill an array with all possible event times. For example, if you choose a granularity of 1ms, then the array will have 1000 values: 0, 0.001, 0.002, ..., 0.999.
Each second, shuffle the array to randomize the order of the elements.
Use the first n elements of the array as the firing times for the event.
Create a Timer and in the Tick event do whatever needs to be done. Additionally, use the following method (in an additional handler of the Tick event) to change the interval each time. It would be best to provide the same Random instance is passed to the method every time rather than providing new instances.
private static double millisecondsPerSecond = 1000.0;
/// <summary>
/// Method used to determine how long you would wait for the event to fire next
/// </summary>
/// <param name="averageFiresPerSecond">The approximate number of times the event should occur per second.</param>
/// <param name="variance">How much variance should be allowed, as a percentage. i.e. a variance of 0.1 would mean that
/// the delay will be +/- 10% of the exact rate.</param>
/// <param name="generator">A randon number generator.</param>
/// <returns>The number of milliseconds to wait for the next event to fire.</returns>
public double GetNextDelay(int averageFiresPerSecond, double variance, Random generator)
{
double randomFactor = ((generator.NextDouble() * 2) * variance);
return (millisecondsPerSecond / averageFiresPerSecond) * randomFactor;
}
Let's say you want 100 numbers whose sum is 1. You can do the following:
Generate 100 random numbers between 0 and 1 (i.e. Random.NextDouble) and store in a list.
Sum the numbers.
Divide each number in the list by the sum.
You now have a list of 100 numbers that sum to 1.0.
Now, create a one-shot timer whose interval is the first value in the list. When it fires, the handler does its job and then sets up the one-shot timer again with an interval equal to the next value in the list.
Except that's not going to work perfectly because it doesn't take into account the amount of time required to process the tick and setup the timer again. So you'll have to keep track of that latency and adjust the next tick accordingly. But even that's not going to be perfect.
As I said in my comment, you're going to have a difficult time getting any of the .NET timers to give you more than 60 ticks per second. At best, you can expect 15 ms between timer ticks. Even if you go with a custom timer implementation, you're going to have some trouble because timer ticks don't occur exactly on time. The problem gets worse, of course, as the timer interval decreases.
In any event, there's no way that you can get a Windows timer to give you better than 1 ms resolution, so you'll have to adjust the method I described above to give you numbers that are greater than or equal to 0.001.
Your idea of using a Stopwatch can work with my method of creating the event intervals. Understand, however, that the loop is going to consume close to 100% of CPU time on a single core. Even then, it might not give you events exactly on time, because other higher-priority tasks might cause your loop to be swapped out.
I would suggest to make a collection of TimeSpan objects initialized to be equal and have a sum of 1 second. The exact values would be determined by your n.
From there, you can offset pairs or groups by whatever values you like and your total will still be one second. For example...
var offset = new TimeSpan.FromMilliseconds(10); // 10ms offset
timeSpans[0] += offset;
timeSpans[1] -= offset;
In this way you can shift them around without affecting the overall sum. If you need to make them so that more come early and fewer come late, then you could do something like...
timeSpans[0] -= offset;
timeSpans[1] -= offset;
timeSpans[2] += offset;
timeSpans[2] += offset;
This would make indexes 0 and 1 have a shorter delay and index 2's delay will be twice as long, but keep the sum total unaffected.
The only thing to keep in mind is that none of the time spans should be less than 0s and your sum total should always be 1s, then you're golden. Once you have your TimeSpan objects distributed, you can use them in order to pause between firing event x. You're going to want to vary (randomize?) your offset a few times and each time you change it, choose new timeSpans (randomly?) to apply the offset to. At the end of the process, it should be pretty chaotically spaced out.
I can provide a more detailed code sample if this is too abstract. :)
Hope this helps!
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics;
namespace TestProject1
{
[TestClass]
public class Test
{
[TestMethod]
public void TestSteps()
{
var random = new Random();
for (int i = 0; i < 20000; i++)
{
int numberOfEvents = random.Next(1,1000);
var generator = new RandomTimeStepGenerator(numberOfEvents);
var stopwatch = new Stopwatch();
stopwatch.Start();
var steps = generator.MillisecondDeltas;
Assert.AreEqual(numberOfEvents, steps.Count);
var sum = generator.MillisecondDeltas.Sum();
Assert.AreEqual(1000.0,sum,0.1);
Assert.IsTrue(stopwatch.ElapsedMilliseconds<10);
}
}
}
public class RandomTimeStepGenerator
{
private readonly int _numberOfEvents;
const int timeResolution = 10000;
public RandomTimeStepGenerator(int numberOfEvents)
{
_numberOfEvents = numberOfEvents;
}
public int NumberOfEvents
{
get { return _numberOfEvents; }
}
public List<double> MillisecondDeltas
{
get
{
var last=0;
var result = new List<double>();
var random = new Random();
for (var i = 0; i < timeResolution && result.Count < _numberOfEvents; i++)
{
var remainingEvents = _numberOfEvents - result.Count;
var remainingTime = timeResolution - i;
if(remainingEvents==1) // make sure the last event fires on the second
{
result.Add((timeResolution - last) / 10.0);
last = i;
}
else if (remainingTime <= remainingEvents) // hurry up and fire you lazy !!! your going to run out of time
{
result.Add(0.1);
}
else
{
double probability = remainingEvents / (double)remainingTime;
int next = random.Next(0,timeResolution);
if ((next*probability) > _numberOfEvents)
{
result.Add((i - last)/10.0);
last = i;
}
}
}
return result;
}
}
}
}

What's wrong in terms of performance with this code? List.Contains, random usage, threading?

I have a local class with a method used to build a list of strings and I'm finding that when I hit this method (in a for loop of 1000 times) often it's not returning the amount I request.
I have a global variable:
string[] cachedKeys
A parameter passed to the method:
int requestedNumberToGet
The method looks similar to this:
List<string> keysToReturn = new List<string>();
int numberPossibleToGet = (cachedKeys.Length <= requestedNumberToGet) ?
cachedKeys.Length : requestedNumberToGet;
Random rand = new Random();
DateTime breakoutTime = DateTime.Now.AddMilliseconds(5);
//Do we have enough to fill the request within the time? otherwise give
//however many we currently have
while (DateTime.Now < breakoutTime
&& keysToReturn.Count < numberPossibleToGet
&& cachedKeys.Length >= numberPossibleToGet)
{
string randomKey = cachedKeys[rand.Next(0, cachedKeys.Length)];
if (!keysToReturn.Contains(randomKey))
keysToReturn.Add(randomKey);
}
if (keysToReturn.Count != numberPossibleToGet)
Debugger.Break();
I have approximately 40 strings in cachedKeys none exceeding 15 characters in length.
I'm no expert with threading so I'm literally just calling this method 1000 times in a loop and consistently hitting that debug there.
The machine this is running on is a fairly beefy desktop so I would expect the breakout time to be realistic, in fact it randomly breaks at any point of the loop (I've seen 20s, 100s, 200s, 300s).
Any one have any ideas where I'm going wrong with this?
Edit: Limited to .NET 2.0
Edit: The purpose of the breakout is so that if the method is taking too long to execute, the client (several web servers using the data for XML feeds) won't have to wait while the other project dependencies initialise, they'll just be given 0 results.
Edit: Thought I'd post the performance stats
Original
'0.0042477465711424217323710136' - 10
'0.0479597267250446634977350473' - 100
'0.4721072091564710039963179678' - 1000
Skeet
'0.0007076318358897569383818334' - 10
'0.007256508857969378789762386' - 100
'0.0749829936486341141122684587' - 1000
Freddy Rios
'0.0003765841748043396576939248' - 10
'0.0046003053460705201359390649' - 100
'0.0417058592642360970458535931' - 1000
Why not just take a copy of the list - O(n) - shuffle it, also O(n) - and then return the number of keys that have been requested. In fact, the shuffle only needs to be O(nRequested). Keep swapping a random member of the unshuffled bit of the list with the very start of the unshuffled bit, then expand the shuffled bit by 1 (just a notional counter).
EDIT: Here's some code which yields the results as an IEnumerable<T>. Note that it uses deferred execution, so if you change the source that's passed in before you first start iterating through the results, you'll see those changes. After the first result is fetched, the elements will have been cached.
static IEnumerable<T> TakeRandom<T>(IEnumerable<T> source,
int sizeRequired,
Random rng)
{
List<T> list = new List<T>(source);
sizeRequired = Math.Min(sizeRequired, list.Count);
for (int i=0; i < sizeRequired; i++)
{
int index = rng.Next(list.Count-i);
T selected = list[i + index];
list[i + index] = list[i];
list[i] = selected;
yield return selected;
}
}
The idea is that at any point after you've fetched n elements, the first n elements of the list will be those elements - so we make sure that we don't pick those again. When then pick a random element from "the rest", swap it to the right position and yield it.
Hope this helps. If you're using C# 3 you might want to make this an extension method by putting "this" in front of the first parameter.
The main issue are the using retries in a random scenario to ensure you get unique values. This quickly gets out of control, specially if the amount of items requested is near to the amount of items to get i.e. if you increase the amount of keys, you will see the issue less often but that can be avoided.
The following method does it by keeping a list of the keys remaining.
List<string> GetSomeKeys(string[] cachedKeys, int requestedNumberToGet)
{
int numberPossibleToGet = Math.Min(cachedKeys.Length, requestedNumberToGet);
List<string> keysRemaining = new List<string>(cachedKeys);
List<string> keysToReturn = new List<string>(numberPossibleToGet);
Random rand = new Random();
for (int i = 0; i < numberPossibleToGet; i++)
{
int randomIndex = rand.Next(keysRemaining.Count);
keysToReturn.Add(keysRemaining[randomIndex]);
keysRemaining.RemoveAt(randomIndex);
}
return keysToReturn;
}
The timeout was necessary on your version as you could potentially keep retrying to get a value for a long time. Specially when you wanted to retrieve the whole list, in which case you would almost certainly get a fail with the version that relies on retries.
Update: The above performs better than these variations:
List<string> GetSomeKeysSwapping(string[] cachedKeys, int requestedNumberToGet)
{
int numberPossibleToGet = Math.Min(cachedKeys.Length, requestedNumberToGet);
List<string> keys = new List<string>(cachedKeys);
List<string> keysToReturn = new List<string>(numberPossibleToGet);
Random rand = new Random();
for (int i = 0; i < numberPossibleToGet; i++)
{
int index = rand.Next(numberPossibleToGet - i) + i;
keysToReturn.Add(keys[index]);
keys[index] = keys[i];
}
return keysToReturn;
}
List<string> GetSomeKeysEnumerable(string[] cachedKeys, int requestedNumberToGet)
{
Random rand = new Random();
return TakeRandom(cachedKeys, requestedNumberToGet, rand).ToList();
}
Some numbers with 10.000 iterations:
Function Name Elapsed Inclusive Time Number of Calls
GetSomeKeys 6,190.66 10,000
GetSomeKeysEnumerable 15,617.04 10,000
GetSomeKeysSwapping 8,293.64 10,000
A few thoughts.
First, your keysToReturn list is potentially being added to each time through the loop, right? You're creating an empty list and then adding each new key to the list. Since the list was not pre-sized, each add becomes an O(n) operation (see MSDN documentation). To fix this, try pre-sizing your list like this.
int numberPossibleToGet = (cachedKeys.Length <= requestedNumberToGet) ? cachedKeys.Length : requestedNumberToGet;
List<string> keysToReturn = new List<string>(numberPossibleToGet);
Second, your breakout time is unrealistic (ok, ok, impossible) on Windows. All of the information I've ever read on Windows timing suggests that the best you can possibly hope for is 10 millisecond resolution, but in practice it's more like 15-18 milliseconds. In fact, try this code:
for (int iv = 0; iv < 10000; iv++) {
Console.WriteLine( DateTime.Now.Millisecond.ToString() );
}
What you'll see in the output are discrete jumps. Here is a sample output that I just ran on my machine.
13
...
13
28
...
28
44
...
44
59
...
59
75
...
The millisecond value jumps from 13 to 28 to 44 to 59 to 75. That's roughly a 15-16 millisecond resolution in the DateTime.Now function for my machine. This behavior is consistent with what you'd see in the C runtime ftime() call. In other words, it's a systemic trait of the Windows timing mechanism. The point is, you should not rely on a consistent 5 millisecond breakout time because you won't get it.
Third, am I right to assume that the breakout time is prevent the main thread from locking up? If so, then it'd be pretty easy to spawn off your function to a ThreadPool thread and let it run to completion regardless of how long it takes. Your main thread can then operate on the data.
Use HashSet instead, HashSet is much faster for lookup than List
HashSet<string> keysToReturn = new HashSet<string>();
int numberPossibleToGet = (cachedKeys.Length <= requestedNumberToGet) ? cachedKeys.Length : requestedNumberToGet;
Random rand = new Random();
DateTime breakoutTime = DateTime.Now.AddMilliseconds(5);
int length = cachedKeys.Length;
while (DateTime.Now < breakoutTime && keysToReturn.Count < numberPossibleToGet) {
int i = rand.Next(0, length);
while (!keysToReturn.Add(cachedKeys[i])) {
i++;
if (i == length)
i = 0;
}
}
Consider using Stopwatch instead of DateTime.Now. It may simply be down to the inaccuracy of DateTime.Now when you're talking about milliseconds.
The problem could quite possibly be here:
if (!keysToReturn.Contains(randomKey))
keysToReturn.Add(randomKey);
This will require iterating over the list to determine if the key is in the return list. However, to be sure, you should try profiling this using a tool. Also, 5ms is pretty fast at .005 seconds, you may want to increase that.

Categories

Resources