Faster way to search through a big string? - c#

I am currently trying to make a program to find blocks of a specific color in a game save and move their position, however with some of the bigger saves my method of searching for the blocks in the save can start to take a bit. My current fastest method takes about 42 seconds to search for and move every block in a string about the size of 1MB. There are a lot of blocks in the save (Roughly one every 50-300 characters in the string, with a total of around 7k) so I'm not sure if string search algorithms would speed up or slow down this process.
So, I was wondering if I could get any tips of if anyone had any ideas on how to further speed up my code I would be very greatfull.
progressBar2.Maximum = blueprint.Length;
int i = 0;
while (i < blueprint.Length - 15)
{
progressBar2.Value = i;
try
{
if (!blueprint.Substring(i, 110).ToLower()
.Contains("\"color\""))
{
i += 100;
}
}
catch
{
return;
}
checkcolor(i, color, colortf, posset, axis);
i++;
}
I am currently optimizing the method checkcolor and it's the cause for most of the delay, but my current method runs it way more than needed.
I've tried adding a second if to skip at an interval of 10 as well as 100 but that caused it to take over 2 min, I've also tried different values to skip other then 100 but 100 seems to be the fastest.
Edit: I was making 2 new temporary strings just to check for a small bit of text millions of times, it's a lot faster to use .IndexOf which I did not know existed. Thanks for the help and sorry if this was off topic.

I would try to compare efficiency without creation substring and using ToLower():
if (!blueprint.IndexOf("\"color\"", StringComparison.OrdinalIgnoreCase) >= 0)

Related

Creating a Square Wave (Alternating between high and low) in C#

I am trying to find a way to create a 2 Hz square wave to an LED (Basically toggle between high and low at 2Hz) I have a general sense of how I think it should go, but not really sure what to do as I am new to C#, any help would be greatly appreciated!
Here's my general thought process:
While(Programruns){
read input
(I feel like there should be a for loop here to keep the square wave going forever until I stop it)
if(button is pressed){
output square wave
}
else {
off}
}
You want a loop with a sleep operation in it.
You didn't tell us how you turn on and off that LED, so I will assume you have a method called SetLED(val). A val of 0 turns the LED off, and 1 turns it on. And, let's have a method called ButtonPressed() that comes back true when the button is pressed.
To get a 2Hz square wave you want to flip val every 250 milliseconds. This code will do that for you.
var ledState = 1;
while (ButtonPressed()) {
SetLED(ledState);
Thread.Sleep(250); //milliseconds
ledState = 1 - ledState; //flip the value
}
SetLED(0); // turn the LED off when done.
That will basically work. But there's a complication: C# and its various underlying operating systems are not hard real-time systems. Therefore Thread.Sleep() sometimes wakes up a bit late. These late wakeups can accumulate and make your square wave a little jittery and, cumulatively, less than 2Hz. You can't do much about the jitter.
But you can avoid the frequency degradation by looking at the time-of-day clock and computing how long to sleep in each loop.
The expression DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond gets you the present time in milliseconds (since some long-ago epoch).
So you can compute the number of milliseconds for the next sleep in your code. That corrects for .Sleep() oversleeping.
var ledState = 1;
long nextTickTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
while (ButtonPressed()) {
SetLED(ledState);
nextTickTime += 250;
long nowTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
int sleepInterval = nextTickTime - nowTime;
if (sleepInterval > 0)
Thread.Sleep(sleepInterval);
ledState = 1 - ledState; //flip the value
}
SetLED(0); // turn the LED off when done.
That's a fairly robust blinker. You can also raise the priority of the thread while the loop is running, but that's a question and answer for another day.

Randomly generating an int value in for loop. After 7 iterations, it returns a very large negative number. Why is this?

