Jump to content
Rocketrolf

What is faster? .hpp or sqf

Recommended Posts

He was hilarious and spot on!

Anywho, SQF is your best bet for scripting. If you're feeling edgy, you can try out Noubernou's Intercept and do everything in C++...

 

a scripting language for a scripting language?

Share this post


Link to post
Share on other sites

a scripting language for a scripting language?

 

for a scripting language for a scripting language for a scripting language for a scripting language for a scripting language?

 

GKU9MQf.gif

 

eat the chip

  • Like 3

Share this post


Link to post
Share on other sites

This thread is going nowhere, here's a bit of info for you.

 

It is not the extension tag that is important as to how fast a script runs or how it behaves, it is from where and how it is called that defines this.

 

You can use any extension you want for a file that is run preprocessed, eg from an addon config or Description.ext as an #Include file.

You can call it MyFile.h,  Myfile.hpp,  Myfile.xyz anything you want,. Because you are running that code via an "#Include" statement from a config file regardless of the extension name, it will still only run once, will run linear, will run before the mission.sqm is even started, can only accept syntax and commands that are specifically for config/description.ext and cannot define variables that can then be used in scripts. It is a completely different environment to a file called to run via a "call", "spawn" or "execVM"

 

For that reason there is no comparison to be made between it and a script/,sqf. They run in different environments and are used for entirely different content/data

 

 

You can also execVM a file with a .hpp extension, or rename that file with an .sqf extension, it will behave exactly the same as you would expect from any file run in ther ExecVM/Spawn/Call environment and will only accept commands that are legal in that environment.

You could probably use any extension you wanted (Although I havent tried) in this environment too

 

 

 

So we have 2 environments for coding in

 

Config: Root from config.bin or config.cpp or description.ext and all files that it runs are called to run from an "#Included" command, can be any extension you want to use.

 

Scripting: Root from Init.sqf, cfgfunctions preinit, Init field of an editor object, event script and are called to run by either "ExecVM", "Spawn" or "Call" commands,

 

 

When folks talk about optimising their code, they are typically referring to the code in the scripting environment, not the config environment. 

 

 

Some explanation first before we discuss optimisation

To simplify things (And i do mean simplify because this gets very in depth and complicated) please accept the following definitions as the two types of code in the scripting environment and the further explanations to help you grasp an understanding

Functions: These are Scripts preprocessed (Compiled) and stored in ram,

Scripts: These are not preprocessed and are not stored in ram

 

When you "call or "spawn" a function, that function has already been processed so it just "runs"

When you execVM a "script", it is first compiled then it is run. It does this every time you want to use it

 

So to look at this in practical terms and compare what is actually going on, lets say we have a server-side script that re-equips 50 players with gear at some point in mid mission

 

Function: Compiled once before the mission has even started , run 50 times

ExecVM: Compiled 50 times, run 50 times

 

So what you can take from this is. (Golden rule Number 1)

 

 

Here are the golden rules for optimisation.

(Golden Rule 1) If a script is required to run more than once ALWAYS store it in ram as a function.

The best way to do this is to define that function in your Cfgfunctions preinit code which is done pre mission start

Example

MyVariable = compile preprocesfilelineumbers "Pathtoscript\script.sqf";

 

Then when you want to run that code you would use the syntax

[] call MyVariable;

 

Take note, if that function has any "sleep" or "waituntil" commands, you cannot use "Call" you need to use

[] spawn MyVariable;

 

 

(Golden Rule 2) 3 Millisecond rule (Keep scripts/functions short where possible and do not spawn too many threads)

On every (Server  - cycle) , (client - frame) the engine will attempt to run all code in all scripts/functions in a particular threadbut it wont try to run the entire code in every script/function in that thread if the code is lengthy.

It is limited to run  a single instance of code for no more than 3 milliseconds. If the instance of code is going to need longer than that to complete, it will halt that piece of code and then return on the next frame/cycle to try and finish running that code.

This does not mean the code in a script has to take less than 3ms to fully run but what it does mean, is keep your code short and to the point and the timing sensible. For example, if you have a looping script that runs a hint command every frame, although the information contained in the hint will very quickly get updated, is it sensible and appropriate that the player gets that update 30 to 50 times a second, or is it good enough for the player to receive the updated information every 5 seconds?

