<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.wesnoth.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cjhopman</id>
	<title>The Battle for Wesnoth Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.wesnoth.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cjhopman"/>
	<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/Special:Contributions/Cjhopman"/>
	<updated>2026-06-01T21:19:17Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.16</generator>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Description&amp;diff=43593</id>
		<title>Description</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Description&amp;diff=43593"/>
		<updated>2011-09-01T19:25:50Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* What is Battle for Wesnoth? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Description/Translations}}&lt;br /&gt;
== What is Battle for Wesnoth? ==&lt;br /&gt;
&lt;br /&gt;
The Battle for Wesnoth is a turn-based tactical strategy game with a high fantasy theme.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;thumb tright&amp;quot;&amp;gt;&amp;lt;div&amp;gt;&lt;br /&gt;
[http://www.wesnoth.org/images/sshots/wesnoth-1.6-4.jpg http://www.wesnoth.org/images/sshots/wesnoth-1.6-4-175.jpg]&lt;br /&gt;
&amp;lt;div class=&amp;quot;thumbcaption&amp;quot;&amp;gt;Delfador's magical lightning strike&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;thumb tright&amp;quot;&amp;gt;&amp;lt;div&amp;gt;&lt;br /&gt;
[http://www.wesnoth.org/images/sshots/wesnoth-1.6-5.jpg http://www.wesnoth.org/images/sshots/wesnoth-1.6-5-175.jpg]&lt;br /&gt;
&amp;lt;div class=&amp;quot;thumbcaption&amp;quot;&amp;gt;An ambush in a campaign&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build up a great army, gradually turning raw recruits into hardened veterans. In later games, recall your toughest warriors and form a deadly host against whom none can stand! Choose units from a large pool of specialists, and hand-pick a force with the right strengths to fight well on different terrains against all manner of opposition.&lt;br /&gt;
&lt;br /&gt;
Wesnoth has many different sagas waiting to be played out.  Fight to regain the throne of Wesnoth, of which you are the legitimate heir...  step into the boots of a young officer sent to guard a not-so-sleepy frontier outpost... lead a brutal quest to unite the orcish tribes...  vanquish a horde of undead warriors unleashed by a foul necromancer, who also happens to have taken your brother hostage...  guide a band of elvish survivors in an epic quest to find a new home...  get revenge on the orcs by utilising the foul art of necromancy... &lt;br /&gt;
&lt;br /&gt;
200+ unit types.  16 races.  6 major factions.  Hundreds of years of history.  The world of Wesnoth is absolutely huge and limited only by your creativity - make your own custom units, compose your own maps, and write your own scenarios or even full-blown campaigns.  You can also challenge up to 8 friends - or strangers - and fight in epic ''multi-player'' fantasy battles.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;thumb tright&amp;quot;&amp;gt;&amp;lt;div&amp;gt;&lt;br /&gt;
[http://www.wesnoth.org/images/sshots/wesnoth-1.6-2.jpg http://www.wesnoth.org/images/sshots/wesnoth-1.6-2-175.jpg]&lt;br /&gt;
&amp;lt;div class=&amp;quot;thumbcaption&amp;quot;&amp;gt;The map editor&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Build up a formidable fighting force, starting from a single leader and a small amount of gold.&lt;br /&gt;
* Over 200 unit types in six major factions, all with distinctive abilities, weapons and spells.&lt;br /&gt;
* Experienced units gain powerful new abilities as they advance.&lt;br /&gt;
* Several multi-player options available, including internet play.&lt;br /&gt;
* Scores of different custom-designed maps, and unlimited random maps.&lt;br /&gt;
* Hundreds of campaign scenarios available for download via a simple in-game procedure.&lt;br /&gt;
* 'Fog of war' feature available for a true test of generalship.&lt;br /&gt;
* Sophisticated mark-up language lets advanced users make their own maps, factions or campaigns.&lt;br /&gt;
* Excellent language support &amp;amp;ndash; 35 different languages currently available.&lt;br /&gt;
* Windows, Mac OS X, GNU/Linux, RISC OS, BeOS, Solaris, FreeBSD, OpenBSD, NetBSD, DragonFly BSD, AmigaOS4, OS/2 &amp;amp; eComStation compatible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Play}}&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=CodingStandards&amp;diff=30431</id>
		<title>CodingStandards</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=CodingStandards&amp;diff=30431"/>
		<updated>2009-05-07T16:58:23Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: remove /* Use the function templates minimum and maximum */  as we no longer support msvc 6&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Wesnoth uses modern/advanced C++ that is portable to modern C++ compilers.&lt;br /&gt;
&lt;br /&gt;
== Formatting ==&lt;br /&gt;
&lt;br /&gt;
When working on C++ for Wesnoth, indent your code with a tab character. After fully indenting, if you still need to line up the text with a specific character on the line above, you may further align it using space characters.&lt;br /&gt;
&lt;br /&gt;
You may use long lines.&lt;br /&gt;
&lt;br /&gt;
== Evil Evil Things To Avoid ==&lt;br /&gt;
&lt;br /&gt;
=== Avoid implicit conversions ===&lt;br /&gt;
&lt;br /&gt;
Make all constructors which only take one argument that is of a different type to the class 'explicit'.&lt;br /&gt;
&lt;br /&gt;
Do not use operator T() where T is a type to allow an implicit conversion to a different type.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
t_string(const std::string&amp;amp;);&lt;br /&gt;
&lt;br /&gt;
This is very evil! It can cause many situations where a temporary t_string is implicitly created and then gets destroyed unexpectedly.&lt;br /&gt;
&lt;br /&gt;
=== Do not use non-private data members of classes ===&lt;br /&gt;
&lt;br /&gt;
It's okay to have a struct with all-public members, if that's what you want.&lt;br /&gt;
&lt;br /&gt;
However, once something is a class, with private data members, do not add public (or even protected) data members to the class. Doing this breaks encapsulation and can cause all kinds of confusing and evil things to happen.&lt;br /&gt;
&lt;br /&gt;
== Naming ==&lt;br /&gt;
&lt;br /&gt;
=== End Non-Public Members of Classes with an Underscore ===&lt;br /&gt;
&lt;br /&gt;
All non-public data members of classes should have their names terminated with an underscore, to show that they are a&lt;br /&gt;
class member. This makes for more readable code, once one is familiar with the convention.&lt;br /&gt;
&lt;br /&gt;
== Idioms ==&lt;br /&gt;
&lt;br /&gt;
=== Use References when a value may not be NULL ===&lt;br /&gt;
&lt;br /&gt;
If a value passed to a function can never be NULL, use a reference instead of a pointer. I.e.&lt;br /&gt;
&lt;br /&gt;
  void myfunction(Object&amp;amp; obj);&lt;br /&gt;
&lt;br /&gt;
rather than&lt;br /&gt;
&lt;br /&gt;
  void myfunction(Object* obj);&lt;br /&gt;
&lt;br /&gt;
This more clearly shows the user of the function that obj may never be NULL, &lt;br /&gt;
without them having to consult documentation or the implementation of the function.&lt;br /&gt;
&lt;br /&gt;
=== Use Const ===&lt;br /&gt;
&lt;br /&gt;
The 'const' feature of C++ allows interfaces to more clearly specify how they treat objects. &lt;br /&gt;
Always use const when you are not going to modify an object.&lt;br /&gt;
&lt;br /&gt;
I.e.&lt;br /&gt;
&lt;br /&gt;
  void myfunction(const Object&amp;amp; obj);&lt;br /&gt;
&lt;br /&gt;
demonstrates to the caller of myfunction() that obj will not be modified. &lt;br /&gt;
If myfunction may modify obj, then use&lt;br /&gt;
&lt;br /&gt;
  void myfunction(Object&amp;amp; obj);&lt;br /&gt;
&lt;br /&gt;
likewise, if a variable is not changed after initialization, make it const.&lt;br /&gt;
&lt;br /&gt;
=== Know the behaviour of const references when types differ ===&lt;br /&gt;
If you assign something to a const reference of a different type, if necessary (if the type is different but there is a conversion) the compiler will create a temporary and guarantee it lasts for the lifetime of the reference. So&lt;br /&gt;
&lt;br /&gt;
  char c = 0; const int&amp;amp; i = c; c = 5; &lt;br /&gt;
&lt;br /&gt;
will result in c == 5 and i == 0 which may not be what you expect.&lt;br /&gt;
&lt;br /&gt;
=== Write Exception-Safe Code ===&lt;br /&gt;
&lt;br /&gt;
Wesnoth code should be exception-safe, even if you do not use exceptions directly. &lt;br /&gt;
That is, you should be able to assume that an exception is thrown almost anywhere &lt;br /&gt;
from within the code, with well-defined results (i.e. no resource leaks).&lt;br /&gt;
&lt;br /&gt;
Code that uses a pattern like,&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
  SDL_Surface* image = IMG_Load(&amp;quot;image.bmp&amp;quot;);&lt;br /&gt;
  ...some code, which uses 'image'...&lt;br /&gt;
  SDL_FreeSurface(image);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
is bad, because the code may throw an exception, and 'image' will never be freed. &lt;br /&gt;
Instead, use wrapper objects which free the object in their destructor.&lt;br /&gt;
&lt;br /&gt;
For SDL_Surface objects, use the &amp;lt;tt&amp;gt;surface&amp;lt;/tt&amp;gt; class. &lt;br /&gt;
So you could rewrite the above code,&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
  surface image(IMG_Load(&amp;quot;image.bmp&amp;quot;));&lt;br /&gt;
  ...some code, which uses 'image'...&lt;br /&gt;
  } ''the image is automatically freed here when 'image' is destroyed&lt;br /&gt;