The code below is rotating a wheel either 10 times or 1 time depending on whether or not the user selects 'yes'.
The rotation method takes a number between 0-100, and rotates the filter an amount based on that number. To test the machine, I want to generate a random number between 0-99. I feel this method should be able to do that. However, after 7 times, the random number produced is -2.147483465E+09 until the end of the run. The output, for example:
89
20
1
58
78
39
90
-2.147483465E+09
-2.147483465E+09
-2.147483465E+09
Could this be something related to garbage collection? The 'sUVFilter' is not changed to 0 by the method, these are the values it gets when I set it = to rand.Next();
Any help or information would be appreciated! Thanks a lot. Here is the code in question.
private void RotateFilterWheel()
{
List<float> filterValuesList = new List<float>();
int timesToRotate = 1;
int success = 0;
Random rand = new Random();
MessageBoxResult result = MessageBox.Show("Rotate filter 10 times?", "Rotate Filter", MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
timesToRotate = 10;
}
for (int x = 0; x < timesToRotate; x++)
{
int sUVFilter = rand.Next(99);
_instDrvr.SetSpectroAutoUVFilterPosition(sUVFilter, ref success);
filterValuesList.Add(sUVFilter);
Thread.Sleep(5000);
}
listBox.ItemsSource = filterValuesList;
}
From the comments:
_instDrvr.SetSpectroAutoUVFilterPosition(sUVFilter, ref success);
That is the real trouble-maker in your program. We don't know enough about it, other than it appears to operate a motor. So you are probably use some company's library to do this, such code is often unmanaged. Could be a COM component, could be using pinvoke.
The diagnostic is that it corrupts the stack of your method. There is more than one way it could do this. One easy way is that it corrupts the value of the EBP processor register in 32-bit code, the RSP register in 64-bit code. Easy to check, use Debug > Windows > Registers and double-check that the register has the exact same value before and after the call.
And it can corrupt the stack frame easily, especially so thanks to the ref success argument. Which passes a pointer to your success variable, stored on the stack frame. Gives it way to easily write more than 4 bytes, this will cause other local variable(s) of your method to randomly change their value. Such memory corruption is much harder to diagnose, other than the obviously weirdo values you see back in the debugger.
That's about all that can be guessed at, you almost certainly need help from the motor controller manufacturer or software vendor to get this problem solved.

Returning each value from for loop in c#

EDIT: I realized that I had been going about it completely the wrong way and after an overhaul, got it working. Thanks for the tips guys, I'll keep them in mind for the future.
I've hit an unusual problem in my program. What I need to do is find the difference between two times, divide it by 1.5 hours, then return the starting time followed by each 1.5 hour increment of the starting time. So if the time was 11:45 am - 2:45 pm, the time difference is three hours, 3/1.5 = 2, then return 11:45 am and 1:15 pm. At the moment, I can do everything except return more than one time. Depending on what I've tried, it returns either the initial time (11:45 am), the first increment (1:15 pm) or the end time (2:45 pm). So far I've tried a few different types of for and do/while loops. The closest I've come was simply concatenating the start time and the incremented time, but the start and end times can range anywhere from 3 - 6 hours so that's not a practical way to do it.
The latest thing I tried:
int i = 0;
do{
i++;
//Start is the starting time, say 11:45 am
start = start.AddMinutes(90);
return start.ToShortTimeString();
} while (i < totalSessions); //totalSessions is the result of hours / 1.5
and I'm calling the function on a dynamic label (which is also in a for loop):
z[i] = new Label();
z[i].Location = new Point(PointX, PointZ);
z[i].Name = "sessionTime_" + i;
z[i].Text = getPlayTimes(dt.Rows[i][1].ToString());
tabPage1.Controls.Add(z[i]);
z[i].BringToFront();
PointZ += z[i].Height;
I'm pretty new to c# so I guess I've just misunderstood something somewhere.
I think you're trying to solve the problem the wrong way. Instead of returning each value as you come to it, create a collection ie List, and push each of your results onto the list until your finishing condition is met.
Then, return the whole array as your return value. This way you will have a nice self-contained function that doesn't have cross-concerns with other logic - it does only it's one little task but does it well.
Good luck!
It's a bit difficult to determine your exact use case, as you haven't offered the complete code you are using. However, you can do what you are asking by using the yield return functionality:
public IEnumerable<string> GetPlayTimes()
{
int i = 0;
do
{
i++;
//Start is the starting time, say 11:45 am
start = start.AddMinutes(90);
yield return start.ToShortTimeString();
} while (i < totalSessions); //totalSessions is the result of hours / 1.5
}
And then use it like so:
foreach (var time in GetPlayTimes())
{
// Do something with time
}

C# Fastest way to find the index of item in a list

