Tuesday, June 18, 2019

Memory Management Tips


I have a few memory management tips that I thought I would share.   If you have other debugging tips then please share them with us.

The Memory Usage Block in the Utility Library 
The Memory Usage block will show you the amount of memory each block, each h-block, and each database table are using.  This list can be sorted (by clicking at the top of the column) to show you which ones are consuming the most.  It is the first step to making your model more manageable.

History Blocks
If a History block shows up in the Memory Usage list as a major consumer of memory, check out how many rows are in the history table.  From time to time, I will set a History block up to record more than just 1000 rows (default).   I might want to set it up for 10,000 rows or more, so I can see all items that traveled through it.  If I ever forget to reset this back down to 1000 rows or even delete the History block altogether, it can consume a bit of memory with an excessive row quantity.  I also like to set up the History block so the data is not saved when the model is saved.  Finally, I like to use the temporary History block if I am debugging.  This is the one that dangles off of an item output.  I like to use this one because every so often I can delete them all with a simple right click.

Queue Item Contents and Activity Item Contents
If an Activity or Queue shows up in the Memory block list, check out the Item Contents tab. The Item Contents tab on the Queue and History can get large under various conditions. For example, if you are showing the historical log and have many items have traveled through it across the run, then it does take up a great deal of memory. 

Database Tables \ Log Tables
If a database table shows up in the Memory block list, check out how many records the table contains.  Tables that contain a log of items or events that constantly grow can be pesky at times when it comes to consuming memory.  The log tables are useful for debugging and analysis; however, when doing really long runs for multiple replications, they can become huge.  I suggest you add a flag as a user input that has the capability to turn off capturing the detailed log table in situations where the table isn’t necessary. The flag is useful when you are performing a large number of replications for a study, and you are really only interested in the high-level results and not a detailed log.

.BAK file
By default, the model makes a backup copy of itself every time you save the model.  This file has the same name but has an extension of .bak instead of .mox.  The model will use this when you use the function File \ Revert Model to revert the model to the last save version.  The backup file isn’t necessary for any other reason.  For older versions of the model, you can definitely delete their .bak.  If you don’t want to create the .bak file in the first place, there is an option that you can set to turn it off.  This can be set in the Edit\Options\Misc tab.  By the way, when you email your model to others or you make a backup copy of the model, the .BAK file does not need to be included. 

Monday, June 3, 2019

Debugging Tips

I have a few debugging tips that I thought I would share.  If you have other debugging tips then please share them with us.

Test as you go
Don’t wait to the end of model development to start testing.  Test as you build.  If you wait until the end to verify the model works correctly, it will take much longer to find bugs because you have to search through the entire model. Build the model in small chunks and test thoroughly as you go.  If you test as you go, the new bugs will be in the constructs you have just built.  You will be focused on a smaller construct to look for the bug while that logic is fresh on your mind.  This is such a crucial aspect of the modeling process that it deserves mentioning more than once! 

Snipping Tool or Snagit or Print Screen
Get access to a screen capture tool and keep it handy.  When an error message pops up, take a screenshot of it.  Don’t be click happy and absent-mindedly click the OK button when errors appear.  If you don’t document what the errors are, you will have to rerun the model again because you will quickly forget the exact details of the error message.  I think the Snipping Tool is installed with Windows, but I am a big fan of SnagIt.

Logging exceptions
No one can or should constantly look for every potential bad event each time they run the model.  For example, if an item stays in the system 10x longer than you expect, there might be a potential problem.  Or if item type x ever goes through a specific construct then you know you have a potential problem.  You can and should continue to monitor that event in case another bug shows up.  There are many more instances that require monitoring, but they shouldn’t consume our attention. 
These are events where you need to set up a construct to log the “exception” events to an error log table in the database when they occur.  You should also report the number of these exceptions on the main model worksheet when and if they occur, so they are sure to grab your attention.  Once you have finished verifying and validating your model, then you can take the exceptions out or have a flag that turns them off. You may also want to leave them in just to reduce your worry.  Logging error events or exception events is a great way to monitor the system.  Note, however, that if you put error events in that are really warnings, you might overlook real errors when they occur.

 Find dialog
If you have an error message and it refers to an object number, you can use the menu shortcut "Control + F" to open the Find dialog in order to find the object number. 

Global Random Seed
If you need to debug your model and want a repeatable result from run to run, you can fix the Global Random Seed.  Debugging can be difficult if the bug appears at different simulation times from run to run.  Fixing the global random seed can be done in the Random Number tab of the Simulation Setup dialog.  If you want to repeat the last model run, set the Random Seed to the "Starting seed used in the last model run."   Setting the seed to any positive number will allow the model to run with a repeatable stream of random numbers, thus giving repeatable results.  Setting the seed to 0 or blank provides a random starting seed. 

Releasing resources
Be careful when you release resources.  The Resource Pool Release block is used to return the resource back to the appropriate pool when the resource is no longer required.  If the block immediately downstream from the Resource Pool Release block has a capacity limit and is full, the resource won’t get released when it is finished with the upstream task.  The resource won’t get released until the item with the resource can move past the Resource Pool Release block and into the next residence block downstream.  This issue is easy to overlook.  It will prevent the resource from being used elsewhere even though it is done with its current task.  The Resource Pool will overly estimate its utilization.  I suggest you specifically look for this issue at the end of model development on every model.  The following construct is one way to eliminate the issue.  In this construct, when the Activity for Task X is busy, the item will be in the Activity labeled "Task X Busy".  When the Activity for Task X is blocked, it will wait in the queue labeled "Task X Blocked" while the Gate prevents anything new from arriving into the Activity block.
  

Debugging infinite loops where the simulation time never progresses past a certain point
Occasionally your model might have a bug which causes it to go into an infinite loop.  This loop could be due to several reasons.  The reasons could involve either creating an infinite number of items, an item looping continuously in a circle, from an unending for loop, or from several other reasons.  There is an easy way to figure out where the loop is occurring.  Turn on the profiler and run the model again well into the infinite loop.  After a while, you must manually stop the model but it should show you the block (S) where the excessive time has been spent.  The blocks with excessive times should be where the infinite loop is occurring. 

Popular Posts