For functions, these will not allow anything else to run in that thread until the function has completed, so keep these very short and to the point. 

If you call a function from within a function, this is inerpreted as 1 big function, not 2 functions.

So for example MyScript.sqf calls function 1, which in turn calls function 2,

The code is run in the following order

 

ExecVM "Myscript.sqf"

Myscript starts

..... [] call Function1

..... Function 1 starts

.......... [] call function 2

.......... Function 2 starts

.......... Function 2 ends

..... function 1 ends

Myscript ends

 

these posts/blogs explains it better

 

 

Final point is open to discussion

 

If a script is only going to be run once, is it better to precompile it and store it in ram at pre init or just compile and run it the one time is is needed via an execVM or spawn command.

 

Well in my opinion, anything that can be done pre mission start is better than doing it post mission, so for pure performance it is likely better to precompile during pre init and spawn or call when required.

However that really depends on how many threads you have running and for that just 1 instance of that 1 code does it make much of a difference, I don't really know but there are plenty of debugging commands you can use to test this with and test how long your code takes to run.....

 

Your end aim is to keep the client FPS and server cps as high as possible.

  • Client FPS ideally needs to be 30 +
  • Server cps needs to be (If running AI at least 20 to see little if any degradation of AI processing when the maximum number of players the mission supports are connected to the server) 

The following also has a negative effect on performance (Some client, some server, some both)

  1. The more AI you have
  2. The more editor objects that do not have "Enablesimulation False" defined for them (Although even when they do have it defined, it still effects performance but not anywhere near to the same extent)
  3. The more players you have connected to the server
  4. The greater the view distance
  5. The more detailed the terrain grid is set for
  6. The more triggers and scripts you have running
  7. Extreme environments (High waves, rain/storm etc
  8. The higher the maximum ping you have set on the server
  9. The lower the clients and/or servers processing power
  10. The more restricted the bandwidth

 

 

I hope this explains it in easily understandable terms and if there is anything incorrect in there, let me know so i can edit it.

  • Like 13

Share this post


Link to post
Share on other sites

The only thing I used the C++ configs for was quickly enabling and disabling third party scripts that made changes to the config, scripts that make use of RscTitles, CfgSounds, CfgRadio, and CfgFunctions in particular. I copied the technique from the MSO missions. It was basically using ifdef, ifndef, define and include to switch stuff on and off cleanly for both config side (description.ext) and in script side (init.sqf). It is basically a framework for making lots of different script mods play nice with each other by refactoring them into isolated modules that can be enabled and configured through the mission params. The only use case it never covered was stringtable.xml manipulation, always had to just merge manually all the strings from the third party script mods that had them, never figured out a way to do it cleaner.

Share this post


Link to post
Share on other sites

Example from a mission:

 

[...]

class GroupCfg 
{
  class groupA 
  {
    name = "Alpha";
    side = "blufor";
    unitnames[] = {{"James", 0}, {"Kerry", 1}};
  }
};

[...]

(this was included in the description.ext)

Access values with getArray(missionConfigFile >> "GroupCfg" >> groupA >> "unitnames"...

 

Why not use sqf with an array for that?
That was the origin of my question.

 

Thank you terox for that answer! It solves some of my problems.

Share this post


Link to post
Share on other sites

I've done some testing into using the mission config to store predefined data, but found all the config calls made actually returning the data about 50% slower than just using a global variable.

Share this post


Link to post
Share on other sites

I'd agree with you there ceeeb.

However where there are pro's there are also cons.

 

For some issues a series of config classes, with attributes can be easier on the eye for say a "Settings" script than an array in a .sqf

 

Take a look at the 2 following examples and then put yourself in the shoes of a newcomer to mission editing and attempting to work with a "Settings" file in a mission template and editing it to your requirements.

 

The following snippets in the example are for defining values used in

1) Setting up groups, defining their callsigns

2)  defining their group icons, colour, size type etc

 

As you will see the Config version is much easier to understand for someone who is unfamiliar with the code and even someone who is would often have to stop and thing "What was that 5th element in the array for ?" !

 

DESCRIPTION.EXT version