&lt;br /&gt;
Instead of allocating memory directly using new[] or malloc(), &lt;br /&gt;
use language-provided containers, such as vector.&lt;br /&gt;
&lt;br /&gt;
=== Do not use sprintf ===&lt;br /&gt;
&lt;br /&gt;
Sprintf does not check whether or not it is writing past the end of the space allocated. &lt;br /&gt;
This is a security problem if someone other than the person running the game &lt;br /&gt;
can cause sprintf to write very long strings. &lt;br /&gt;
In Wesnoth this untrusted data could come potentially from other players &lt;br /&gt;
in a multiplayer game or from downloaded campaigns. &lt;br /&gt;
Instead you should use snprintf with the second argument being sizeof of the buffer &lt;br /&gt;
that will hold the result.&lt;br /&gt;
&lt;br /&gt;
== Standard C++ to avoid ==&lt;br /&gt;
&lt;br /&gt;
=== Do not use wstring ===&lt;br /&gt;
&lt;br /&gt;
The standard C++ wstring class, defined as a basic_string&amp;lt; wchar_t &amp;gt;, &lt;br /&gt;
does not exist in some platforms supported by Wesnoth. &lt;br /&gt;
Use wide_string, defined in language.hpp, instead. &lt;br /&gt;
wide_string is actually defined as a vector&amp;lt; wchar_t &amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Do not use 0 when you mean NULL ===&lt;br /&gt;
&lt;br /&gt;
Several Wesnoth developers, including Dave, find the number 0 to be very ambiguous when used in a non-numeric context. In keeping with the precedent that has already been established in the Wesnoth source code, you should avoid using literal zero for initializing and/or comparing null pointers.&lt;br /&gt;
&lt;br /&gt;
== C legacy to be avoided ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use util::array instead of C-style Arrays ===&lt;br /&gt;
&lt;br /&gt;
C-style arrays are very efficient, but their interface is ugly. &lt;br /&gt;
Use util::array defined in array.hpp. &lt;br /&gt;
It is a wrapper for an array which has a C++ container-style interface. &lt;br /&gt;
If you need to, extend it to make it fit your needs.&lt;br /&gt;
&lt;br /&gt;
=== Do not use C-style casts ===&lt;br /&gt;
&lt;br /&gt;
The following code,&lt;br /&gt;
&lt;br /&gt;
  if(i-&amp;gt;second.side() == (size_t)player_number_) {&lt;br /&gt;
&lt;br /&gt;
is considered bad practice in C++ since a C-style cast is overpowered -- if types change around it could end up casting away constness, or performing an implementation-defined data reinterpretation (basically a C-style cast is a compiler generated combination of static_cast, reinterpret_cast, and const_cast).&lt;br /&gt;
&lt;br /&gt;
Good programming style is to use the least powerful tool available that does what you want. &lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
  if(i-&amp;gt;second.side() == static_cast&amp;lt;size_t&amp;gt;(player_number_)) {&lt;br /&gt;
&lt;br /&gt;
Alternatively, a constructor call may be used for non-builtin types.&lt;br /&gt;
&lt;br /&gt;
Note: there may be some obscure cases where a C-style cast is desirable, &lt;br /&gt;
such as converting a pointer to an integer type of unspecified size.&lt;br /&gt;
&lt;br /&gt;
=== Do not use #define for constant variable ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;define foo X is not typesafe and you can use a const foo = X; &lt;br /&gt;
(in an anonymous namespace) to achieve the same but typesafe.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
=== Document &amp;quot;config&amp;quot; preconditions and postconditions ===&lt;br /&gt;
&lt;br /&gt;
In the Wesnoth code you will commonly encounter a data container known as the &amp;quot;config&amp;quot;, &lt;br /&gt;
which contains heirarchical string data (such as WML contents or game settings). &lt;br /&gt;
The tagged &amp;quot;children&amp;quot; of the config and their string &amp;quot;attributes&amp;quot; are arranged &lt;br /&gt;
in an ordered and mapped format internally using STL.&lt;br /&gt;
&lt;br /&gt;
Because config data is utilized in so many ways and places,  it can be difficult to track across the scope of the entire program. You should document all public functions that take/return a config, specifying config content expectations (and updating any related entries in the [[ReferenceWML]] wiki pages). &lt;br /&gt;
In particular, if your function requires a config parameter, specify where/how the config should be created. This will be a great help to any future coders who need to call or modify your function.&lt;br /&gt;
&lt;br /&gt;
=== Doxygen ===&lt;br /&gt;
See [[Doxygen]] for tips on how to comment the code,&lt;br /&gt;
so that doxygen can nicely document it.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[HackingWesnoth]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=30042</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=30042"/>
		<updated>2009-04-08T16:38:08Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* WML Profiling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which leads to even worse memory-efficiency. There are several different ways that we can improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and so is not very memory-efficient if we want decent performance. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that insertions can move elements to different buckets and so our &amp;quot;indices&amp;quot; will need to be updateable. This likely means that they would need an extra level of indirection so they can point to something that doesn't move. Also, with blocked cuckoo hashing the table has a fixed constant size, if it gets too large we would have to resize it which can be quite slow. A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distinct string (due to the linked list pointer). We would likely hold a large block of listnodes in a vector or deque so that they don't all require a small memory allocation.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we have these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. This would allow us to aggressively unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''EDIT''' 9/4/09 00:40 GMT &amp;lt;br&amp;gt;&lt;br /&gt;
Lazy optimizations is not really a good title for these as I actually intend for config objects to move back and forth between these states. That is, we should be able to, when constructing a config object, tell it which of the three states to be in. And we should be able to tell it at any time to go into any of the three states.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
EDIT: I have started doing some of this [[cjhopman_wml|here]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9 here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=30041</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=30041"/>
		<updated>2009-04-08T16:37:10Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* WML Profiling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which leads to even worse memory-efficiency. There are several different ways that we can improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and so is not very memory-efficient if we want decent performance. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that insertions can move elements to different buckets and so our &amp;quot;indices&amp;quot; will need to be updateable. This likely means that they would need an extra level of indirection so they can point to something that doesn't move. Also, with blocked cuckoo hashing the table has a fixed constant size, if it gets too large we would have to resize it which can be quite slow. A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distinct string (due to the linked list pointer). We would likely hold a large block of listnodes in a vector or deque so that they don't all require a small memory allocation.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we have these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. This would allow us to aggressively unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''EDIT''' 9/4/09 00:40 GMT &amp;lt;br&amp;gt;&lt;br /&gt;
Lazy optimizations is not really a good title for these as I actually intend for config objects to move back and forth between these states. That is, we should be able to, when constructing a config object, tell it which of the three states to be in. And we should be able to tell it at any time to go into any of the three states.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
EDIT: I have started doing some of this [[#cjhopman_wml|here]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9 here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29879</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29879"/>
		<updated>2009-04-04T02:53:48Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* String Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which leads to even worse memory-efficiency. There are several different ways that we can improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and so is not very memory-efficient if we want decent performance. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that insertions can move elements to different buckets and so our &amp;quot;indices&amp;quot; will need to be updateable. This likely means that they would need an extra level of indirection so they can point to something that doesn't move. Also, with blocked cuckoo hashing the table has a fixed constant size, if it gets too large we would have to resize it which can be quite slow. A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distinct string (due to the linked list pointer). We would likely hold a large block of listnodes in a vector or deque so that they don't all require a small memory allocation.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we have these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. This would allow us to aggressively unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''EDIT''' 9/4/09 00:40 GMT &amp;lt;br&amp;gt;&lt;br /&gt;
Lazy optimizations is not really a good title for these as I actually intend for config objects to move back and forth between these states. That is, we should be able to, when constructing a config object, tell it which of the three states to be in. And we should be able to tell it at any time to go into any of the three states.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9 here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29878</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29878"/>
		<updated>2009-04-04T02:40:57Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* String Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which leads to even worse memory-efficiency. There are several different ways that we can improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and so is not very memory-efficient if we want decent performance. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that insertions can move elements to different buckets and so our &amp;quot;indices&amp;quot; will need to be updateable. This likely means that they would need an extra level of indirection so they can point to something that doesn't move. Also, with blocked cuckoo hashing the table has a fixed constant size, if it gets too large we would have to resize it which can be quite slow. A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distinct string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we have these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. This would allow us to aggressively unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''EDIT''' 9/4/09 00:40 GMT &amp;lt;br&amp;gt;&lt;br /&gt;
Lazy optimizations is not really a good title for these as I actually intend for config objects to move back and forth between these states. That is, we should be able to, when constructing a config object, tell it which of the three states to be in. And we should be able to tell it at any time to go into any of the three states.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9 here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29877</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29877"/>
		<updated>2009-04-04T00:40:24Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Lazy Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which leads to even worse memory-efficiency. There are several different ways that we can improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and so is not very memory-efficient if we want decent performance. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distinct string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we have these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. This would allow us to aggressively unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''EDIT''' 9/4/09 00:40 GMT &amp;lt;br&amp;gt;&lt;br /&gt;
Lazy optimizations is not really a good title for these as I actually intend for config objects to move back and forth between these states. That is, we should be able to, when constructing a config object, tell it which of the three states to be in. And we should be able to tell it at any time to go into any of the three states.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9 here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29876</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29876"/>
		<updated>2009-04-04T00:39:44Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Lazy Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which leads to even worse memory-efficiency. There are several different ways that we can improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and so is not very memory-efficient if we want decent performance. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distinct string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we have these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. This would allow us to aggressively unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''EDIT'''&amp;lt;br&amp;gt;&lt;br /&gt;
Lazy optimizations is not really a good title for these as I actually intend for config objects to move back and forth between these states. That is, we should be able to, when constructing a config object, tell it which of the three states to be in. And we should be able to tell it at any time to go into any of the three states.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9 here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29875</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29875"/>
		<updated>2009-04-04T00:30:16Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Lazy Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which leads to even worse memory-efficiency. There are several different ways that we can improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and so is not very memory-efficient if we want decent performance. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distinct string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we have these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. This would allow us to aggressively unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9 here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29850</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29850"/>
		<updated>2009-04-03T21:46:42Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* String Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which leads to even worse memory-efficiency. There are several different ways that we can improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and so is not very memory-efficient if we want decent performance. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distinct string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9 here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29849</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29849"/>
		<updated>2009-04-03T21:43:59Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Timeline */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which leads to even worse memory-efficiency. There are several different ways that we can improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9 here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29848</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29848"/>
		<updated>2009-04-03T21:41:39Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Technical details */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which leads to even worse memory-efficiency. There are several different ways that we can improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29847</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29847"/>
		<updated>2009-04-03T21:38:56Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Technical details */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can leads to even worse memory-efficiency. There are several different ways that we can improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29846</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29846"/>
		<updated>2009-04-03T21:36:58Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Larger patches and other substantial contributions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up because being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29845</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29845"/>
		<updated>2009-04-03T21:31:40Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Technical details */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if certain assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29844</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29844"/>
		<updated>2009-04-03T21:30:55Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* String Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The problem is that a basic linear-probing hash table performs very poorly at high load factors and is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29843</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29843"/>
		<updated>2009-04-03T21:29:01Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* String Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). As we will be allocating a lot of these listnodes, this is a nearly perfect opportunity to use Boost.Pool so that we don't actually do a bunch of small memory allocations.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29842</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29842"/>
		<updated>2009-04-03T21:26:39Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* String Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an extra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29841</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29841"/>
		<updated>2009-04-03T21:25:19Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Config Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (that is, basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29840</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29840"/>
		<updated>2009-04-03T21:24:48Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Config Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This is a significant amount of overhead per child config and attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29839</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29839"/>
		<updated>2009-04-03T21:22:32Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Lazy Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each tag stored with its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29838</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29838"/>
		<updated>2009-04-03T21:21:54Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Lazy Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store some more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29837</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29837"/>
		<updated>2009-04-03T21:21:00Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Lazy Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell how long a WML tag/attribute is. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29836</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29836"/>
		<updated>2009-04-03T21:17:16Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* WML Profiling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but investigating them is one reason for me to do some extensive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage patterns (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29835</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29835"/>
		<updated>2009-04-03T21:10:37Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Lazy Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&amp;lt;br&amp;gt;&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&amp;lt;br&amp;gt;&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29832</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29832"/>
		<updated>2009-04-03T20:43:27Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Basics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29831</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29831"/>
		<updated>2009-04-03T20:42:50Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Basics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29817</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29817"/>
		<updated>2009-04-03T19:44:56Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* String Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29815</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29815"/>
		<updated>2009-04-03T19:25:22Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Project */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* I already know and like the Wesnoth community. I will stay regardless of anything that happens for SOC.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29805</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29805"/>
		<updated>2009-04-03T18:49:32Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Lazy Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload a lot of WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29804</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29804"/>
		<updated>2009-04-03T18:45:00Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* WML Profiling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeIdeas&amp;diff=29803</id>
		<title>SummerOfCodeIdeas</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeIdeas&amp;diff=29803"/>
		<updated>2009-04-03T18:44:06Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Optimize implementation of WML for memory usage */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a compilation of ideas from ML. Needs to be refined (more detailed description, deliverables, workload estimation?):&lt;br /&gt;
&lt;br /&gt;
== I want to be one of your Google Summer of Code students, what should I do... ==&lt;br /&gt;
&lt;br /&gt;
Here is a quick list of things to do to get you started&lt;br /&gt;
* Create an account on gna.org&lt;br /&gt;
* Create an account on the wesnoth forum, and tell an admin on the IRC channel to mark is as a GSoC Student account (Admins are boucman, Ivanovic, mordante, Shadow_Master, Sirp and Turuk)&lt;br /&gt;
* Join the irc channel (#wesnoth-dev on irc.freenode.net) and introduce yourself. We will not give formal interviews, but we will clearly favor people we have learned to know during the selection process (basically communication via IRC is mandatory for our project! it is the main way of &amp;quot;every day communication&amp;quot; for Wesnoth. For the same reason, it's also a good idea to regularly read the [http://wesnoth.debian.net/?C=M;O=A IRC logs].).&lt;br /&gt;
&lt;br /&gt;
* Start a wiki page about your idea, add a link on the bottom of this page and add this information on it:&lt;br /&gt;
** List your account names (gna, forum, irc nick) so that we can recognize you&lt;br /&gt;
** Fill the questionnaire on this page: [[SoC_Information_for_Google#Does_your_organization_have_an_application_template_you_would_like_to_see_students_use.3F_If_so.2C_please_provide_it_now.| List of questions to answer]]&lt;br /&gt;
** Detail your idea as much as possible, look at other students pages, and please give milestones and studies you've done&lt;br /&gt;
** Add a link to the page at the bottom of this page&lt;br /&gt;
&lt;br /&gt;
* Though not mandatory, it is highly advisable to go to the [[EasyCoding]] and [[NotSoEasyCoding]] pages and implement one of these ideas (or any idea of similar scope) so we have an idea how you work. Be sure to use your gna account when submitting these patches so we know who it is coming from. You can also implement some features from our feature request database at gna. When you implement something, also list it on your own page with a reference to the patch.&lt;br /&gt;
&lt;br /&gt;
* For working on Wesnoth you have to be able to compile trunk. To do so you should have a look at the [[WesnothSVN|page about svn]] and afterwards [[CompilingWesnoth|compile Wesnoth svn]].&lt;br /&gt;
&lt;br /&gt;
* Once you have everything done here and think your idea is okay, go to [http://groups.google.com/group/google-summer-of-code-announce/web/guide-to-the-gsoc-web-app-for-student-applicants page at google] to submit your application. You have to submit it before '''April 3rd at 19:00 UTC (12:00 PST)''' or you have no chance to get in!&lt;br /&gt;
&lt;br /&gt;
== List of Ideas for the Project (Suggestions from the wesnoth developers) ==&lt;br /&gt;
&lt;br /&gt;
Here is only a short description of possible Ideas we have, each has a page of its own with a more detailed version on it.&lt;br /&gt;
&lt;br /&gt;
=== Optimize implementation of WML for memory usage ===&lt;br /&gt;
&lt;br /&gt;
Based on this idea: [http://dave.wesnoth.org/?p=9] optimize WML to minimize its memory usage. High memory usage has been a problem for Wesnoth, and this project will aim to reduce it.&lt;br /&gt;
&lt;br /&gt;
=== Implement campaign statistics reports on stats.wesnoth.org ===&lt;br /&gt;
&lt;br /&gt;
Wesnoth has an infrastructure which records details of campaigns that players play into a centralized MySQL database. However, we only have rudimentary reports based on this MySQL database available at this time, at [http://stats.wesnoth.org].&lt;br /&gt;
&lt;br /&gt;
This project would involve writing a stats reporting web site which would take the data from the MySQL database and produce reports in chart and table form. Campaign designers would be able to use these reports to gather feedback on their campaigns and get ideas for improvements.&lt;br /&gt;
&lt;br /&gt;
A student could largely make their choice of infrastructure for creating the Website -- whether they prefer Python, Perl, Ruby, PHP, etc. This is a great opportunity for someone who doesn't want to dive into hardcore C++ to make a valuable contribution to Wesnoth.&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas Stats Server]] - Full Version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
=== Extending the Multiplayer server ===&lt;br /&gt;
&lt;br /&gt;
Our multiplayer community is generally strong and healthy, but we believe its growth is limited by some problems in the interface of the multiplayer lobby.&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas Multiplayer server]] - Full version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
=== Addon server ===&lt;br /&gt;
Wesnoth has an addon server which offers users to upload user &lt;br /&gt;
made content (UMC). This allows all other users of Wesnoth&lt;br /&gt;
to easily download and install this content. The server was &lt;br /&gt;
originally written for user-made campaigns but contains a lot&lt;br /&gt;
more types of addons nowadays. Both the server side and the &lt;br /&gt;
client side need to be improved.&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas Addon Server]] - Full version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
=== WML validation schemes ===&lt;br /&gt;
Wesnoth uses WML as basic data structure. Over the years&lt;br /&gt;
this language has evolved and got more complex. At the&lt;br /&gt;
moment the WML is validated at runtime and in case of a&lt;br /&gt;
problem the engine stops. With schemes these problems can&lt;br /&gt;
be validated when loading the WML, making it easier to find&lt;br /&gt;
problems before running into them.&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas Schemes]] - Full version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
=== Write a primitive library for Formula AI ===&lt;br /&gt;
&lt;br /&gt;
Wesnoth has always had a simple C++ based AI. David (our lead developer) has been working on a simple language to write AI in Wesnoth: [[FormulaAI]]&lt;br /&gt;
&lt;br /&gt;
The Wesnoth AI is used as an opponent in most campaigns, and as such is an important piece of code for the Wesnoth project. Unfortunately, because the skills required to understand and modify it are rather arcane, it is also one of the most neglected parts of the Wesnoth code. This is a place where a lot of research and useful work could be done. But keep in mind that [[WhyWritingAWesnothAIIsHard|writing an AI for Wesnoth is difficult]].&lt;br /&gt;
&lt;br /&gt;
Writing a whole AI is so complicated that we believe it can't be done in a single Summer of code. All proposals should keep that in mind and try to identify an interesting subset that would be workable in the limited time of a summer of code&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas FormulaAI]] - Full version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
=== Savegame reorganization ===&lt;br /&gt;
The savegame formats of Wesnoth for single player campaigns&lt;br /&gt;
and multiplayer differ from each other. And they are processed&lt;br /&gt;
differently as well. Now there is an additional request coming&lt;br /&gt;
up: Multiplayer campaigns. The task will be to unify the savegames&lt;br /&gt;
for all types of scenarios in order to provide a maintainable code&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
[[SoC Ideas Savegame]] - Full version of the idea, with detailed information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Other possible ideas to be fleshed out ===&lt;br /&gt;
A MapGenerator rewrite - better scalable for outdoor maps, plus the possibility to define areas (similar to the caverns in the cave generator) etc.&lt;br /&gt;
&lt;br /&gt;
=== Make your own ideas ===&lt;br /&gt;
If you have your own idea the best thing is to join IRC wesnoth-dev at irc.freenode.net and discuss the idea with the developers there. If the developers think your idea is interesting and like the feature you can start to turn it into a full proposal. Once done discuss it again on IRC so the developers can accept your idea.&lt;br /&gt;
&lt;br /&gt;
== Information about our Project ==&lt;br /&gt;
The information we provided google with about our project can be looked up at the site [[SoC Information for Google]].&lt;br /&gt;
&lt;br /&gt;
Also see the [[DeveloperResources]] link (from the [[Project]] page).&lt;br /&gt;
&lt;br /&gt;
== People to bug on IRC ==&lt;br /&gt;
We have prepared a list of people with their &amp;quot;area of competence&amp;quot;. This is to give you an idea on which areas those people can be of help for you. Of course you should always just ask in the IRC chan, but those are the most likely ones to answer questions in the respective area. And here is the list:&lt;br /&gt;
&lt;br /&gt;
[[SoC People to bug on IRC]]&lt;br /&gt;
&lt;br /&gt;
== GSoC Student pages ==&lt;br /&gt;
&lt;br /&gt;
Please add a link to your wiki page below&lt;br /&gt;
&lt;br /&gt;
==== AI ====&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_Velory| Velory - SoC Proposal]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_AI_Improvement_Crab| Crab - SoC Proposal - AI Improvement]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_Sparksteel | Sparksteel - Improving the AI engine design]]&lt;br /&gt;
&lt;br /&gt;
[[FormulaAISoC2009Dragonking | Dragonking - Improving the formula AI ]]&lt;br /&gt;
&lt;br /&gt;
[[GSoC_Proposal_-_Position_Evaluation | henning - Position Evaluation ]]&lt;br /&gt;
&lt;br /&gt;
[[GSoC_Proposal_Evolutionary_AI | heineckm - Evolutionary AI]]&lt;br /&gt;
&lt;br /&gt;
==== Savegame reorganization ====&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_Euschn | Euschn - Savegame reorganization]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_lmg| lmg - Savegame reorganization]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_grantwu| grantwu - Savegame reorganization]]&lt;br /&gt;
&lt;br /&gt;
==== Extending the Multiplayer server ====&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_rubend | rubend - Extending the Multiplayer server]]&lt;br /&gt;
&lt;br /&gt;
[[MP Server Ilor | Ilor - Extending the Multiplayer server]]&lt;br /&gt;
&lt;br /&gt;
==== Addon server ====&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_Ryochan7| Ryochan7 - Addon server]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_iyonius| iyonius - Addon server]]&lt;br /&gt;
&lt;br /&gt;
==== Optimize implementation of WML for memory usage ====&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_res| res -  Optimize implementation of WML for memory usage ]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_jdmunro| jdmunro -  Optimize implementation of WML for memory usage ]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_Ryanc| ryanc -  Optimize implementation of WML for memory usage ]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_cjhopman| cjhopman -  Optimize implementation of WML for memory usage ]]&lt;br /&gt;
&lt;br /&gt;
==== Implement campaign statistics reports on stats.wesnoth.org ====&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_Elbin| Elbin - New campaign statistics page]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_Munk| Munk - New campaign stats page]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_carlestyle| carlestyle - New campaign stats page]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_nerwa| NeRwa - New campaign stats page]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_mrfinch| mrfinch - New Campaign Statistics Page]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_corn| corn - New Campaign Statistics Page]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_csaunders | csaunders - SoC Proposal - Stats Server]]&lt;br /&gt;
&lt;br /&gt;
[[SummerOfCodeProposal_rohita | Rohita - New campaign stats page ]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code|*]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29802</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29802"/>
		<updated>2009-04-03T18:43:09Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman Profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29801</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29801"/>
		<updated>2009-04-03T18:41:54Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* String Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will likely have more overhead than the hashing options. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman Profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29800</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29800"/>
		<updated>2009-04-03T18:40:35Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* note to mentors */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman Profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29799</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29799"/>
		<updated>2009-04-03T18:40:05Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Timeline */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman Profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins. Start with string optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 20th&amp;lt;br&amp;gt;&lt;br /&gt;
String optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin wml representation optimizations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
June 27th&amp;lt;br&amp;gt;&lt;br /&gt;
WML representation optimizations finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 6th&amp;lt;br&amp;gt;&lt;br /&gt;
Submission of midterm evaluations begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 27th&amp;lt;br&amp;gt;&lt;br /&gt;
Framework for lazy loading/construction finished, tested, and documented.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin pass of intensive debugging and documentation on all three parts. Each of the three parts have already been tested and documented so this is just a sort of final cleaning pass.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 3rd&amp;lt;br&amp;gt;&lt;br /&gt;
Begin migration of current code to use lazy loading/construction where appropriate.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 10th&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;Pencils down&amp;quot; date.&amp;lt;br&amp;gt;&lt;br /&gt;
Everything should actually be completed by this time, and this final week is a sort of buffer to ensure that everything is very well-tested and documented.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
August 17th&amp;lt;br&amp;gt;&lt;br /&gt;
End of GSOC.&amp;lt;br&amp;gt;&lt;br /&gt;
Final evaluation submission begins.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29795</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29795"/>
		<updated>2009-04-03T18:19:01Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Timeline */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman Profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
April 3rd - April 15th&amp;lt;br&amp;gt;&lt;br /&gt;
Convince Wesnoth mentors to accept my proposal.&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up some cpu optimizations that I am working on for Wesnoth.&amp;lt;br&amp;gt;&lt;br /&gt;
Begin more in-depth profiling of loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 17th - April 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
I get to go to Stockholm for a week.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 20th&amp;lt;br&amp;gt;&lt;br /&gt;
Accepted proposals announced on GSOC site.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
April 23rd - May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Finish up in-depth profiling of loaded WML in preparation for coding to begin.&amp;lt;br&amp;gt;&lt;br /&gt;
Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 10th - May 16th&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
May 23rd&amp;lt;br&amp;gt;&lt;br /&gt;
Coding begins.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
July 4th&amp;lt;br&amp;gt;&lt;br /&gt;
Have string optimizations and wml representation optimizations complete. Begin working on lazy loading/construction.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29794</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29794"/>
		<updated>2009-04-03T18:18:07Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Timeline */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman Profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
 April 3rd - April 15th&lt;br /&gt;
 Convince Wesnoth mentors to accept my proposal.&lt;br /&gt;
 Finish up some cpu optimizations that I am working on for Wesnoth.&lt;br /&gt;
 Begin more in-depth profiling of loaded WML.&lt;br /&gt;
 &lt;br /&gt;
 April 17th - April 23rd&lt;br /&gt;
 I get to go to Stockholm for a week.&lt;br /&gt;
 &lt;br /&gt;
 April 20th&lt;br /&gt;
 Accepted proposals announced on GSOC site.&lt;br /&gt;
 &lt;br /&gt;
 April 23rd - May 23rd&lt;br /&gt;
 Finish up in-depth profiling of loaded WML in preparation for coding to begin.&lt;br /&gt;
 Make changes to config class to hide internals as described [http://dave.wesnoth.org/?p=9|here].&lt;br /&gt;
 &lt;br /&gt;
 May 10th - May 16th&lt;br /&gt;
 I have a couple of finals. I will likely actually have more time this week as I won't have class every day.&lt;br /&gt;
&lt;br /&gt;
 May 23rd&lt;br /&gt;
 Coding begins.&lt;br /&gt;
&lt;br /&gt;
 July 4th&lt;br /&gt;
 Have string optimizations and wml representation optimizations complete. Begin working on lazy loading/construction.&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29793</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29793"/>
		<updated>2009-04-03T18:04:20Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* WML Profiling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
Before doing any optimizations, we need to know whether or not it has a possibility of making an improvement. Basically the assumptions that we have made are that there a lot of strings, a lot of these strings are not unique, and there are a lot of config objects. These are reasonable assumptions, but it is one reason for me to do some intrusive profiling.&amp;lt;br&amp;gt;&lt;br /&gt;
The second reason to do profiling is to determine the benefit of optimizations that we do write. For this reason I have already set up a heap profiler so that I can see some higher level memory usage profiles (see [[Cjhopman Profiling]]). I also plan to do some more intrusive programming, basically I want to be able to see the structure of the graph of config objects (with some info like size of current, size of all children, etc.). Also, I will want to see the distribution of strings in tag names, attribute keys and attribute values. This will be the first thing that I do for this project, currently scheduled to be done before the actual start of coding time.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29791</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29791"/>
		<updated>2009-04-03T17:53:09Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* String Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
''More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
''More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29790</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29790"/>
		<updated>2009-04-03T17:52:08Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Lazy Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. &amp;lt;br&amp;gt;&lt;br /&gt;
While lazy loading will cut memory usage of a config object by, basically, 100%, I expect lazy construction to cut it by as much as 50%. The benefit of lazy construction would be that construction of the object once it is needed will not have to go to disk and so will be faster.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we wanted to get really aggressive, we could have either of these lazy schemes actually store a bit more information so that construction would not require full parsing. In particular, I am thinking that we could have each element store its length, then when we need to build a thing we can do it much more quickly. One benefit of this is that it would allow us to reasonably unload WML that we think won't be needed.&amp;lt;br&amp;gt;&lt;br /&gt;
This optimization actually has the potential to greatly reduce memory usage. Implementing this will likely hit several parts of the code (config, config_cache, parser, ...).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===WML Profiling===&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29788</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29788"/>
		<updated>2009-04-03T17:30:24Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* String Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation is that we can optimize the low level representation of the string. I think the best option for this would be to use or adapt an already written lightweight string. A more important aspect of the low-level string representation is that it does a lot of small memory allocations. To solve this we can use some type of pool allocation (possibly Boost.Pool) for our lightweight strings.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. This is, I'd say, a more inter&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29787</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29787"/>
		<updated>2009-04-03T17:16:02Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Lazy Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation that I will mention is that we can optimize the low level representation of the string. This is currently outside the scope of my gsoc project, though if profiling shows that there is a lot to gain in this area then that could change. I think the best option for this would be to use or adapt an already written lightweight string. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. In fact, the associated type identifiers could be packed into the high bits of a 32 bit index into the string hash table. This is, I'd say, a more inter&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29756</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29756"/>
		<updated>2009-04-03T09:34:05Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Lazy Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation that I will mention is that we can optimize the low level representation of the string. This is currently outside the scope of my gsoc project, though if profiling shows that there is a lot to gain in this area then that could change. I think the best option for this would be to use or adapt an already written lightweight string. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
Finally, we load a lot of WML (and build the corresponding config objects) that we don't need to. I intend to implement a framework that will allow us to lazily load WML from disk, and that will possibly allow us to lazily construct config objects from the loaded WML.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Loading'''&lt;br /&gt;
The most aggressive lazy optimization would be to leave WML on disk until needed. This could save us a lot of memory, but could require us to minimally parse the WML multiple times as there is no way to tell when a WML block ends. One other similar possibility is to load and parse the WML, and then write it to a temporary cache. This would be simpler to do and its possible that cached WML is already in a format that would allow for easy lazy loading (I am not sure of the format of cached WML).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Lazy Construction'''&lt;br /&gt;
A slightly less aggressive, but still useful, optimization would be to not fully construct some config objects. With the previously discussed string representation, a config object becomes simply a stream of ints and associated types. That is, everything&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29754</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29754"/>
		<updated>2009-04-03T09:14:03Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Config Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation that I will mention is that we can optimize the low level representation of the string. This is currently outside the scope of my gsoc project, though if profiling shows that there is a lot to gain in this area then that could change. I think the best option for this would be to use or adapt an already written lightweight string. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). This should cut the overhead per config object in half, and there should be almost no overhead per attribute. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29753</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29753"/>
		<updated>2009-04-03T09:04:31Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Technical details */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy Work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation that I will mention is that we can optimize the low level representation of the string. This is currently outside the scope of my gsoc project, though if profiling shows that there is a lot to gain in this area then that could change. I think the best option for this would be to use or adapt an already written lightweight string. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). I believe that, after a config object is built, most operations are lookups and there are only a few insertions and deletions. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29752</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29752"/>
		<updated>2009-04-03T09:04:17Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Technical details */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation that I will mention is that we can optimize the low level representation of the string. This is currently outside the scope of my gsoc project, though if profiling shows that there is a lot to gain in this area then that could change. I think the best option for this would be to use or adapt an already written lightweight string. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). I believe that, after a config object is built, most operations are lookups and there are only a few insertions and deletions. Without further profiling, I believe that the sorted vectors is the best approach. This change would have less memory overhead and would allocate the memory that it does use in larger blocks than the current method.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Lazy Work===&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29751</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29751"/>
		<updated>2009-04-03T09:03:00Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Config Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation that I will mention is that we can optimize the low level representation of the string. This is currently outside the scope of my gsoc project, though if profiling shows that there is a lot to gain in this area then that could change. I think the best option for this would be to use or adapt an already written lightweight string. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (basically, vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). I believe that, after a config object is built, most operations are lookups and there are only a few insertions and deletions. Without further profiling, I believe that the sorted vectors is the best approach.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29750</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29750"/>
		<updated>2009-04-03T09:02:18Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Config Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation that I will mention is that we can optimize the low level representation of the string. This is currently outside the scope of my gsoc project, though if profiling shows that there is a lot to gain in this area then that could change. I think the best option for this would be to use or adapt an already written lightweight string. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;pair&amp;lt;string_index, config*&amp;gt; &amp;gt;, that is). I believe that, after a config object is built, most operations are lookups and there are only a few insertions and deletions. Without further profiling, I believe that the sorted vectors is the best approach.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29749</id>
		<title>SummerOfCodeProposal cjhopman</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=SummerOfCodeProposal_cjhopman&amp;diff=29749"/>
		<updated>2009-04-03T09:01:55Z</updated>

		<summary type="html">&lt;p&gt;Cjhopman: /* Config Representation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===note to mentors=== &lt;br /&gt;
this is a work in progress, feel free to not review it yet.&lt;br /&gt;
&lt;br /&gt;
==Questionnaire==&lt;br /&gt;
===Basics===&lt;br /&gt;
&lt;br /&gt;
# Write a small introduction to yourself. &lt;br /&gt;
#* My name is Chris Hopman, I'm a student of computer science and mathematics. I'm graduating from the University of Wisconsin - Madison in May and will be attending the computer science PhD program here in the fall.&lt;br /&gt;
# State your preferred email address. &lt;br /&gt;
#* cjhopman@gmail.com&lt;br /&gt;
# If you have chosen a nick for IRC and Wesnoth forums, what is it? &lt;br /&gt;
#* My nick is cjhopman pretty much everywhere.&lt;br /&gt;
# Why do you want to participate in summer of code? &lt;br /&gt;
#* Participating in summer of code will give me an opportunity to spend a lot of time doing something that I enjoy. I will get to work on an interesting project and will get to make a major contribution to a great project.&lt;br /&gt;
# What are you studying, subject, level and school? &lt;br /&gt;
#* I am currently an undergraduate studying mathematics and computer science at the University of Wisconsin - Madison. I will be graduating in May and will be attending the PhD program here in the fall.&lt;br /&gt;
# If you have contributed any patches to Wesnoth, please list them below. You can also list patches that have been submitted but not committed yet and patches that have not been specifically written for Wesnoth. If you have gained commit access to our SVN (during the evaluation period or earlier) please state so. &lt;br /&gt;
#* I received commit access to the Wesnoth SVN early in 2008. There is a list of some of my [[#My contributions to Wesnoth|contributions]] below.&lt;br /&gt;
&lt;br /&gt;
===Experience===&lt;br /&gt;
&lt;br /&gt;
# What programs/software have you worked on before?&lt;br /&gt;
#* The largest program that I have worked on is definitely Wesnoth. Other than that, and other than projects just for classes, I have worked on two other projects. The first is [http://code.google.com/p/autoscanner autoscanner]. The goal of this program is to do automatic 3d reconstruction of a statue from a short video clip. I did this project with another student for a professor that we worked for. The second project is more of a library of various functions. It can be found [http://code.google.com/p/wrong-answer-library here]. It is meant primarily to be useful for algorithm competitions (TopCoder, ICPC, etc.) and so is mostly graph theory, computational geometry, linear algebra, and other similar stuff.&lt;br /&gt;
# Have you developed software in a team environment before? (As opposed to hacking on something on your own) &lt;br /&gt;
#* Other than Wesnoth, the two projects I just mentioned were both done in groups of 2-3. So, primarily my experience of developing software in a team environment is just that from my contributions to Wesnoth.&lt;br /&gt;
# Have you participated to the Google Summer of Code before? As a mentor or a student? In what project? Were you successful? If not, why? &lt;br /&gt;
#* I have not participated in Google Summer of Code before.&lt;br /&gt;
&lt;br /&gt;
===Open Source===&lt;br /&gt;
&lt;br /&gt;
# Are you already involved with any open source development projects? If yes, please describe the project and the scope of your involvement. &lt;br /&gt;
#* Wesnoth is the only open source project that I am involved in (actually both of my projects on code.google.com are also open source but it's a whole different level). Most of my contribution to Wesnoth has been bug fixes and other minor work, though I have had several larger contributions. There is a list of these [[#My contributions to Wesnoth|below]].&lt;br /&gt;
&lt;br /&gt;
===Gaming experience - Are you a gamer?===&lt;br /&gt;
&lt;br /&gt;
# What type of gamer are you? &lt;br /&gt;
#* I am a diverse gamer. I've been playing games for more than 80% of my life (wow, just realized how long it has been)&lt;br /&gt;
# What type of games? &lt;br /&gt;
#* I like pretty much all genres. Yet, my favorites tend to be strategy games or rpgs. And those that find a good blend of the two are great. For example, Battle for Wesnoth (some others, too--Final Fantasy Tactics comes to mind).&lt;br /&gt;
# What type of opponents do you prefer? &lt;br /&gt;
#* Smart ones. I love the challenge of trying to outplay a smart player.&lt;br /&gt;
# Are you more interested in story or gameplay?&lt;br /&gt;
#* It depends. Generally when I am playing single-player games story and gameplay are both important though I am more likely to accept below average gameplay for an above average story than vice-versa. Playing multiplayer, particularly competitive multiplayer, gameplay is much more important.&lt;br /&gt;
# Have you played Wesnoth? If so, tell us roughly for how long and whether you lean towards single player or multiplayer. &lt;br /&gt;
#* I have played Wesnoth for a bit over a year. I had focused on single player campaigns but in the last two months have shifted to almost only multiplayer.&lt;br /&gt;
&lt;br /&gt;
===Communication skills===&lt;br /&gt;
&lt;br /&gt;
# Though most of our developers are not native English speakers, English is the project's working language. Describe your fluency level in written English. &lt;br /&gt;
#* I am fluent in written English. I had better be as I am definitely not in any others.&lt;br /&gt;
# Are you good at interacting with other players? Our developer community is friendly, but the player community can be a bit rough. &lt;br /&gt;
#* Yes, I am good at interacting with other players and with other people in general. &lt;br /&gt;
# Do you give constructive advice? &lt;br /&gt;
#* I think that I give constructive advice. I have been a tutor in math and computer science for a couple years and a sailing instructor for longer. Both of these have definitely improved my ability to give constructive advice.&lt;br /&gt;
# Do you receive advice well? &lt;br /&gt;
#* Yes, I do. I feel that a factor in this is that I am always interested in learning more and advice often offers an opportunity to do that.&lt;br /&gt;
# Are you good at sorting useful criticisms from useless ones? &lt;br /&gt;
#* Yes.&lt;br /&gt;
&lt;br /&gt;
===Project===&lt;br /&gt;
&lt;br /&gt;
# Did you select a project from our list? If that is the case, what project did you select? What do you want to especially concentrate on? &lt;br /&gt;
#* I chose to work on the optimization of wml for memory usage problem. &lt;br /&gt;
# Why did you choose this project? &lt;br /&gt;
#* I chose this project because I enjoy working with algorithms and data structures, and, in particular, I enjoy the challenge of finding better ways of doing things. I think that this project will be a chance for me to do that. &lt;br /&gt;
# Include an estimated timeline for your work on the project.&lt;br /&gt;
#* See [[#Timeline|timeline]] below.&lt;br /&gt;
# Include as much technical detail about your implementation as you can &lt;br /&gt;
#* See [[#Technical details|technical details]] below.&lt;br /&gt;
# What do you expect to gain from this project? &lt;br /&gt;
#* I expect to gain experience working with and redesigning a complex data structure. Also, I will get to be mentored by a person with more experience programming (and working on larger projects) which can only improve my own skills.&lt;br /&gt;
# What would make you stay in the Wesnoth community after the conclusion of SOC? &lt;br /&gt;
#* A cookie, chocolate chip preferably.&lt;br /&gt;
&lt;br /&gt;
===Practical considerations===&lt;br /&gt;
&lt;br /&gt;
# Are you familiar with any of the following tools or languages? Subversion, C++, Python, build environments&lt;br /&gt;
#* I am very familiar with C++. I have used subversion enough that I can do the basics, I am not very familiar with creating and merging branches. I only have a little experience with both Python and build environments. With either of these, I currently can only do the most basic tasks.&lt;br /&gt;
# Which tools do you normally use for development? Why do you use them? &lt;br /&gt;
#* Currently, I do almost all of my development in Linux, with a text editor, gdb and other command-line tools. Linux in general just makes development so much easier and the tools it provides are very powerful. In Windows (which I haven't really developed in in almost a year) I use Visual Studio 2005/2008. For debugging I feel it is even better than the tools available in Linux, and it has a few other nice features that may improve my productivity.&lt;br /&gt;
# What programming languages are you fluent in? &lt;br /&gt;
#* I am very fluent in C++, and significantly less so in Java. I have some experience with C and Scheme.&lt;br /&gt;
# What spoken languages are you fluent in? &lt;br /&gt;
#* English.&lt;br /&gt;
# At what hours are you awake and when will you be able to be in IRC (please specify in UTC) &lt;br /&gt;
#* I am generally awake from 1:00pm to 5:00 am UTC and will be available most of that time. &lt;br /&gt;
# Would you mind talking with your mentor on telephone / internet phone? We would like to have a backup way for communications for the case that somehow emails and IRC do fail.&lt;br /&gt;
#* I would not mind that at all.&lt;br /&gt;
&lt;br /&gt;
==Technical details==&lt;br /&gt;
The in-memory storage of WML currently uses a significant amount of memory. Also, the various data structures used often make small memory allocations which can lead to heap fragmentation and even worse memory-efficiency. There are several different ways that we can significantly improve the memory-efficiency of loaded WML.&amp;lt;br&amp;gt;&lt;br /&gt;
There are basically three areas that I intend to optimize for this gsoc project. First is the [[#String Representation|representation of strings]] in loaded WML. Second, the [[#Config Representation|representation of the config class]]. And third, implement a [[#Lazy work|framework]] for both lazy loading and lazy construction of config objects. These three things should all improve the memory-efficiency of loaded WML, but only if some assumptions hold true. For this reason I will also do some in-depth [[#WML Profiling|WML profiling]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String Representation===&lt;br /&gt;
A large part of the memory usage comes from strings(including t_strings). It's highly likely that a lot of these strings are the same (for example, &amp;quot;Id&amp;quot;, &amp;quot;Name&amp;quot;, etc). If enough of these are shared, then a lot of memory could be saved by sharing the string representations. The basic idea here is to have all strings in some global area accessible by an index or pointer. For example, a naive approach would be to just have an unsorted vector of strings and then the actual string representation in the config class would be an index into the vector. The obvious problem with that is that lookup for new strings is slow. Basically, our needs are low memory overhead, fast lookup of new (unknown) strings, fast lookup by &amp;quot;index&amp;quot;, and fast insertion.&amp;lt;br&amp;gt;&lt;br /&gt;
I have a couple ideas of how to do this.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
My primary idea is to use a hash table to store the strings. The difficulty with this is that the basic linear-probing hash table suffers poor performance as the load factor gets high and requires rebuilding with more buckets. The real problem is that a basic hash table is not very memory-efficient. There are a couple of other implementations that would be more memory-efficient. Each of these implementations are efficient at high load factors.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Blocked cuckoo hashing'''&amp;lt;br&amp;gt;&lt;br /&gt;
One variant that would be good for this project is blocked cuckoo hashing, a variant of [http://en.wikipedia.org/wiki/Cuckoo_hashing| cuckoo hashing] where each position in the table can hold some fixed amount of keys. There are several benefits to this implementation. At a very high ( &amp;gt; 99.9% ) load factor this implementation is still efficient and has very little memory overhead. The storage needed for blocked cuckoo hashing can be allocated as one large contiguous block. One downside is that the table has a fixed size and resizing the hash table would be difficult as it requires updating all the indices (the easiest way to do this adds an actra pointer per distinct string). A better option than resizing the table would be to have a backup stash. This could be a simple vector, but it would likely be better for it to be a smaller hash table that more gracefully handles dynamic size requirements.&amp;lt;br&amp;gt;&lt;br /&gt;
More info available [http://www.sciencedirect.com/science?_ob=ArticleURL&amp;amp;_udi=B6V1G-4N56BWF-5&amp;amp;_user=10&amp;amp;_rdoc=1&amp;amp;_fmt=&amp;amp;_orig=search&amp;amp;_sort=d&amp;amp;view=c&amp;amp;_acct=C000050221&amp;amp;_version=1&amp;amp;_urlVersion=0&amp;amp;_userid=10&amp;amp;md5=067aef2a68139cd8694dcdab5d847db3 here] (I was unable to find a free version of this paper).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Move-to-front chaining'''&amp;lt;br&amp;gt;&lt;br /&gt;
In this variant the hash table is an array of linked lists. When we do lookups, the node that we find is moved to the front of its respective list. This move-to-front heuristic makes the hash table very efficient when there is a skew in the distribution of looked up words (as is likely the case with WML). The downside to this method is that it has more memory overhead per distint string (due to the linked list pointer). We could allocate a deque or vector of listnodes so that they aren't each a small allocation (though this makes removing them and reusing that space a bit more complex).&amp;lt;br&amp;gt;&lt;br /&gt;
More info on efficiency of this implementation [http://goanna.cs.rmit.edu.au/~jz/fulltext/ipl01.pdf].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Chaining with dynamic array'''&amp;lt;br&amp;gt;&lt;br /&gt;
Here we replace the linked list with a dynamically sized array. This has a bit less memory overhead but the allocated memory will not be in a single contiguous allocation. Also, in this method is it more difficult to use the move-to-front optimization as it would require updating the indices. Without that optimization, this is likely the least cpu-efficient of the three implementations.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
I believe that the best for this project will be one of the first two (though once one is working it will be quite simple to drop in another as the interfaces are the same).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
For this project, if profiling shows that there is a lot of non-distinct strings as is expected, I will implement at least one of the first two variants. The first has an overhead of at least 32 bits per distinct string(assuming 32 bit size_t) and the second at least 64. Again, profiling will show if it will be worth it.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: Another option for this would be a B-tree with large branching. This will have a bit more overhead than the blocked cuckoo hashing but possible less than the MtF chaining. I do not currently plan to implement this during gsoc, though again it would have the same (or very similar) interface as the hash tables and should be easy to drop in and profile.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last thing with string representation that I will mention is that we can optimize the low level representation of the string. This is currently outside the scope of my gsoc project, though if profiling shows that there is a lot to gain in this area then that could change. I think the best option for this would be to use or adapt an already written lightweight string. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Config Representation===&lt;br /&gt;
Moving a level up from strings we get to the representation of the config class in memory. Currently it is basically&amp;lt;br&amp;gt;&lt;br /&gt;
 struct config {&lt;br /&gt;
     map&amp;lt;string, t_string&amp;gt; attributes;&lt;br /&gt;
     map&amp;lt;string, vector&amp;lt;config*&amp;gt; &amp;gt; children;&lt;br /&gt;
     vector&amp;lt;pair&amp;lt;map&amp;lt;..&amp;gt;::iterator, size_t&amp;gt; &amp;gt; ordered_children;&lt;br /&gt;
 };&lt;br /&gt;
This looks like the equivalent of approximately 5 pointers overhead for each child_config, 2 for each attribute. Also, each config has overhead of about 3 pointers and 3 ints for the maps and vector. On my system, I estimate that is about 70 bytes of overhead per config object and about 15-20 per attribute. This is just a quick estimate, I have not done in-depth profiling yet to determine this.&amp;lt;br&amp;gt;&lt;br /&gt;
We can probably just replace this with two sorted vectors (vector&amp;lt;pair&amp;lt;string_index, t_string&amp;gt; &amp;gt; and vector&amp;lt;string_index, config*&amp;gt;, that is). I believe that, after a config object is built, most operations are lookups and there are only a few insertions and deletions. Without further profiling, I believe that the sorted vectors is the best approach.&lt;br /&gt;
&lt;br /&gt;
==Timeline==&lt;br /&gt;
&lt;br /&gt;
==My contributions to Wesnoth==&lt;br /&gt;
&lt;br /&gt;
====Larger patches and other substantial contributions====&lt;br /&gt;
&lt;br /&gt;
'''unit_map'''&amp;lt;br&amp;gt;&lt;br /&gt;
Originally redesigned this in early 2008 to have iterators that would be updated as a unit is moved and that would know when they become invalidated. Also added some more powerful iterators/accessors.[https://gna.org/patch/?1020][https://gna.org/patch/index.php?1046]&lt;br /&gt;
Recently I have refactored this a bit, templatizing the iterators. Even better, I greatly improved the documentation of the interface. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''gui2 text box history'''&amp;lt;br&amp;gt;&lt;br /&gt;
I added support for text box history to gui2. [http://svn.gna.org/viewcvs/wesnoth?rev=33868&amp;amp;dir_pagestart=250&amp;amp;view=rev]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Profiling and some optimization'''&amp;lt;br&amp;gt;&lt;br /&gt;
I have [http://code.google.com/p/google-perftools/ google performance tools] working with Wesnoth to do some profiling. Originally I set this up as being able to profile memory usage and cpu usage will be important to this project. I have some results of this up at another [[cjhopman_profiling|page]].&amp;lt;br&amp;gt;&lt;br /&gt;
While doing some profiling I found a couple of bottlenecks in the code.&amp;lt;br&amp;gt;&lt;br /&gt;
First, image::locator::locator() was using ~8-10% of the time in-game. I rewrote its lookup to use a hash-based map and cut the time the function used in half. [http://svn.gna.org/viewcvs/wesnoth?rev=34388&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Second, I changed the algorithm that we used to determine what rectangles to redraw. This shows significant gains in some graphics-intensive situations (as much as 3x fps).[https://gna.org/patch/?1141]&amp;lt;br&amp;gt;&lt;br /&gt;
Third, I am doing some work on the tokenizer used for parsing wml that shows a 10-20% speedup of WML loading at the cost of significant complexity. I'm not sure yet that this is worth it without first optimizing the underlying preprocessor stream that the tokenizer gets its input from.&lt;br /&gt;
&lt;br /&gt;
===Smaller changes and bug fixes===&lt;br /&gt;
Report an error when a macro is not resolved and is not a filename.[https://gna.org/patch/?1035]&amp;lt;br&amp;gt;&lt;br /&gt;
Very simple bug fix.[https://gna.org/patch/?1041]&amp;lt;br&amp;gt;&lt;br /&gt;
Prevent duplicate advances_from entries.[http://svn.gna.org/viewcvs/wesnoth?rev=25960&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #13003.[http://svn.gna.org/viewcvs/wesnoth?rev=32849&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #12990.[http://svn.gna.org/viewcvs/wesnoth?rev=32854&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Began to refactor the attack class.[http://svn.gna.org/viewcvs/wesnoth?rev=32952&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug #11031.[http://svn.gna.org/viewcvs/wesnoth?rev=33360&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Fix bug with KNOCKBACK and similar wml.[http://svn.gna.org/viewcvs/wesnoth?rev=33652&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Simplified unit_map lookup by id.[http://svn.gna.org/viewcvs/wesnoth?rev=33956&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;br /&gt;
Improved error message when attempting to dereference invalid iterator.[http://svn.gna.org/viewcvs/wesnoth?rev=34224&amp;amp;view=rev]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cjhopman</name></author>
		
	</entry>
</feed>