I want to know what is the fastest way to find the index of an item in a list. The reason I want to know is because I am making a XNA render but I started getting out of memory exceptions on larger models when I only used a vertex buffer, so I have now implemented an index buffer system. My problem is that I now have to continuously scan a list containing all my Vector3s for the index of the one that I want placed next in my index buffer. I am currently scanning for indices like this:
for (int i = 1; i < circleVect.Length; i++)
{
indices.Add(vertices.FindIndex(v3 => v3 == circleVect[i]));
indices.Add(vertices.FindIndex(v3 => v3 == circleVect[i - 1]));
indices.Add(vertices.FindIndex(v3 => v3 == middle));
}
This works fine except for the fact that it is rather slow. It takes almost 1 second for one cylinder to be calculated and I have more than 70 000 of them in my large model. I have therefore been seeing a loading screen for more than 20 minutes while loading my larger model and it still is not completed. This is unfortunately simply unacceptable. If I try loading my smaller model it takes more than 5 minutes whereas the unindexed loader took merely a second or so.
I have absolutely no formal training in C# and even less in XNA so I know this is probably a very inefficient way of calculating the indices so I would therefore appreciate it if any of you could assist me in creating a more efficient importer.
PS. If necessary I can change the list to an array but this would be a last resort option because it could potentially put strain on the system memory (causing an exception) and would mean quite a bit of coding for me.
in your code you are looping through your vertices 3 times one for each FindIndex line. Instead use one for loop and traverse and check for all three conditions in 1 go.
Your main performance killer is searching in a List of 70 000 items which takes 70 000 operations.
This will work a lot faster than searching in a list.
Dictionary<int, Vertice> vertices = new Dictionary<int, Vertice>();
for (int i = 1; i < vertices.Length; i++)
{
if (vertices.ContainsKey(vertices[i]))
{
indices.Add(vertices[i]);
}
if (vertices.ContainsKey(vertices[i - 1]))
{
indices.Add(vertices[i - 1]);
}
if (vertices.ContainsKey(vertices[middle]))
{
indices.Add(vertices[middle]);
}
}
edit: if searching in the list takes 2 seconds, searching in a dictionary will take 00:00:02 seconds
for (int i = 1; i < circleVect.Length; i++)
{
for (int j = 0; j < vertices.Count; j++)
{
var v3 = vertices[j];
if (v3 == circleVect[i] || v3 == circleVect[i - 1] || v3 == middle)
indices.Add(j);
}
}
You may want to consider adding logic to stop the inner loop from checking after all three of the indexes have been found.
Thanks for all the answers but none of them really worked and really appeard to be faster than what I had. I ended up having to create a structure where I could calculate the needed list index based on a given reference point.

While loop execution time

