1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
|
TODO 0.9:
Tools:
1:
A commit script to run tests, etc. Can also record ohcount stats.
2:
Testutil- maybe- if no output file given, print to stdout, remove the
human-readable option.
Docs:
1:
Turn method/class/fuction names in tutorials to links to the API doc.
Also dates of generation on tutorials - if not through txt2tags, through python
script
2:
INISection::GetName/GetNameSTL isn't mentioned in any tutorial. Perhaps
add it to Getting Started. Or at least add links to INISection API
reference (maybe a Read More section)
3:
Split features on the site, in README and on Launchpad to categories,
such as speed, debugging, etc. With nice HTML on the site so it's
clearly differentiable.
4:
Review tutorials, simplify them, make them more readable, improve them
in general. Use bold/italic, paragraphs to improve readability.
Simplify sentences where possible by removing unnecessary words.
Maybe try to use open text summarizer for help.
To the getting started tutorial, add a better intro - with an about section
, a link to download, etc. getting started also needs to be separated
into more subsections (add sub headers to the code itself part) -
maybe the same with other tutorials.
paragraphs - 3-5 sentences. Use tables when/if needed.
Getting started should also mention asserts, not only warnings,
should be at most ~30 mins and should say at the beginning and/or
in title that we're going to show all functionality needed to use
MiniINI (i.e. stuff like ReadXXX)
5:
Proofread API docs to remove stupid copypaste bugs and improve it.
Learn more about doxygen tags, and maybe use some more of them.
Also make sure everything has basic description in API docs.
Specify where we require arguments to have certain values (e.g.
output buffers have to be allocated)
6:
In the iteration tutorial, mention that GetSection("") won't return NULL
unless we iterate outside the file and that there's an assert for that.
7:
Change all comment, help and doc strings to normal dot ended sentences
TODO 0.10+:
Tools:
1:
Projects for various IDEs and make alternatives.
Move default build system to something else than make.
Probably SCons. Then create a benchmark-extra target.
2:
Tester: provide tests for situations such as NULL buffer passed to LoadBuffer,
non-INI, nonexistent file passed to OpenFile etc.
We also need tests designed specifically to test Allocator.
Maybe even separate testgroup that doesn't even use INIFiles/Sections,
just Allocator directly.
3:
Tester:
Verbosity options: Normal: no MiniINI warnings, minimal info
Verbose: no MiniINI warnings, detailed info
More verbose: MiniINI warnings, detailed info
4:
Makefile:
Benchmark, tester should be non-essential. I.e. if making any of them fails,
emit a warning but make everything else.
5:
A printini tool (binary), that prints all contents of MiniINI,
with chars like \n or EOL emphasized.
6:
Benchmark (no need for bench-extra as it won't cause slowdown') - memory
usage calculations (i.e. sizeof(INIFile) + sizeof(Allocator) + size of
Allocator blocks + INIFile length * (sizeof(INISection *) + sizeof(INISection))
+ (for every INISection) INISection length * sizeof(c *) + size of all globals and
statics. This can't measure bookkeeping bytes, but can still provide
an alternative to Massif measurements. Use measured data to consider
minimizing memory usage by decreasing size of INISection members, global
buffers, both in debug and optimized, measure cache performance after any
optimizations.
- names and tags are stored in allocator, so no need to count them twice
7:
Use a script to replace contents the rulesmd.ini test file by randomly
generated contents with equally long strings
8:
Scripts- try to refactor all XXXGroup functionality to few/one class/es
(maybe put that into a module?) - at least create a base class if possible
Error checking/Debugging:
1:
Modify parseint and maybe other functions to make sure they can work
even on machines where int is 16 or 64 bit. Probably use #ifdef to do that.
2:
Make sure there never are two tags or sections with the same name
(+ warnings). Or at least have the warnings and mention this
in documentation. This will have to wait until current Insert based
sorting is replaced as optimized builds break this functionality.
Interface:
1:
Writing functionality - AddTag, AddSection, DeleteTag, DeleteSection, SetTag
Deleting should be the easiest part, so let's do that first.
Note that deleting sections will need a specific INISection destructor.
The priority should be to get _working_ writing first, fast later. So don't
worry even if every single AddXXX, DeleteXXX, SetXXX results in writing to file.
Maybe SetTag and AddTag should be the same method that adds a new tag if it
doesn't exist.
Speed:
1+:
Sorting idea: When initializing static INISection data, also create
arrays or c* for every char (i.e. 255 of them). These will be used in
bucket sorting like so:
When section loading, every tag goes to bucket with its starting char, and
is sorted using the standard insert method there.
When we're finished, concatenate the buckets to the Tags array.
Implement this and benchmark.
Especially benchmark this on rulesmd2.ini and on arrays (where almost all
elems will go to the same bucket so overhead will be greatest)
2+:
Instead of 4; implement MSD radix sort.
Both 4; and 5; have to be benchmarked on huge array input which should be
slow for the current sort.
3:
ReadStrings code as macro in ReadInts/Floats/Bools might be useful as
there would be no need to create a buffer of pointers to strings, they could be
used directly.
This would get us at best about 4%, usually about 1.5%.
However, it would require removing ParseInts, ParseFloats, ParseBools,
and make code much more of a mess.
Fortunately, most of time wasted is spent on new/delete, which means:
To Allocator, add a special on-demand block, that doesn't get deleted,
but is small and only capable of holding a single buffer at a time.
This removes reallocating complexity as, since there are no other buffers
in the block, we can reallocate freely when we ask for memory.
So create such a block and use it for methods that only allocate memory
once, in a small buffer. This block should never contract, unless it
gets over some size that's considered too much (so when we're loading
multitags with 10000 values, the memory gets freed right away)
- this "too much" size should be relative to file size (5%?),
but at least 64 bytes (usual cache line size)
However, this might not be needed. At first, just use the normal allocator.
Then measure any increases in memory use (as each new buffer gets deleted
right after it's allocated, allocator should quickly delete any new blocks)
Note that this will require changes to allocator's NewSpace, DeleteSpace
methods. Void * might be used as an argument, but templates would probably
be better.
Implement, benchmark.
4:
Try to improve branch prediction in most used functions
Try using __builtin_expect + -freorder-blocks or -O2 .
Also try to decrease cache misses by manual prefetching.
Have to benchmark that with bench-extra to get time, not instruction
count
5:
Optimized string operations (strlen, etc.) as described in strchr.com articles.
Possibly optional code specific for SSE 4.2 .
Optimizations based on Intel optimization manual.
6:
Try using attribute __const__ for pure functions
7:
Optimizations specifically targeting reading small files
(<32kiB, as well as <1kiB) -especially Allocator could handle smaller
files better (allocate less blocks to waste less memory)
Currently, memory usage won't go below 4135 bytes even with an empty
file. It might be possible to halve that.
Refactoring:
Docs:
1:
What MiniINI loads and how (for instance, empty section headers are ignored)
2:
An article about MiniINI parsing process (After sorting gets rewritten)
Web:
TODO 1.0+
Tools:
1-:
Reintroduce profile guided optimization, include in release
Note: Library PGO can use gca files generated by profiling run (although we might
have to set the not-exactly-same-source error to warning)
2?:
Better INISection array benchmark: should search for arrays in a section
by itself (need to find 2 tags starting with the same characters - start
by comparing first char, then another, etc, if we get to a number in multiple
tags starting by the same letter, find 1 and 2, if done, we can assume we
found the array.)
3:
.deb packaging script
4?:
Maybe a simple GUI for test.py (whether to benchmark or compare,
which inifiles to use, etc)
5:
testutil.py:
support for gprof
options for memcheck, cachegrind, callgrind, massif/ms_print
maximum, average heap, stack and bookkeeping bytes from massif out file
rename to a more descriptive script name (other scripts might need that as well)
6-:
dynamic linking
7:
testutil.py:
More detailed stats with bench-extra and possibly run time tests -
i.e. mean, median, average error, measurement errors
8?:
Test.py - possibly- stats about how tag count, etc. affect
execution time, memory use etc. (might need a separate tool) - e.g. does
this value increase execution time linearly? etc.
Error checking/debugging:
1:
warning when whitespace is ignored in a header
warning when [ or ] is detected in a val
warning when there's only ] in line
warning when there are multiple sections/tags with same name
warning when there is [ and ] in wrong order
warning when there is [ and/or ] with name=value separator in the same line
warning when there are characters after ] in a line
warning when there is [ after [
warning when two-more tags/sections with same name and ignore all but the
first one
warning when header is empty
2:
Thread safety
Interface:
1+:
A plain C wrapper, Vala wrapper, maybe a Python wrapper as well
2:
A (template?) generic Read method for serialization, that will construct an
object as long as it has a string constructor. E.g. a template method that
will execute ctor of given type on the referenced variable to write to.
Maybe a corresponding write method as well. This might require more
intelligent whitespace handling - either using double quotes or removing
spaces around tag names and values - the latter isn't impossible, one
possible implementation is to keep a space counter variable, and if we hit a
non-space char after a space sequence., we add that many spaces.
If we hit the end of line, we don't add them. In order to prevent an if check
every character if we've had a space sequence last character we could enter a
separate loop with the first space that will exit at first non-space character.
If done right this could mean overhead only when spaces exist.
Also offer detailed stats, i.e. which items take how much memory.
Speed:
Refactoring:
Docs:
1+:
Write a simple example game using MiniINI (Tetris, Asteroids, Arkanoid clone
or something along those lines)
Web:
1?:
Wiki(once needed, _if_ ever needed)
|