class 1stPlt_HQ
{
    Grp_ID  = "WHQ"; // WHQ=group this; (Mission editor Init field entry of each unit in group)
    Grp_Type = "HQ"; //
    Grp_Size = "PLATOON"; //
    Callsign = "HQ";
    m_Text = "HQ";
    m_size = 0.6;
    m_colour = "BLUE"; // {R,G,B,A};
};
 
 
class 1stPlt_XO
{
    Grp_ID  = "WXO"; // WXO=group this; (Mission editor Init field entry of each unit in group)
    Grp_Type = "HQ";
    Grp_Size = "PLATOON";
    Callsign = "XO";
    m_Text = "XO";
    m_size = 0.6;
    m_colour = "BLUE";
 
};
 
class 1stPlt_RECON
{
    Grp_ID  = "WRECON"; // WRECON=group this; (Mission editor Init field entry of each unit in group)
    Grp_Type = "RECON";
    Grp_Size = "FIRETEAM";
    Callsign = "Recon";
    m_Text = "R";
    m_size = 0.6;
    m_colour = "BLUE";
};
 
class 1stPlt_ALPHASqd
{
    Grp_ID  = "WA"; // WA=group this; (Mission editor Init field entry of each unit in group)
    Grp_Type = "INFANTRY";
    Grp_Size = "SQUAD";
    Callsign = "Alpha";
    m_Text = "A";
    m_size = 0.6;
    m_colour = "BLUE";
};

 

Script.sqf version

_hq =
[
          "WHQ", // WHQ=group this; (Mission editor Init field entry of each unit in group)
          "HQ",
          "PLATOON",
          "HQ",
          "HQ",
          0.6,
          "BLUE"
];
 
_XO=
[
          "WXO",
          "HQ",
          "PLATOON",
          "XO",
          "XO",
          0.6,
         "BLUE"
];
 
_recon =
[
          "WRECON", // WRECON=group this; (Mission editor Init field entry of each unit in group)
          "RECON",
          "FIRETEAM",
          "Recon",
          "R",
          0.6,
          "BLUE"
];
 
_alpha =
[
          "WA", // WA=group this; (Mission editor Init field entry of each unit in group)
          "INFANTRY",
          "SQUAD",
          "Alpha",
          "A",
          0.6,
          "BLUE"
];

 

What can you take from this.....

Well

