Arrays in PowerBuilder - arrays

I have this code
n_userobject inv_userobject[]
For i = 1 to dw_1.Rowcount()
inv_userobject[i] = create n_userobject
.
.
.
NEXT
dw_1.rowcount() returns only 210 rows. Its so odd that in the range of 170 up, the application stop and crashes on inv_userobject[i] = create n_userobject.
My question, is there any limit on array or userobject declaration using arrays?
I already try destroying it after the loop so as to check if that will be a possible solution, but it is still crashing.
Or how can i be able to somehow refresh the userobject?
Or is there anyone out there encounter this?
Thanks for all your help.

First, your memory problem. You're definitely not running into an array limit. If I was to take a guess, one of the instance variables in n_userobject isn't being cleaned up properly (i.e. pointing to a class that isn't being destroyed when the parent class is destroyed) or pointing to a class that similarly doesn't clean itself up. If you've got PB Enterprise, I'd do a profiling trace with a smaller loop and see what is being garbage collected (there's a utility called CDMatch that really helps this process).
Secondly, let's face it, you're just doing this to avoid writing a reset method. Even if you get this functional, it will never be as efficient as writing your own reset method and reusing the same instance over again. Yes, it's another method you'll have to maintain whenever the instance variable list changes or the defaults change, but you'll easily gain that back in performance.
Good luck,
Terry.

I'm assuming the crash you're facing is at the PBVM level, and not a regular PB exception (which you can catch in your code). If I'm wrong, please add the exception details.
A loop of 170-210 iterations really isn't a large one. However, crashes within loops are usually the result of resource exhaustion. What we usually do in long loops is call GarbageCollect() occasionally. How often should it be called depends on what your code does - using it frequently could allow the use of less memory, but it will slow down the run. Read this for more.
If this doesn't help, make sure the error does not come from some non-PB code (imported DLL or so). You can check the stack trace during the crash to see the exception's origin.
Lastly, if you're supported by Sybase (or a local representative), you can send them a crash dump. They can analyze it, and see if it's a bug in PB, and if so, let you know when it was (or will be) fixed.

What I would normally do with a DataWindow is to create an object that processes the data in a row and call it for each row.

the only suggestion i have for this is to remove the rowcount from the for (For i = 1 to dw_1.Rowcount()) this will cause the code to recount the rows every time it uses one. get the count into a variable and then use the variable. it should run a bit better and be far more easy to debug.

Related

Nagios Auto Rescheduling Feature Default Values Wrong?

I am trying to understand how the auto rescheduling logic is supposed to work.
The recommended values in nagios.cfg are:
auto_reschedule_checks=1
auto_rescheduling_interval=30
auto_rescheduling_window=45
Supposedly this is after they realized the default values (same as above but with window=180) had the potential to have checks that never actually get executed (See https://support.nagios.com/kb/print-19.html).
But.. How are these new values any different?
How I understand it, every 30sec, it takes the next 45sec of checks, finds checks that overlap, and reschedules those evenly across the 45sec.
Isnt it possible for a check to indefinitely get rescheduled into that last 15 seconds of the 45sec window?
Am I missing something? Do rescheduled checks get an elevated priority so they arent rescheduled again? Reading through the code, it doesnt appear they are given any special treatment.
Seems to me that the only way to prevent that is for the interval and window to be the same.
Which means maybe a couple checks occurring right at each 30sec transition may go unnoticed,
but Id rather that than what I am presuming the behavior is with the "recommended" interval=30sec , window=45sec.
Any insights would be helpful!

Swift threading issue in Array

In my project, have a data provider, which provides data in every 2 milli seconds. Following is the delegate method in which the data is getting.
func measurementUpdated(_ measurement: Double) {
measurements.append(measurement)
guard measurements.count >= 300 else { return }
ecgView.measurements = Array(measurements.suffix(300))
DispatchQueue.main.async {
self.ecgView.setNeedsDisplay()
}
guard measurements.count >= 50000 else { return }
let olderMeasurementsPrefix = measurements.count - 50000
measurements = Array(measurements.dropFirst(olderMeasurementsPrefix))
print("Measurement Count : \(measurements.count)")
}
What I am trying to do is that when the array has more than 50000 elements, to delete the older measurement in the first n index of Array, for which I am using the dropFirst method of Array.
But, I am getting a crash with the following message:
Fatal error: Can't form Range with upperBound < lowerBound
I think the issue due to threading, both appending and deletion might happen at the same time, since the delegate is firing in a time interval of 2 millisecond. Can you suggest me an optimized way to resolve this issue?
So to really fix this, we need to first address two of your claims:
1) You said, in effect, that measurementUpdated() would be called on the main thread (for you said both append and dropFirst would be called on main thread. You also said several times that measurementUpdated() would be called every 2ms. You do not want to be calling a method every 2ms on the main thread. You'll pile up quite a lot of them very quickly, and get many delays in their updating, as the main thread is going to have UI stuff to be doing, and that always eats up time.
So first rule: measurementUpdated() should always be called on another thread. Keep it the same thread, though.
Second rule: The entire code path from whatever collects the data to when measurementUpdated() is called must also be on a non-main thread. It can be on the thread that measurementUpdated(), but doesn't have to be.
Third rule: You do not need your UI graph to update every 2ms. The human eye cannot perceive UI change that's faster than about 150ms. Also, the device's main thread will get totally bogged down trying to re-render as frequently as every 2ms. I bet your graph UI can't even render a single pass at 2ms! So let's give your main thread a break, by only updating the graph every, say, 150ms. Measure the current time in MS and compare against the last time you updated the graph from this routine.
Fourth rule: don't change any array (or any object) in two different threads without doing a mutex lock, as they'll sometimes collide (one thread will be trying to do an operation on it while another is too). An excellent article that covers all the current swift ways of doing mutex locks is Matt Gallagher's Mutexes and closure capture in Swift. It's a great read, and has both simple and advanced solutions and their tradeoffs.
One other suggestion: You're allocating or reallocating a few arrays every 2ms. It's unnecessary, and adds undue stress on the memory pools under the hood, I'd think. I suggest not doing append and dropsFirst calls. Try rewriting such that you have a single array that holds 50,000 doubles, and never changes size. Simply change values in the array, and keep 2 indexes so that you always know where the "start" and the "end" of the data set is within the array. i.e. pretend the next array element after the last is the first array element (pretend the array loops around to the front). Then you're not churning memory at all, and it'll operate much quicker too. You can surely find Array extensions people have written to make this trivial to use. Every 150ms you can copy the data into a second pre-allocated array in the correct order for your graph UI to consume, or just pass the two indexes to your graph UI if you own your graph UI and can adjust it to accommodate.
I don't have time right now to write a code example that covers all of this (maybe someone else does), but I'll try to revisit this tomorrow. It'd actually be a lot better for you if you made a renewed stab at it yourself, and then ask us a new question (on a new StackOverflow) if you get stuck.
Update As #Smartcat correctly pointed this solution has the potential of causing memory issues if the main thread is not fast enough to consume the arrays in the same pace the worker thread produces them.
The problem seems to be caused by ecgView's measurements property: you are writing to it on the thread receiving the data, while the view tries to read from it on the main thread, and simultaneous accesses to the same data from multiple thread is (unfortunately) likely to generate race conditions.
In conclusion, you need to make sure that both reads and writes happen on the same thread, and can easily be achieved my moving the setter call within the async dispatch:
let ecgViewMeasurements = Array(measurements.suffix(300))
DispatchQueue.main.async {
self.ecgView.measurements = ecgViewMeasurements
self.ecgView.setNeedsDisplay()
}
According to what you say, I will assume the delegate is calling the measuramentUpdate method from a concurrent thread.
If that's the case, and the problem is really related to threading, this should fix your problem:
func measurementUpdated(_ measurement: Double) {
DispatchQueue(label: "MySerialQueue").async {
measurements.append(measurement)
guard measurements.count >= 300 else { return }
ecgView.measurements = Array(measurements.suffix(300))
DispatchQueue.main.async {
self.ecgView.setNeedsDisplay()
}
guard measurements.count >= 50000 else { return }
let olderMeasurementsPrefix = measurements.count - 50000
measurements = Array(measurements.dropFirst(olderMeasurementsPrefix))
print("Measurement Count : \(measurements.count)")
}
}
This will put the code in an serial queue. This way you can ensure that this block of code will run only one at a time.

Breakable loop in Scratch?

How do you make a breakable loop in Scratch? I'm using Scratch 2.0 and can't find any good way to make a loop breakable, from inside of the loop itself.
Disclaimer:
There is no perfect way to do it. If you can possibly stand this true fact then feel free to continue.
There are a few different ways you could do it.
With repeat until
The first and most simple one follows this:
But this isn't technically part of the script - it's just repeating until some value returns true.
With a custom block (stop this script)
In order to do it inside of the script, you'll need to use a sneaky little trick with custom blocks.
Create a custom block called whatever you want - but probably along the lines of "breakable loop". Inside of it, create this script:
By using stop script we are breaking out of the script that is currently running - which, according to Scratch, is the custom block.
See the result! (as scratchblocks)
With broadcast and wait
You could also use a broadcast-and-wait method, very similar to above:
Though I highly suggest you don't use this method, as if any other sprites have breakable loops you'll need to rename each one, which can be tedious after using a lot of loops in a lot of sprites!
(Note this bug has been fixed in version 442 of the editor and such the following no longer applies.)
Help! My project is lagging a bunch now!
As #foi has noticed, if your code must be run inside of a frame you probably checked run without screen refresh. Unfortunately, due to a bug in the Scratch player, this causes the program to essentially break after the stop this script block has been activated. How can you handle this?
It follows the same principle you use when you use a run without screen refresh custom block inside of a forever loop - the loop doesn't use screen refresh while the inside does, allowing for instant animations whether or not one is using turbo mode.
Here's an example - the image is really too long to be embedded, so see it here instead.
You can make a variable inside or outside of the repeat and make your script like this:
repeat until [[my variable] = [e.g: 1]]
your code
your code
your code
your code
end of repeat until
For a "repeat until" block the simplest way would be to "or" your normal until condition with the break condition in the until.
By adding an incremeting loop counter variable in the loop you can use a "repeat until" to replicate the function of a "repeat n times" block
By using a "repeat until" block with only your break condition you get the equivalent of a "forever" block
If you need another script/ sprite to trigger the break then a public variable will let you break the loop from anywhere and let a single condition break loops for different sprites.
I'd post an image of the blocks but this is my first reply and the site won't let me!
good luck
You can use these few ways to do it...
conditional loop
stop this script
if then else, in the else section, put nothing
I would prefer to use the first method, as it requires less blocks and for the first method, you can still add in code that will be executed after the loop has stopped executing.
You can make it repeat x times or make it have a certain point where it stops, such as another variable changing.
Otherwise, I don't think there is a wat to do that.
Use the repeat until block. Then put in an equals block or whatever into the boolean part. Then inside that repeat until block, put a stop this script block.
Hope this helps :D

Array.Clear throwing out of bounds exception

I'm having trouble with a clear statement. I've got an array that gets sized dynamically, filled, and then passed to a function to be converted to some custom objects.
After that conversion I want to clear the array. I use
Array.Clear(FileData, 0, FileData.Length)
as this thread suggests (reset-an-array-to-default-in-visual-basic). However, every time I get to that point in the script the try-catch wrapping the Clear catches an out of bounds exception on the Clear.
The array is not empty (actually it's got ~34900 items) so it's not that the array has zero length. The one thing that it might be that isn't discussed in the question I referenced above is that my array is 2 dimensional.
All that said, I'm fairly well stumped. Any help would be appreciated.
UPDATE: For those experiencing this issue, I ultimately just left the step commented out, so that instead of clearing and then setting the array to Nothing, I just set it to Nothing. Doesn't really solve the underlying issue, but (should) free up memory all the same.

WPF app with multiple usercontrols

I Am creating simple WPF test project which contains multiple UserControls(Insteda of Pages).I Am using Switcher Class to navigate between different UserControls.When i navigate to different pages,i have observed that memory consuption keep on increasing on each UserControle Navigationand GC is not invoked.
1.So am i doing something wrong in following code?
2.Which part of the code consuming more memory?
3.Do i need to invoke GC for disposing my UserControls on each new UserControle creation?
If need how can i invoke GC?
public void On_Navigate_Click()
{
UserControle newusercontrole=new UserControle();
DataSet ds = new DataSet();
ds=con.getSome_Datafrom_SQL();//Gets data from SQL via connection class
dataGrid_test.ItemsSource = ds.Tables[0].DefaultView;
Grid.SetColumn(newusercontrole, 1);//dataGrid_test is inside newusercontrole and following is the code to add "this" usercontrol to the main window.
Grid.SetRow(newusercontrole, 1);
Grid.SetZIndex(newusercontrole, 10);
Container.Children.Add(newusercontrole);
}
First off, I must point out that if garbage collection really isn't happening (as you said), it's not your fault and it does not mean you're doing something wrong. It only means that the CLR doesn't think that your system is under memory pressure yet.
Now, to manually invoke a garbage collection cycle anyway, you can use the GC.Collect() static method. If a garbage collection actually starts and your memory consumption is still unreasonably high, this means that you're probably doing something wrong: You're keeping an ever increasing number of unnecessary object references and the garbage collector cannot safely collect those objects. This is a kind of a memory leak.
As far as your code goes, I think that the problem is at the end of the method you posted:
Container.Children.Add(newusercontrole);
This seems to add a new object (on every click) to the collection Container.Children. If this is not removed elsewhere, this is probably the cause of your memory leak. I don't know what the suitable solution would be for your use case (since I don't know exactly how your UI should behave), but you'll likely need to find a way to remove the last UserControle added from the Container.Children. If you can use LINQ, then the methods OfType<T>() and Last() could be of use to find it.
In any case, don't leave the GC.Collect() line in production code. Use it only to force a collection cycle for testing purposes, like this one.

Resources