We were having a performance issue in a C# while loop. The loop was super slow doing only one simple math calc. Turns out that parmIn can be a huge number anywhere from 999999999 to MaxInt. We hadn't anticipated the giant value of parmIn. We have fixed our code using a different methodology.
The loop, coded for simplicity below, did one math calc. I am just curious as to what the actual execution time for a single iteration of a while loop containing one simple math calc is?
int v1=0;
while(v1 < parmIn) {
v1+=parmIn2;
}
There is something else going on here. The following will complete in ~100ms for me. You say that the parmIn can approach MaxInt. If this is true, and the ParmIn2 is > 1, you're not checking to see if your int + the new int will overflow. If ParmIn >= MaxInt - parmIn2, your loop might never complete as it will roll back over to MinInt and continue.
static void Main(string[] args)
{
int i = 0;
int x = int.MaxValue - 50;
int z = 42;
System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();
st.Start();
while (i < x)
{
i += z;
}
st.Stop();
Console.WriteLine(st.Elapsed.Milliseconds.ToString());
Console.ReadLine();
}
Assuming an optimal compiler, it should be one operation to check the while condition, and one operation to do the addition.
The time, small as it is, to execute just one iteration of the loop shown in your question is ... surprise ... small.
However, it depends on the actual CPU speed and whatnot exactly how small it is.
It should be just a few machine instructions, so not many cycles to pass once through the iteration, but there could be a few cycles to loop back up, especially if branch prediction fails.
In any case, the code as shown either suffers from:
Premature optimization (in that you're asking about timing for it)
Incorrect assumptions. You can probably get a much faster code if parmIn is big by just calculating how many loop iterations you would have to perform, and do a multiplication. (note again that this might be an incorrect assumption, which is why there is only one sure way to find performance issues, measure measure measure)
What is your real question?
It depends on the processor you are using and the calculation it is performing. (For example, even on some modern architectures, an add may take only one clock cycle, but a divide may take many clock cycles. There is a comparison to determine if the loop should continue, which is likely to be around one clock cycle, and then a branch back to the start of the loop, which may take any number of cycles depending on pipeline size and branch prediction)
IMHO the best way to find out more is to put the code you are interested into a very large loop (millions of iterations), time the loop, and divide by the number of iterations - this will give you an idea of how long it takes per iteration of the loop. (on your PC). You can try different operations and learn a bit about how your PC works. I prefer this "hands on" approach (at least to start with) because you can learn so much more from physically trying it than just asking someone else to tell you the answer.
The while loop is couple of instructions and one instruction for the math operation. You're really looking at a minimal execution time for one iteration. it's the sheer number of iterations you're doing that is killing you.
Note that a tight loop like this has implications on other things as well, as it bogs down one CPU and it blocks the UI thread (if it's running on it). Thus, not only it is slow due to the number of operations, it also adds a perceived perf impact due to making the whole machine look unresponsive.
If you're interested in the actual execution time, why not time it for yourself and find out?
int parmIn = 10 * 1000 * 1000; // 10 million
int v1=0;
Stopwatch sw = Stopwatch.StartNew();
while(v1 < parmIn) {
v1+=parmIn2;
}
sw.Stop();
double opsPerSec = (double)parmIn / sw.Elapsed.TotalSeconds;
And, of course, the time for one iteration is 1/opsPerSec.
Whenever someone asks about how fast control structures in any language you know they are trying to optimize the wrong thing. If you find yourself changing all your i++ to ++i or changing all your switch to if...else for speed you are micro-optimizing. And micro optimizations almost never give you the speed you want. Instead, think a bit more about what you are really trying to do and devise a better way to do it.
I'm not sure if the code you posted is really what you intend to do or if it is simply the loop stripped down to what you think is causing the problem. If it is the former then what you are trying to do is find the largest value of a number that is smaller than another number. If this is really what you want then you don't really need a loop:
// assuming v1, parmIn and parmIn2 are integers,
// and you want the largest number (v1) that is
// smaller than parmIn but is a multiple of parmIn2.
// AGAIN, assuming INTEGER MATH:
v1 = (parmIn/parmIn2)*parmIn2;
EDIT: I just realized that the code as originally written gives the smallest number that is a multiple of parmIn2 that is larger than parmIn. So the correct code is:
v1 = ((parmIn/parmIn2)*parmIn2)+parmIn2;
If this is not what you really want then my advise remains the same: think a bit on what you are really trying to do (or ask on Stackoverflow) instead of trying to find out weather while or for is faster. Of course, you won't always find a mathematical solution to the problem. In which case there are other strategies to lower the number of loops taken. Here's one based on your current problem: keep doubling the incrementer until it is too large and then back off until it is just right:
int v1=0;
int incrementer=parmIn2;
// keep doubling the incrementer to
// speed up the loop:
while(v1 < parmIn) {
v1+=incrementer;
incrementer=incrementer*2;
}
// now v1 is too big, back off
// and resume normal loop:
v1-=incrementer;
while(v1 < parmIn) {
v1+=parmIn2;
}
Here's yet another alternative that speeds up the loop:
// First count at 100x speed
while(v1 < parmIn) {
v1+=parmIn2*100;
}
// back off and count at 50x speed
v1-=parmIn2*100;
while(v1 < parmIn) {
v1+=parmIn2*50;
}
// back off and count at 10x speed
v1-=parmIn2*50;
while(v1 < parmIn) {
v1+=parmIn2*10;
}
// back off and count at normal speed
v1-=parmIn2*10;
while(v1 < parmIn) {
v1+=parmIn2;
}
In my experience, especially with graphics programming where you have millions of pixels or polygons to process, speeding up code usually involve adding even more code which translates to more processor instructions instead of trying to find the fewest instructions possible for the task at hand. The trick is to avoid processing what you don't have to.

Categories