Everything is a balance, you have to take into consideration such elements as

 

  1. Who needs to understand this code ? (Answer somebody editing a mission therefore it needs to be easily understood)
  2. When does it need to run ? (Answer at pre init in preparation for more scripts that run at some point between mission.sqm and time = 0
  3. Does it have to be super fast and optimised ? (Answer, no not really, its all done pre init but its config anyway)
  4. How often does it need to be run ? (Answer: once on each client)

and many other things.

 

This then defines how the code is written, where and how it is actioned etc.

  • Like 2

Share this post


Link to post
Share on other sites

Access to the data seems like it wouldn't be the same in those examples though.

 

For example to grab the type of alpha group you can access the information via:

_alphaType = _alpha select 1; // Group type - Infantry.

For the config it would be something like this right? 

_alphaType = ["ClassSettingsOrSomething","1stPlt_ALPHASqd","Grp_Type"] call BIS_fnc_getCfgData;  // Group type - Infantry.

While visually reading the config seems easier, accessing the data seems more convoluted unless I'm doing it totally wrong. :)

Share this post


Link to post
Share on other sites

I've done some testing into using the mission config to store predefined data, but found all the config calls made actually returning the data about 50% slower than just using a global variable.

 

The getX commands are resource hogs. getarray, gettext, getnumber, etc

Share this post


Link to post
Share on other sites

terox Is correct if you look inside the functions_f.pbo you'll find in the initFunctions.sqf how arma 3 pulls this off Bohemia added in there their own parsing syntax through the description.ext.
Actually very interesting inside that file, I glossed over it once. Bohemia actually use their own way to parse the files.
It also shows how the cfgFunctions is retrived from the ext file.

 

The getX commands are resource hogs. getarray, gettext, getnumber, etc

 

Test it see if it is. Make a config file to parse and add another that is a .sqf file with arrays. See which one is the fastest.

 

I might do it too I am interested in 20 array elements in sqf vs hpp

 

And accessing elements on a config is very simple your description.ext is your "root class"
Inside that you add an #include "Configs Location"

so it becomes for example in scripts

Inside the description.ext

 

Is the "super class" that then goes down inside subclasses such as you define e.g

inside the cfgFunctions.hpp

class CfgFunctions{	class mySubOrdering < -- SubClass	{		class myFunctionsSubClass < -- subClass 		{                        myNumber = 5; 			tag = "myTag"; //Custom tag name			requiredAddons[] = {"A3_Data_F"}; //Optional requirements of CfgPatches classes. When some addons are missing, functions won't be compiled.		};	};};

CfgFunctions is the superclass
Accessing the classes like so.

myTagsString = getText(MissionconfigFile >> "cfgFunctions" >> "mySubOrdering" >> "MyFunctionsSubClass" >> "myTag" >> "tag") <-- This will get the string stored in the tag variable
MyTagsArray = getArray (MissionconfigFile >> "cfgFunctions" >> "mySubOrdering" >> "MyFunctionsSubClass" >> "requiredAddons") <--- This will get an array entry defined by the config
myTagsNumber getnumber (MissionconfigFile >> "cfgFunctions" >> "mySubOrdering" >> "MyFunctionsSubClass" >> "myNumber") <--- Retrive a number from this entry (just for example this doesn't work in cfgFunctions.hpp with out erroring.

Make sense? Oops I apologise MissionConfigFile FOR NON ADDON files.

And you make available to the description.ext via #include "scripts/MyFunctions.hpp"

Technically you could make any kind of config and append it into the #include which I've seen people do in some instances.

 

 

As an additional piece of information about Torex said, the issue with spawn'ing and calling. Calls will blockade ALL other execution whether it is used in scheduled or unscheduled environment. Personal experience here I had a function being used in a HUD, didn't realise the call in a while {true} do {} would never end (*facedesk*) So my HUD wasn't updating.
It HAD to be spawn'd. To prevent server locks etc. Inside a spawn and you need the result to be complete and finished use

 

WaitUntil {scriptDone "scriptshandle";}; This way it prevents another script being run before this one completes IF it completes.

 

Results are in test 1:
154 Element Array for config completed in 0 ms 1/10000 cycles (.hpp file)

154 Element Array for non-config complete in 1 ms 1/10000 cycles (.sqf file)

Results are in test 2:
308 Element Array for config complete in 0 ms 1/10000 cycles (.hpp file)
308 Element Array for non-config complete in 1 ms 1/10000 cycles (.sqf file)

 

Result are in test 3 (Worse case)
616 Element Array for config complete in 0 ms 1/10000 cycles (.hpp file)

616 Element Array for non-config complete in 1 ms 1/10000 (.sqf file)

 

I think we've definitively proven that .hpp is faster. Hmmm.
Wonder if I can use getText to store code. and execute it O_o (Nope worth a try though)

 

Configs win.

Share this post


Link to post
Share on other sites

 

Results are in test 1:

154 Element Array for config completed in 0 ms 1/10000 cycles (.hpp file)

154 Element Array for non-config complete in 1 ms 1/10000 cycles (.sqf file)

Results are in test 2:

308 Element Array for config complete in 0 ms 1/10000 cycles (.hpp file)

308 Element Array for non-config complete in 1 ms 1/10000 cycles (.sqf file)

 

Result are in test 3 (Worse case)

616 Element Array for config complete in 0 ms 1/10000 cycles (.hpp file)

616 Element Array for non-config complete in 1 ms 1/10000 (.sqf file)

 

I think we've definitively proven that .hpp is faster. Hmmm.

Wonder if I can use getText to store code. and execute it O_o (Nope worth a try though)

 

Configs win.

 

0ms ????????? Only 1/10000 cycles complete??????? Are you sure?

 

Code performance button doesn't work in MP editor

 

Now try again in the SP editor, not MP.

 

That or your code is somehow broken and does not run.

Share this post


Link to post
Share on other sites

The misinformation is this thread is real. The premise of this thread alone leaves no room for factual discussion, it's like asking, "What's faster? A Ferrari or a typewriter?"

Want "faster" code? Reduce the complexity of the algorithm and structure the data to fit the scenario. A slow algorithm is still going to be slow; there's no magic bullet. SQF code is still going to be interpreted, regardless of where you put it. Loading your code into memory will cut-out file IO -- doing this sooner or later has a negligible difference in a practical scenario.

Share this post


Link to post
Share on other sites

0ms ????????? Only 1/10000 cycles complete??????? Are you sure?

 

Code performance button doesn't work in MP editor

 

Now try again in the SP editor, not MP.

 

That or your code is somehow broken and does not run.

Again:

616 config element array of string values completed in 0.068 m/s 10000/10000 cycles (retrived using configFile >> "")

616 non-config element array of string values completed in 0.211551 m/s 4727/10000 cycles. (executed through execVM) (ExecVM sucks....)

616 non-config element array of string values executed using pre-compiled code completed in 0.0925 m/s (executed using call)

616 non-config element array of string values executed using pre-compiled code completed in 0.0025 m/s (executed using spawn) had to do [] spawn { [] spawn my_BindFunc};

 

So it looks like spawn wins.

 

Share this post


Link to post
Share on other sites

Again:

616 config element array of string values completed in 0.068 m/s 10000/10000 cycles (retrived using configFile >> "")

616 non-config element array of string values completed in 0.211551 m/s 4727/10000 cycles. (executed through execVM) (ExecVM sucks....)

616 non-config element array of string values executed using pre-compiled code completed in 0.0925 m/s (executed using call)

616 non-config element array of string values executed using pre-compiled code completed in 0.0025 m/s (executed using spawn) had to do [] spawn { [] spawn my_BindFunc};

 

So it looks like spawn wins.

Have you got code examples to prove you are not insane?

  • Like 2

Share this post


Link to post
Share on other sites

I myself find that COBOL is very good at handling these sorts of functions. I have also recently been learning the ancient art of RPG and would love to help you write a mission in OS/400 with the QSQFLE syntax parser

  • Like 1

Share this post


Link to post
Share on other sites

configFile used:

class SuperClass {
    
    class parentClass
            {
                
                class childClass
                {
                arrayText[] = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n"}; <--- repeated 44 times down the page (Forums won't let me post it)
    
        };
    };
};

myArray = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n"]; <-- repeated 44 times down the page 616

was run with call by My_func = compile PreProcessFileLineNumbers "thearrayfile.sqf"; was called using [] call My_func; produced the numbers above.

config was retrived using the following myArray = getArray(MissionConfigFile >> "SuperClass" >> "parentClass" >> "childClass" >> "arrayText")

My_func was also run by Local execution using [] spawn { [] spawn My_fnc; }; to produce the below results.

 

New results are in.

Config file: 0.0695 ms

Non-config (call) 0.0891 ms

Non-config ([] spawn { [] spawn myFunc; } 0.0025 ms

Edited by MarkCode82

Share this post


Link to post
Share on other sites
configFile used:

class SuperClass {
    
    class parentClass
            {
                
                class childClass
                {
                arrayText[] = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n"}; <--- repeated 44 times down the page (Forums won't let me post it)
    
        };
    };
};

myArray = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n"]; <-- repeated 44 times down the page 616
was run with call by My_func = compile PreProcessFileLineNumbers "thearrayfile.sqf"; was called using [] call My_func; produced the numbers above.

config was retrived using the following myArray = getArray(MissionConfigFile >> "SuperClass" >> "parentClass" >> "childClass" >> "arrayText")

My_func was also run by Local execution using [] spawn { [] spawn My_fnc; }; to produce the below results.

 

New results are in.

Config file: 0.0695 ms

Non-config (call) 0.0891 ms

Non-config ([] spawn { [] spawn myFunc; } 0.0025 ms

From all 4 experiments (why you didnt show how you measured execVM?????) only config retrieval is valid. You said you were measuring it against precompiled array, when infact you were measuring it against compiling of a file. And as for spawn, it seems you have absolutely no idea how this works and why you cannot measure it this way.

TLDR - Don't, just don't, ok?

  • Like 1

Share this post


Link to post
Share on other sites

From all 4 experiments (why you didnt show how you measured execVM?????) only config retrieval is valid. You said you were measuring it against precompiled array, when infact you were measuring it against compiling of a file. And as for spawn, it seems you have absolutely no idea how this works and why you cannot measure it this way.

TLDR - Don't, just don't, ok?

THANK YOU!

Share this post


Link to post
Share on other sites
From all 4 experiments (why you didnt show how you measured execVM?????) only config retrieval is valid. You said you were measuring it against precompiled array, when infact you were measuring it against compiling of a file. And as for spawn, it seems you have absolutely no idea how this works and why you cannot measure it this way.

TLDR - Don't, just don't, ok?

 

 

Show us how it's done then? Instead of openly ridiculing me.

And did you just nitpick because I executed a single file with a single array?

 

[] spawn executes code into the Virtual Machine thread and does not wait for the result. You say you cannot use it to measure this way?

Why or why can you not? I am not going to roll over for the status quo. Give me the reason why you can't? If I am correct if I was to just copy and paste that array directly into the debug console then executed it should produce a pretty similiar result. Possibly faster.

 

 

Direct execution in debug: 616 element array 0.0888 ms

Config file: 0.0695 ms

Non-config (call) 0.0891 ms

Non-config ([] spawn { [] spawn myFunc; } 0.0025 ms

Non-config [] execVM: 0.41876 ms

 

Satisfied now?

Share this post


Link to post
Share on other sites

Show us how it's done then? Instead of openly ridiculing me.

And did you just nitpick because I executed a single file with a single array?

ExecVM was aweful more than 2.00 m/s not even worth mentioning.

 

[] spawn executes code into the Virtual Machine thread and does not wait for the result. You say you cannot use it to measure this way?

Why or why can you not? I am not going to roll over for the status quo. Give me the reason why you can't? If I am correct if I was to just copy and paste that array directly into the debug console then executed it should produce a pretty similiar result. Possibly faster.

 

With spawn, it is executed concurrently, and therefore does not yield a result. The time you're getting for execVM and spawn is the return time (pretty much immediately). You have to measure what is actually being performed in the separate threads (if they truly even are in a separate thread).

Share this post


Link to post
Share on other sites

I'm guessing it's the doubled spawn thing?  So that all codeperformance was checking for was "How quickly did I execute the spawn command?" not "how quickly did the code my nested spawn executed complete?"  Am I right? :)

  • Like 1

Share this post


Link to post
Share on other sites

Yet when spawn is executed because the variable is global it immediately becomes available. Accessible.

So technically you can make it yield a result by giving the variable a global scope correct?

Because basically thats all a call really does is change scope from 1 script to another if it's a function and not a proceedure.

With a return statement at the buttom then you can change it's scope to either global or local in the next script.

 

Which is nearly the same as the way functions are actually defined using .hpp functions-as-files they're defined into the global scope.

And to get a true gauge.

0.0021 ms with a WaitUntil {scriptDone _thisScript;}; Inside the script.

0.0020 ms with a if (scriptDone _thiScript) exitWith {}; To ensure complete script termination.

0.0614 ms with a decrease in search depth to a single class (MissionConfigFile >> "SuperClass" >> "arrayText")

0.0695 ms with a search depth of: (MissionConfigFile >> "SuperClass" >> "parentClass" >> "childClass" >> "arrayText")

SQF (call) 0.0891 ms
SQF ([] spawn { [] spawn myFunc; } 0.0025 ms

SQF [] execVM: 0.41876 ms (Rubbish execVM sucks) (spawn compile PreProcessFileLineNumbers at the same time)

 

The waitUntil and if(scriptDone _thisScript) should eliminate your result yielding issue instead has to wait for a "true" condition on the script to terminate. Which is

as good as returning True.

 

Results are still pretty much the same. The additional search depths of the configs is probably what causes the computation time to lengthen.

Share this post


Link to post
Share on other sites

Interesting experiment, even if this is all valid, how practical would it be to do all this in the name of <1ms gains? I imagine maintainability would also suffer as well. Not arguing, just bringing up some questions.

Us sneaky programmers are always trying to shed off those pesky milliseconds xD

 

 

I'm guessing it's the doubled spawn thing?  So that all codeperformance was checking for was "How quickly did I execute the spawn command?" not "how quickly did the code my nested spawn executed complete?"  Am I right?  :)

 
That's right.

Share this post


Link to post
Share on other sites

Yes maintainability would suffer. I would have just done the [] spawn FuncBind in single player but I can't it doesn't show the GUI or the result.

Probably because Local Execute is non-scheduled so I had to make it scheduled.

Share this post


Link to post
Share on other sites

I'm guessing it's the doubled spawn thing?  So that all codeperformance was checking for was "How quickly did I execute the spawn command?" not "how quickly did the code my nested spawn executed complete?"  Am I right? :)

Correct, the simple concept someone here fails to understand even if his life depended on it.

  • Like 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×