Code is getting slower with every run (PowerPoint VSTO) - performance

I'm writting a PowerPoint AddIn (VSTO) which makes the following (very roughly):
1. Loop through all slides
2. Loop through all tags for each slide and write the tag information to a List-Object
3. Do some calucations on the List-Object and update some columns in the list-Object
4. Loop through the List-Object and write the tags back to the sorresponding slides / tags
I recognized that this code runs for every run slower and slowwer - the 10th run is 3-4 times slower than the first one.
I also see the memory usage goes up for every run.
What are my tools to check where the bottle neck is?
How can I find the problem which makes my code slower for every run?
Is there a way to clear the memory etc. the AddOn uses after each run?
I'm sorry to ask such general question, but please let me know if you need more details
My PowerPoint has 32 Slides - for each slide i want to write tags (in this example 49 Tags). Because of updates etc. the code is executed several times by the user. I simulate this by doing it 11 times automatically. I recognize here the same behavior as by user interaction: the writing of the tags for the 32 Slides is getting slower with every execute.
I reduced my code to the minimum which has the same behavior. I tried also to first delete the tags on every slide but without success.
private void btn_DoIt10Times_Click(object sender, EventArgs e)
{
Stopwatch watch = new Stopwatch();
watch.Start();
SlideTags_Write();
watch.Stop();
//MessageBox.Show("Time spend: " + watch.Elapsed);
for (int i = 1; i <= 10; i++)
{
SlideTags_Write();
}
Stopwatch watch2 = new Stopwatch();
watch2.Start();
SlideTags_Write();
watch2.Stop();
MessageBox.Show("Time 1st run: " + watch.Elapsed + "\n Time 11th run: " + watch2.Elapsed);
}
public void SlideTags_Write()
{
PowerPoint.Presentation oPresentation = Globals.ThisAddIn.Application.ActivePresentation;
foreach (PowerPoint.Slide oSlide in oPresentation.Slides)
{
//for (int iTag = 1; iTag <= oSlide.Tags.Count; iTag++)
//{
// oSlide.Tags.Delete(oSlide.Tags.Name(iTag));
//}
for (int iTag = 1; iTag < 50; iTag++)
{
oSlide.Tags.Add("Tag_" + iTag.ToString(), "Tag Value " + iTag.ToString());
}
}
}

Related

How can I randomize a video to play after another by pressing a key on Processing?

