So how does this work?
I usually explain it visually:
Normal PCode >>> Prog1 > Prog2 > Prog3
Flashed Object >>> Prog1 > Prog2 > Prog3
If you’re running flashed code for Prog1 and it doesn’t exist for Prog2, then the code dies. If you’re running non-flashed code for Prog1 and there is no non-flashed code for Prog2 then that code dies. Since you now know that there are different object modules and that there are different runtime engines for each module, these rules should make sense.
If you are running non-flashed, it continues to execute non-flashed code even if there is flashed code available in some other module. Again, they don’t cross, you use one or the other. Given these rules, I believe it’s possible for two different users to be running different object modules depending on the initial entry point they use, and thus there is the possibility of a problem occurring here and not there with the same program.
How do you know if your code is flashed? Use the "where" command when people are using the system. If you see a lot of ports in PX.* modes then users are running flashed code. Users with BR.* modes are in the standard BASIC Runtime. Don’t panic if there are users in both, but find out why.
Periodically the Flashed code needs to come back up (not really through the non-flashed runtime) to get access to the same VME services that are used by PCode and everything else. It’s in part the D3 reliance on these services that keeps the VME from going away. Knowing which services are required from the VME can help to make flashed code more performant because it means you stay in the optimized mode for more cycles. Check the D3 Ref manual, look for "FlashBASIC Features that Function Differently in D3NT vs. UNIX".
You can be sure that all User Exits leave flashed space and execute in the VME – thus giving you a performance hit. So rather than parsing the output from CONV(”,’50bb’) because it looks mysterious, use @PIB, @ACCOUNT and @USER. Better yet, you know a user’s port is never going to change on you in a given session, so assign PORT=@PIB, DATE=DATE(), and others at the top of your first entry point into the application and carry the variables around with you in named common so that you don’t have to call out to a function every time you need this static data.
Identifying other functions that aren’t processed by the flashed modules is not as easy as saying OCONV() goes to the VME, for example, because there are some functions like numeric and date masking that can be done by flashed code, while others that must be done by the VME. As you can see just by this example, there are sometimes two sets of code, like the flashed data masking and the non-flashed data masking, so it’s reasonable that there could be issues in one and not the other. In some cases you must flash the code, for example with %functions. In other cases you cannot flash the code – for example, I don’t think the ‘file’ statement is supported yet.
You also need to come back up from Flashed object into the VME to do terminal IO. So rather than doing this:
It’s better to do a single:
…even if that line gets very long and ugly (one of the benefits of flashed code is better string handling). Right after sending output to the screen we usually pause for user response. So someone might be tempted to wonder why we care about saving time slices in a screen print if we’re just going to come to a halt anyway. But the sooner one user relinquishes their slice, the sooner someone else gets a turn, and that results in the perception of improved speed.
For better performance with terminal IO, you can Flash-compile terminal definitions so that flashed object can execute compatible flashed terminal IO functions. This results in much faster screen painting (says 10x to 20x in the docs). To do this, select your favorite term-type, and use the term statement as follows:
term vt100 (co
So, should you flash or not? The answer depends on knowing if your code contains statements that will not run in flashed mode, and the easiest way to find out is to just recompile everything. That can be done using this command:
compile filename * (ow
The ‘o’ option tells the compiler to generate flashed object. The ‘w’ option tells the compiler to not generate non-flashed pcodes. Flashed object is not generated from source code, it’s generated from the pcode after a non-flashed compilation has been done. So when you compile with the ‘o’ option it recompiles from source to pcode object and then does a separate step to compile from pcode to flash. The ‘w’ option simply tells the compiler to skip the first part, the object is already there, just (re)generate the flashed module and append it to the end of the existing non-flashed module.
What if you don’t want to run flashed object but all of your programs are flashed? You can control this at the entry point to all programs. Most applications have a login proc that executes a menu program. This is done with something like run bp menu or just menu. If you recompile the menu program without the flash option (o) then it will not have a flashed module and all programs called from there will be non-flashed. Or… catalog entries in the master dictionary begin with the letters ‘VR’. If you ed md menu and change atb1 to ‘VR1’, then anything that calls the menu will only execute the non-flashed module, and anything called from menu will only be using their non-flashed module. There is currently no way to turn off flash for an account or system. You must do it as described here.
Want better performance from FlashBASIC?
I’m not sure how this is handled in NT but in *nix platforms you can modify the ‘pick0’ configuration record, where you will find a line that says ‘basic 4096’ or similar. When D3 is booted this tells the system how much memory gets allocated just for FlashBASIC modules. The D3 shpstat command allows you to see the Flashed modules in memory and you can see immediately if there is not enough memory allocated. In *nix systems (not Windows) you can also compile programs with the (k) option, like (owk) which tells D3 to leave the object code in memory when users are done with it. This core-locking feature is nice because it eliminates the overhead for the system in reading object code from disk for different users at different times of the day. You probably don’t want to core-lock everything – keep an eye on shpstat when you make changes like this.
Well, there ya have it. We covered a lot more than just FlashBASIC, that was a short tour around the whole system. I don’t think anyone needs more information to make good use of FlashBASIC. You should have a better idea of how this stuff works underneath. You should understand (though perhaps not forgive) why Flashed code and non-Flash work differently. You should understand now why different patches are available for *nix for the D3 abs (with the compiler and NF runtime), FlashBASIC (like Linux.7.5.1.F6 or whatever), and the monitor (AIX.7.2.4.M2 etc). And best of all I hope you find yourself better able to decide whether you want to use flashed code, whether you can, and how you can get more out of it when you do.
If I get more info about how this works in NT I’ll post another note.