Sign in to follow this  
Followers 0
Jon

Variable / Function Limits Removed

7 posts in this topic

I've removed the limits on the number of user functions and user variables.

The user functions are now just stored in a big linked list. I may change this for a sorted list for quick binary-chop searching but for now I just want to make sure it works :huh2:

The variable table was rewritten using some ideas and code that Nutster sent. Basically a class is used that simply stores a list of named variables (in a linked list). This is used as-is for global variables. (m_Globals )

For local variables a stack of these "named variables" is used (m_Locals). Every time the scope increases a new stack entry is created so each function(or scope) has it's own private set of variables. When the function exits the stack is simply "popped".

David's code was originally a binary-tree structure (unused\btree_variant.cpp) that was very cool and baffling, but a binary tree is optimized for large amounts of data - the reason it was reimplemented as a linked list was because of the logic that most functions only use a handful of variables (David said the binary tree benefits only seemed to kick in at around 50 local variables).

I had a further idea to "cache" the last 8 or so variables accessed in the list to speed up access to frequently used items when large lists are used, but I'm sure David will do some more testing when he gets time to see if the list or the tree is the best structure for AutoIt. It is fairly easy to readd david's code (btree_variant and stack_btree) as the format for the variabletable is pretty much identical - just change the m_Globals and m_Locals declarations.

It's a major change so I need lots of testing on the variables, especially scoping and byref stuff to make sure that things still work :D

Also, I would like the devs to take a look at these rewritten and new files to make sure that I've not created any memory leaks:

- variabletable.cpp

- variable_list.cpp

- stack_variable_list.cpp

http://www.hiddensoft.com/autoit3/files/unstable/autoit/

Thanks,

J

Share this post


Link to post
Share on other sites



nonreg ok from my point of view.

Just a remark with Include the var number goes much above 50.

on my tiny perf comparison that's the dif against 101

Perf improvement 3.0.101.0 -> 3.0.102.20 (2004\04\27 00:26)

For=-0.53% Do=-2.61% While=-4.95% Include=2.39%

:D

Share this post


Link to post
Share on other sites

David's code was originally a binary-tree structure (unused\btree_variant.cpp) that was very cool and baffling, but a binary tree is optimized for large amounts of data - the reason it was reimplemented as a linked list was because of the logic that most functions only use a handful of variables (David said the binary tree benefits only seemed to kick in at around 50 local variables). 

You think that was baffling? I didn't even give you the code to remove a node from the binary tree. Duck and cover! Now that is baffling! :D

David Nuttall
Nuttall Computer Consulting

An Aquarius born during the Age of Aquarius

AutoIt allows me to re-invent the wheel so much faster.

I'm off to write a wizard, a wonderful wizard of odd...

Share this post


Link to post
Share on other sites

I know the feeling. It looks good so far, but you turned all my constructor initializers into assignments inside the function. ;( What about smaller, faster and less redundent code do you not like?

I will see if I can do the timing tests this weekend.


David Nuttall
Nuttall Computer Consulting

An Aquarius born during the Age of Aquarius

AutoIt allows me to re-invent the wheel so much faster.

I'm off to write a wizard, a wonderful wizard of odd...

Share this post


Link to post
Share on other sites

Constructor initializers save time, memory and reduncy in execution. Compare:

class Test1
{
private:
     AString m_name;
     double *m_list;
     unsigned int m_size;

public:
     Test1(void):  m_name(""), m_list(NULL), m_size(0) { }
     Test1(AString name):  m_name(name), m_list(NULL), m_size(0) { }
     Test1(int size):  m_name(""), m_size(size)
     {
          m_list = new double[size];  // assume new will work.
     }
};

with

class Test1
{
private:
     AString m_name;
     double *m_list;
     unsigned int m_size;

public:
     Test1(void)
     {
          m_name = "";
          m_list = NULL;
          m_size = 0;
     }

     Test1(AString name)
     {
          m_name = name;
          m_list = NULL;
          m_size = 0;
     }

     Test1(int size)
     {
          m_name = "";
          m_size = size;
          m_list = new double[size];  // assume it will work.
     }
};

When an object is created, its constuctor is called to initialize the data members. If an initializer list given, then the data members are initialized with the given values. If the list is not given, then the data members are created using their default rules. This means that objects used in the class, such as AString in my example, are created using their void constuctors.

By using the void constructor and then doing the assignment later on, you end up doing twice the work (almost). Even for primitive data members, such as int and double, the initializer is a little more efficent over assigning inside the constructor as the data member does not need to be found again, but is known at the time of object creation.

When creating an initializer list, I generally put the list in the order the data members appear in the class definition. Also, I do not refer to one data member in the initializer of another. If you use a function call with-in the initializer list, it must be a global function, a function in an existing object or a static member function. By the time execution is inside the constuctor, the data members exist and non-static member functions can be called.

As for code size, the code for calling the void constructor is inserted as well as the code for the assignment, if an initializer list is not given. If the list is given, then the appropriate constructor is called and there is no need for an extra assignment. The optimizer may even be able to remove the unused function from the linker package. I could see the executable being somewhat smaller and faster by just changing the constuctors to use initializer lists as appropriate.


David Nuttall
Nuttall Computer Consulting

An Aquarius born during the Age of Aquarius

AutoIt allows me to re-invent the wheel so much faster.

I'm off to write a wizard, a wonderful wizard of odd...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0