D
Dave
Hello all,
I have written an expression interpreter, and a profiler has told me that a
specific part of it is in need of optimization. My purpose in posting to
this newsgroup is to solicit suggestions on how I might accomplish my
intended aim more efficiently.
My interpreter supports the "if-then-else" construct. In addition, it
supports variables, which means it has a symbol table. As you probably
suspect, the symbol table is implemented using std::map<std::string,
var_value_t>.
Currently, the processing of an if-then-else proceeds as follows:
1. Save the original symbol table state; say the returned handle to the
saved state is 1
2. Parse the boolean condition and store the result in rval (note that it is
not possible for the symbol table to be altered here; I do not allow
assignment in the condition of an if-then-else)
3. Parse the "then" subexpression
4. Save the "then" symbol table state; say the returned handle to the saved
state is 2
5. Restore symbol table state 1
6. Parse the "else" subexpression
7. Save the "else" symbol table state; say the returned handle to the saved
state is 3
8. If rval is true, restore symbol table state 2, else restore symbol table
state 3
The following serves as an example expression to which this processing could
be applied (assume 'a' is an integer initialized to 0):
if true then a := 6 else a := 7
Note that the "then" and "else" subexpressions can be arbitrarily complex;
they might even be another if-then-else. And so on recursively... This
fact eliminates some potential shortcuts.
What needs to be optimized is the saving and restoring of the symbol table
states. Currently, states are saved in a std::vector<>. When state is
requested to be saved, I just push_back() the whole symbol table and return
the index as the "handle" to the saved state. When the restoration of a
state is requested, I just index the std::vector<> with the passed handle
(index) and copy back the symbol table at that index. All of this copying
of std::map<> is taking a big toll performance-wise.
I have already tried adding an undo / redo feature that allows me to operate
only upon the actual symbol table itself. Unfortunately, I quickly
discovered that this is not robust enough. State is not properly
maintained. A careful run through of the example expression above
demonstrates this.
Can anybody suggest something more efficient than my current implementation?
It is a requirement that whatever I implement remain within the realm of
standard C++.
Thank you,
Dave
I have written an expression interpreter, and a profiler has told me that a
specific part of it is in need of optimization. My purpose in posting to
this newsgroup is to solicit suggestions on how I might accomplish my
intended aim more efficiently.
My interpreter supports the "if-then-else" construct. In addition, it
supports variables, which means it has a symbol table. As you probably
suspect, the symbol table is implemented using std::map<std::string,
var_value_t>.
Currently, the processing of an if-then-else proceeds as follows:
1. Save the original symbol table state; say the returned handle to the
saved state is 1
2. Parse the boolean condition and store the result in rval (note that it is
not possible for the symbol table to be altered here; I do not allow
assignment in the condition of an if-then-else)
3. Parse the "then" subexpression
4. Save the "then" symbol table state; say the returned handle to the saved
state is 2
5. Restore symbol table state 1
6. Parse the "else" subexpression
7. Save the "else" symbol table state; say the returned handle to the saved
state is 3
8. If rval is true, restore symbol table state 2, else restore symbol table
state 3
The following serves as an example expression to which this processing could
be applied (assume 'a' is an integer initialized to 0):
if true then a := 6 else a := 7
Note that the "then" and "else" subexpressions can be arbitrarily complex;
they might even be another if-then-else. And so on recursively... This
fact eliminates some potential shortcuts.
What needs to be optimized is the saving and restoring of the symbol table
states. Currently, states are saved in a std::vector<>. When state is
requested to be saved, I just push_back() the whole symbol table and return
the index as the "handle" to the saved state. When the restoration of a
state is requested, I just index the std::vector<> with the passed handle
(index) and copy back the symbol table at that index. All of this copying
of std::map<> is taking a big toll performance-wise.
I have already tried adding an undo / redo feature that allows me to operate
only upon the actual symbol table itself. Unfortunately, I quickly
discovered that this is not robust enough. State is not properly
maintained. A careful run through of the example expression above
demonstrates this.
Can anybody suggest something more efficient than my current implementation?
It is a requirement that whatever I implement remain within the realm of
standard C++.
Thank you,
Dave