I'm quite new to Processing.
I'm trying to make Processing randomly play a video after I clear the screen by mouseclick, so I create an array that contain 3 videos and play one at a time.
Holding 'Spacebar' will play a video and release it will stop the video. Mouseclick will clear the screen to an image. The question is how can it randomize to another video if I press spacebar again after clear the screen.
I've been searching all over the internet but couldn't find any solution for my coding or if my logic is wrong, please help me.
Here's my code.
int value = 0;
PImage photo;
import processing.video.*;
int n = 3; //number of videos
float vidN = random(0, n+1);
int x = int (vidN);
Movie[] video = new Movie[3];
//int rand = 0;
int index = 0;
void setup() {
size(800, 500);
frameRate(30);
video = new Movie[3];
video[0] = new Movie (this, "01.mp4");
video[1] = new Movie (this, "02.mp4");
video[2] = new Movie (this, "03.mp4");
photo = loadImage("1.jpg");
}
void draw() {
}
void movieEvent(Movie video) {
video.read();
}
void keyPressed() {
if (key == ' ') {
image(video[x], 0, 0);
video[x].play();
}
}
void mouseClicked() {
if (value == 0) {
video[x].jump(0);
video[x].stop();
background(0);
image(photo, 0, 0);
}
}
You have this bit of logic in your code which picks a random integer:
float vidN = random(0, n+1);
int x = int (vidN);
In theory, if you want to randomise to another video when the spacebar is pressed again you can re-use this bit of logic:
void keyPressed() {
if (key == ' ') {
x = int(random(n+1));
image(video[x], 0, 0);
video[x].play();
}
}
(Above I've used shorthand of the two lines declaring vidN and x, but the logic is the same. If the logic is harder to follow since two operations on the same line (picking a random float between 0,n+1 and rounding down to an integer value), feel free to expand back to two lines: readability is more important).
As side notes, these bit of logic look a bit off:
the if (value == 0) condition will always be true since value never changes, making both value and the condition redundant. (Perhaps you plan to use for something else later ? If so, you could save separate sketches, but start with the simplest version and exclude anything you don't need, otherwise, in general, remove any bit of code you don't need. It will be easier to read, follow and change.)
Currently your logic says that whenever you click current video resets to the start and stops playing and when you hit the spacebar. Once you add the logic to randomise the video that the most recent frame of the current video (just randomised) will display (image(video[x], 0, 0);), then that video will play. Unless you click to stop the current video, previously started videos (via play()) will play in the background (e.g. if they have audio you'll hear them in the background even if you only see one static frame from the last time space was pressed).
Maybe this is the behaviour you want ? You've explained a localised section of what you want to achieve, but not overall what the whole of the program you posted should do. That would help others provide suggestions regarding logic.
In general, try to break the problem down to simple steps that you can test in isolation. Once you've found a solid solution for each part, you can add each part into a main sketch one at a time, testing each time you add something. (This way if something goes wrong it's easy to isolate/fix).
Kevin Workman's How To Program is a great article on this.
As a mental excercise it will help to read through the code line by line and imagine what it might do. Then run it and see if the code behaves as you predicted/intended. Slowly and surely this will get better and better. Have fun learning!

playing PDE files in a loop?

I'm still relatively new to Processing. We are thinking of showing our Processing work in a loop for a small exhibition. Is there a way to play multiple PDEs in a loop? I know I can export as frames and then assemble them as a longer loop-able Quicktime file, but I'm wondering if there's any way to play and loop the files themselves?
Also, for interactive PDEs, what's the best way to present them? We are thinking of having a couple of computers with PDEs running in Processing but it would be nice to have a file run for 20 minutes and then open another file for 20 minutes.
Thanks in advance!
You should be able to put together a shell/batch script that uses the processing-java command line executable.
You should be able to set that up via the Tools > Install "processing-java"
If you're not confortable with bash/batch scripting you could even write a Processing sketch that launches Processing sketches
Here's a very rough take on it using selectFolder() and exec():
final int SKETCH_RUN_TIME = 10000;//10 seconds for each sketch, feel free to change
ArrayList<File> sketches = new ArrayList<File>();
int sketchIndex = 0;
void setup(){
selectFolder("Select a folder containing Processing sketches:", "folderSelected");
}
void draw(){
}
void nextSketch(){
//run sketch
String sketchPath = sketches.get(sketchIndex).getAbsolutePath();
println("launching",sketchPath);
Process sketch = exec("/usr/local/bin/processing-java",
"--sketch="+sketchPath,
"--present");
//increment sketch index for next time around (checking the index is still valid, otherwise go back to 0)
sketchIndex++;
if(sketchIndex >= sketches.size()){
sketchIndex = 0;
}
//delay is deprecated so you shouldn't use this a lot, but as a proof concept this will do
delay(SKETCH_RUN_TIME);
nextSketch();
}
void folderSelected(File selection) {
if (selection == null) {
println("No folder ? Ok, maybe another time. Bye! :)");
exit();
} else {
File[] files = selection.listFiles();
//filter just Processing sketches
for(int i = 0; i < files.length; i++){
if(files[i].isDirectory()){
String folderName = files[i].getName();
File[] sketchFiles = files[i].listFiles();
boolean isValidSketch = false;
//search for a .pde file with the same folder name to check if it's a valid sketch
for(File f : sketchFiles){
if(f.getName().equals(folderName+".pde")){
isValidSketch = true;
break;
}
}
if(isValidSketch) {
sketches.add(files[i]);
}else{
System.out.println(files[i]+" is not a valid Processing sketch");
}
}
}
println("sketches found:",sketches);
nextSketch();
}
}
The code is commented so hopefully it should be easy to read and follow.
You will be prompted to select a folder containing sketches to run.
Note 1: I've used the processing-java path on my machine (/usr/local/bin/processing-java). If you're on Windows this may be different and you need to change this.
Note 2: The processing-java command launches another Process which makes it tricky to close the previous sketch before running the next one. As a workaround for you you could call exit() on each sketch after the amount of time you need.
Note 3: The code will not recursively traverse the selected folder containing sketches, so only the first level sketches will be executed, anything deeper should be ignored.

Progress when assigning datasource to XtraTreeList

I have a XtraTreeList and I assign a huge datasource (with millions of items) to it
xtraTree.TreeViewData = dataSource;
This operation takes 80 seconds to complete, which is totally fine given the amount of nodes.
I'd just like to display a somewhat reliable progress bar to the user, indicating how many nodes have been processed.
I have tried:
looking in the event list, but I only found PrintExportProgress
googling for the topic, hoping I would find something on the DevExpress support pages
I'm using the WinForms variant, version 15.2 if that matters.
This is not about displaying progress while I build the datasource. There are 2 steps:
build the datasource (read from file) - this also takes 60 seconds, but I do that myself and I have no problem here
assign the datasource to the XtraTreeList - works, but I don't get progress information and it needs to be done on the UI thread, which is blocking
This is also not about cross-thread updating of the progress bar. I know how to do that.
Hey I did the same thing in a project that I built using WinForms ... except I only had 4500 items - these items were files that I had to extract data from. What I did is at each file that I processed (at the bottom of my foreach loop) I called a method to update my progress bar on my form:
Form1.UpdateProgressbar();
Inside my Form1.cs, I did this:
public void UpdateProgressbar()
{
progressBar2.Increment(1);
label7.Text = "Processed: " + Convert.ToString(progressBar2.Value) + " out of " + Globals.totalartistcount + " Artists";
label8.Text = "Processed: " + Globals.songcounter + " Songs. Processing: " + Globals.artist;
label9.Text = "Total Number of Songs to process: " + Globals.totalsongcount;
progressBar2.Update();
Application.DoEvents();
}
If I remember right the
Application.DoEvents();
was critical to actually see the progress bar move and the labels update their text. I initialized my progress bar this way:
/* ------ progress bar ------------------------------------------ */
public void InitializeProgressBar(DirectoryInfo di)
{
int songcount = 0;
int artistcount = 0;
int index = 0;
//Get Total number of folders
foreach (var sf in di.GetDirectories())
{
//find index of artist to process
//this is just an array of artist names and if true or false to process
for (int i = 0; i <= Globals.artists.GetUpperBound(0); i++)
{
if (sf.Name == Globals.artists[i, 0])
{
index = i;
break;
}
}
if (Globals.artists[index, 1] != "false")
{
// Get a total number of files to process (MAX)
foreach (var fi in sf.GetFiles("*.mp3"))
{
songcount++;
}
artistcount++;
}
}
Globals.totalartistcount = artistcount;
Globals.totalsongcount = songcount;
progressBar2.Minimum = 0;
progressBar2.Maximum = artistcount - 1;
progressBar2.Value = 0;
Application.DoEvents();
}
There, I hope that helps.

How To Get A Random Number To Count Down

I am trying to get a random number to count down to zero, but what i have keeps giving me a random number. Then every second it will generate a new random number between 4 and 11, and won't count down. if anyone can help it would be greatly appreciated. thanks in advance!
enter code here
private void timer1_Tick(object sender, EventArgs e)
{
Random nuber = new Random();
i = nuber.Next(4, 11);
i--;
textBox1.Text = i.ToString();
if(i == 0)
{
Form1 f1 = new Form1();
Form2 f2 = new Form2();
f2.Show();
f1.Close();
}
}
If I understand what you are trying to do, then you need to generate the number outside of the loop, in an initialization phase, in a static (global) variable. Then the timer tick will count it down. Note your f1 is created and then closed, it never shows, so is superfluous. Also you are creating a new form every time which is maybe not what you want.
Basically you need to move just the two statements:
random nuber = new Random();
i = number.next();
to wherever it is that you create the timer.

Parallel loops and Random produce odd results

I just started playing with the Task Parallel Library, and ran into interesting issues; I have a general idea of what is going on, but would like to hear comments from people more competent than me to help understand what is happening. My apologies for the somewhat lengthy code.
I started with a non-parallel simulation of a random walk:
var random = new Random();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var simulations = new List<int>();
for (var run = 0; run < 20; run++)
{
var position = 0;
for (var step = 0; step < 10000000; step++)
{
if (random.Next(0, 2) == 0)
{
position--;
}
else
{
position++;
}
}
Console.WriteLine(string.Format("Terminated run {0} at position {1}.", run, position));
simulations.Add(position);
}
Console.WriteLine(string.Format("Average position: {0} .", simulations.Average()));
stopwatch.Stop();
Console.WriteLine(string.Format("Time elapsed: {0}", stopwatch.ElapsedMilliseconds));
Console.ReadLine();
I then wrote my first attempt at a parallel loop:
var localRandom = new Random();
stopwatch.Reset();
stopwatch.Start();
var parallelSimulations = new List<int>();
Parallel.For(0, 20, run =>
{
var position = 0;
for (var step = 0; step < 10000000; step++)
{
if (localRandom.Next(0, 2) == 0)
{
position--;
}
else
{
position++;
}
}
Console.WriteLine(string.Format("Terminated run {0} at position {1}.", run, position));
parallelSimulations.Add(position);
});
Console.WriteLine(string.Format("Average position: {0} .", parallelSimulations.Average()));
stopwatch.Stop();
Console.WriteLine(string.Format("Time elapsed: {0}", stopwatch.ElapsedMilliseconds));
Console.ReadLine();
When I ran it on a virtual machine set to use 1 core only, I observed a similar duration, but the runs are no longer processed in order - no surprise.
When I ran it on a dual-core machine, things went odd. I saw no improvement in time, and observed some very weird results for each run. Most runs end up with results of -1,000,000, (or very close), which indicates that Random.Next is returning 0 quasi all the time.
When I make the random local to each loop, everything works just fine, and I get the expected duration improvement:
Parallel.For(0, 20, run =>
{
var localRandom = new Random();
var position = 0;
My guess is that the problem has to do with the fact that the Random object is shared between the loops, and has some state. The lack of improvement in duration in the "failing parallel" version is I assume due to that fact that the calls to Random are not processed in parallel (even though I see that the parallel version uses both cores, whereas the original doesn't). The piece I really don't get is why the simulation results are what they are.
One separate worry I have is that if I use Random instances local to each loop, I may run into the problem of having multiple loops starting with the same seed (the issue you get when you generate multiple Randoms too close in time, resulting in identical sequences).
Any insight in what is going on would be very valuable to me!
Neither of these approaches will give you really good random numbers.
This blog post covers a lot of approaches for getting better random numbers with Random
Link
These may be fine for many day to day applications.
However if you use the same random number generator on multiple threads even with different seeds you will still impact the quality of your random numbers. This is because you are generating sequences of pseudo-random numbers which may overlap.
This video explains why in a bit more detail:
http://software.intel.com/en-us/videos/tim-mattson-use-and-abuse-of-random-numbers/
If you want really random numbers then you really need to use the crypto random number generator System.Security.Cryptography.RNGCryptoServiceProvider. This is threadsafe.
The Random class is not thread-safe; if you use it on multiple threads, it can get messed up.
You should make a separate Random instance on each thread, and make sure that they don't end up using the same seed. (eg, Environment.TickCount * Thread.CurrentThread.ManagedThreadId)
One core problem:
random.Next is not thread safe.
Two ramifications:
Quality of the randomness is destroyed by race conditions.
False sharing destroys scalability on multicores.
Several possible solutions:
Make random.Next thread safe: solves quality issue but not scalability.
Use multiple PRNGs: solves scalability issue but may degrade quality.
...

Resources