tag:blogger.com,1999:blog-38708019315844604132024-03-12T19:13:00.330-07:00On Software and LanguagesSpeaking up from the Qt ghetto... (on C++, Java, Perl, Python, Haskell?, Erlang??, Systems and Processes)Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.comBlogger133125tag:blogger.com,1999:blog-3870801931584460413.post-54490595844938365462022-11-09T07:29:00.005-08:002023-01-06T05:54:31.551-08:00 Why Qt containers? And do we ❤️ them?<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJEJRos4pVkSqhYhQnWcvQ38-tqQmTIs_UbU5HaT5DciwYpznlrudIwUR13RlQqjSWLJxxHnAuQrv2xLSOgwv6ID_GQ-sfMSR4VH8taLutb-dRM_dzY0ECjrqzWOTYMpeyX85cShBtRKbzTods8kkmyyAE30oFjYT5DUIhpa6u4UNhwwBLvDlPqi0I/s262/qt%20logo%20-%20Big.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="192" data-original-width="262" height="49" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJEJRos4pVkSqhYhQnWcvQ38-tqQmTIs_UbU5HaT5DciwYpznlrudIwUR13RlQqjSWLJxxHnAuQrv2xLSOgwv6ID_GQ-sfMSR4VH8taLutb-dRM_dzY0ECjrqzWOTYMpeyX85cShBtRKbzTods8kkmyyAE30oFjYT5DUIhpa6u4UNhwwBLvDlPqi0I/w67-h49/qt%20logo%20-%20Big.png" width="67" /></a></div><p style="text-align: left;"><span style="font-family: inherit;">I have read the following post titled <i> "I ❤️ Qt containers! :)"</i> on the Qt Development mailing list and found it extremely interesting. It is written by <b>Volker Hilsheimer</b>, the current chief maintainer of the Qt project, and elaborates on some design principles Qt libraries are using. The post was was written as a response to more general question of why isn't Qt switching to standard C++ library containers.<br /></span><span style="font-family: inherit;"><br />I hope nobody gets offended that I repost it here - I do it because not everyone can read the archives. I'd also like to be able to find it for myself in case I'd like to ponder on Qt containers and their design.<br /></span><span style="font-family: inherit;"><span style="font-family: inherit;"><br />So happy reading (emphasizings and formattings are all mine):</span></span></p><div><div><blockquote style="text-align: left;"><span style="font-family: "Times New Roman",serif; font-size: 12pt; mso-ansi-language: DE; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: DE; mso-fareast-theme-font: minor-latin;">" .... </span><span style="font-family: "Times New Roman", serif; font-size: 12pt;">Historically, STL implementations were <b>unusable and unreliable for cross
platform development</b> (we supported HP-UX, AIX, SGI, Sun back in those days),
and generally incomplete (only a few associative containers pre-C++11). So, 30
or 20 years ago, or perhaps up to C++11 and until we could drop commercial Unix
systems as irrelevant (esp for Nokia’s plans; although no idea about the
quality of the STL for Symbian C++), the STL wasn’t really much of an option.</span><div><span style="font-family: "Times New Roman",serif; font-size: 12pt; mso-ansi-language: DE; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: DE; mso-fareast-theme-font: minor-latin;">
<br />
However, this is a more <b>fundamental question </b>about <b>what we try to achieve with
Qt</b>. Qt has never tried to be a C++ library that follows the design principals
of the std library. In many cases, we <b>don’t even care that much </b>about <b>the
single responsibility principle </b>(hello, <i>QWidget</i>). Qt container classes have
always been <b>more than a dumb storage of data</b> on top of which algorithms
operate. <i>QString</i> is a very rich class with tons of functionality, specific to
text handling. <i>std::string </i>is a sequence of characters. Working with <i>QString </i>vs
<i>std::string</i> to deal with user-provided text input requires rather completely
different mindsets.<br />
<br /><b>
Our core competence of designing intuitive APIs</b> does not exclude container
classes. That’s why with Qt containers, we can write<br />
<pre class="brush: cpp">if (list.contains(value)) {
// ...
}
</pre>
rather than<br />
<pre class="brush: cpp">if (std::find(list.begin(), list.end(), value) != list.end()) {
// ...
}
</pre>
Perhaps it makes me an inferior C++ developer, but I rather prefer the former.
Well, <i>std::map</i> got a<i> contains()</i>, and <i>std::string</i> a <i>starts_with()</i> in<b> C++ 20, only
25 years late(r)</b>.<br />
<br />
Indeed, sometimes that convenience means that our users, and we ourselves, can
do something silly like:<br />
<pre class="brush: cpp">if (map.contains(key)) {
value = map.value(key);
// do stuff with value
}
</pre>
Convenience is no excuse for us as developers of Qt to be sloppy. It is also no
excuse for ignoring the new features we get into our toolbox when we move to
C++ 20 or 23. But that C++ 20 finally introduces <i>std::map::contains</i> (but not<i>
std::vector::contains</i>…), or adds <i>std::span</i>, is also <b>no excuse for us to toss
our own designs out of the window</b>, and to demand that all Qt users must embrace
the STL instead.<br />
<br /><b>One of Qt’s goals</b> has always been<b> to make C++ accessible for people that come
from other languages</b>, with a programming model that is not rooted in how the
C++ standard library does things. That programming language used to be Java -
hence our Java-style iterators in Qt containers. Today, people perhaps rather
learn programming with Python in school. There will always be more people that
have learned programming with other languages, than those that have carefully
studied the C++ standard and the impact of various constructs in Compiler
Explorer. We must <b>make it easy for the former, while also enabling the latter.</b><br /><br />
And there are the practical reasons why I don’t want to replace <i>QList </i>with
<i>std::vector</i> and <i>QHash </i>with <i>std::unordered_map</i>: we store our data structures in
the d-pointer, and we want to stay flexbile wrt the actual stored type. So
copy-elision and return-value-optimization don't buy us much: we need to return
copies of containers from our property getters. Not const references to
containers, and not temporary lists that can be moved out. <b>So we do need
reference counting</b>.<br />
<br />
For the here and now, and the last 25 years of Qt and C++, it’s not helpful to
argue that we will soon be able to return a type-erased span and get rid of
“horrible and inefficient” APIs returning owning containers. <i>std::span</i> is a new
tool, opening up new opportunities; the expressiveness of e.g. C++ <i>ranges </i>might
even make it much easier for someone coming from e.g. Python to use Qt, while
allowing us to write much more efficient code. So we do need to consider how we
name and design our APIs today so that we can add new APIs to unlock that power
in the future. And <b>we need to keep looking for ways to improve what we have</b> -
with extra awareness of what potential changes mean for our users and
co-contributors.<br />
<br />
Those improvements cannot require that we force everyone to change significant
amounts of existing code, all the time; or that they have to regularly unlearn
established Qt patterns; or that they have to live without the convenience.
Yes, I’m biased, but<b> I honestly don’t see any universe where a Qt without our
implicitly shared, owning, old-fashioned containers</b>, and instead with only STL
containers and programming paradigms, would have been as easy, or as much fun,
to use.<br /><br />
Volker</span><span style="font-family: "Times New Roman", serif; font-size: 12pt;">"</span> </div></blockquote><div><span style="font-family: inherit; mso-ansi-language: DE; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: DE; mso-fareast-theme-font: minor-latin;"></span><div style="text-align: left;"><span style="font-family: inherit; font-size: x-large; mso-ansi-language: DE; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: DE; mso-fareast-theme-font: minor-latin;">Summing up</span></div><div style="text-align: left;"><span style="font-family: inherit; mso-ansi-language: DE; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: DE; mso-fareast-theme-font: minor-latin;"><br /></span></div><div style="text-align: left;"><span style="font-family: inherit; mso-ansi-language: DE; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: DE; mso-fareast-theme-font: minor-latin;">As it was already said elsewhere, "<i>Qt is known for making C++ easy and accessible"</i>! You might say it's <b>C++ for the people</b>. Maybe it's for that reason that C++ didn't go the way of Haskell despite Commitee's best efforts? 😏<br /></span><div><span style="font-family: inherit; mso-ansi-language: DE; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: DE; mso-fareast-theme-font: minor-latin;"><br /><br /></span></div><span style="font-family: inherit; mso-ansi-language: DE; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: DE; mso-fareast-theme-font: minor-latin;"><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ25-lWskL74uKT_PZa-hT2uAz99zPZybwoOulvzn_Pp7uiAgNQqs347nKB_Q8nhb3CwzsnAPPpYLZxia_CwRHCe0flfwErsvfyVppT6Q31m16Bdcw4zjCFL0Il7r9KE-TQ35I4CMWzX55YxqouD42dXGMAX8hqKK2Z639e5HaiJQbREvdi8ddT4MY/s618/Qt%20and%20performance.PNG" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="319" data-original-width="618" height="264" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ25-lWskL74uKT_PZa-hT2uAz99zPZybwoOulvzn_Pp7uiAgNQqs347nKB_Q8nhb3CwzsnAPPpYLZxia_CwRHCe0flfwErsvfyVppT6Q31m16Bdcw4zjCFL0Il7r9KE-TQ35I4CMWzX55YxqouD42dXGMAX8hqKK2Z639e5HaiJQbREvdi8ddT4MY/w511-h264/Qt%20and%20performance.PNG" width="511" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">A screenshot (I forgot from which presentation...)</td></tr></tbody></table></span></div><div style="text-align: left;"><span style="font-family: inherit; mso-ansi-language: DE; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: DE; mso-fareast-theme-font: minor-latin;"><br /></span></div><div style="text-align: left;"><span style="font-family: inherit; font-size: large; mso-ansi-language: DE; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: DE; mso-fareast-theme-font: minor-latin;">PS:</span><span style="mso-ansi-language: DE; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: DE; mso-fareast-theme-font: minor-latin;"><span style="font-family: inherit;"> I didn't remove anything from the original post for the sake of completeness</span></span></div></div></div><div><br /><br /></div></div>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-10026712246320914722022-09-27T00:36:00.000-07:002022-09-27T00:36:23.458-07:00Guest post - An Extraterrestrial Guide to C++20 Text Formatting <div><br /></div><div>This is a <b>guest post</b> which was written by Victor Zverovich* (aka <a href="https://twitter.com/vzverovich">@vzverovich</a>) for <a href="https://www.cppstories.com/2020/02/extra-format-cpp20.html/">C++ Stories</a> and which I liked so much (not least because of the funny <b>S. Lem</b> references 😀 <b>whose big fan I used to be in my time</b>!) that I asked for permission to repost it here. And so, you can read it here including new, fresh pictures from Stanislaw Lem's works. </div><div><br /></div><div><b>My take</b> on <i>std::format</i>: </div><div><ul style="text-align: left;"><li>you can say what you want about C++20, but it allowed to solve the problems of both <i>iostreams </i>and <i>printf </i>by reusing their strenghts and transcending their limitations!</li></ul></div><div><span style="color: #e69138; font-size: x-small;">>>>> the original text starts here >>>></span></div><div><span style="font-size: x-small;"><br /></span></div><h2 style="text-align: left;"><span>Intro <br /></span><span style="font-size: small;">(with apologies to Stanisław Lem) </span></h2><div><br /></div><div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://upload.wikimedia.org/wikipedia/lv/3/3b/Ijona_Klus%C4%81_ce%C4%BCojumi.jpg" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="800" data-original-width="609" height="400" src="https://upload.wikimedia.org/wikipedia/lv/3/3b/Ijona_Klus%C4%81_ce%C4%BCojumi.jpg" title="Star Diaries, Latvian edition" width="304" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-size: x-small;">Star Diaries, Latvian edition</span></td></tr></tbody></table>Consider the following use case: you are developing the Enteropia<i>[2]</i>-first Sepulka<i>[3]</i>-as-a-Service (SaaS) platform and have server code written in C++ that checks the value of requested sepulka’s squishiness received over the wire and, if the value is invalid, logs it and returns an error to the client. Squishiness is passed as a single byte and you want to format it as a 2-digit hexadecimal integer, because that is, of course, the Ardrite<i>[1]</i> National Standards Institute (ANSI) standard representation of squishiness. You decide to<b> try different formatting facilities</b> provided by C++ and decide which one to use for logging. </div><div><br /></div><div>First you try <i>iostreams</i>:
<pre class="brush: cpp">#include <cstdint>
#include <iomanip>
#include <iostream>
void log_error(std::ostream& log, std::uint_least8_t squishiness) {
log << "Invalid squishiness: "
<< std::setfill('0') << std::setw(2) << std::hex
<< squishiness << "\n";
}
</pre>
The code is a bit verbose, isn’t it? You also need to pull in an additional header, <<i>iomanip></i>, to do even basic formatting. But that’s not a big deal. </div><div><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://img.genial.ly/5e7dbb859bd9860f8a4a0917/5617d7db-863a-477d-a26a-2a338f6d05ca.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="439" data-original-width="800" height="176" src="https://img.genial.ly/5e7dbb859bd9860f8a4a0917/5617d7db-863a-477d-a26a-2a338f6d05ca.png" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-size: x-small;">Ardrites testing</span></td></tr></tbody></table></div><div>However, when you<b> try to test this code </b>(inhabitants of Enteropia have an unusual tradition of testing their logging code), you find out that the code doesn’t do what you want. For example,</div><div><pre class="brush: cpp">log_error(std::cout, 10);
</pre>
prints
<pre class="brush: cpp">Invalid squishiness: 0
</pre>
Which is surprising for two reasons: first it prints one character instead of two and second the printed<br /> value is wrong. After a bit of debugging, you figure out that <i>iostreams </i>treat the value as a character on your platform and that the extra newline in your log is not a coincidence. An even worse scenario is that it works on your system, but not on the one of your most beloved customers. </div><div><br /></div><div>So you add a cast to fix this which makes the code even more verbose (see the code <a href="https://godbolt.org/z/mjeMy4">@Compiler Explorer</a>)
<pre class="brush: cpp">log << "Invalid squishiness: "
<< std::setfill('0') << std::setw(2) << std::hex
<< static_cast<unsigned>(squishiness) << "\n";
</pre>
Can the Ardrites do better than that? </div><div><br /></div><div>Yes, they can. </div><div><br /></div><h2 style="text-align: left;"><span>Format strings </span></h2><div><br /></div><div>Surprisingly, the answer comes from the <b>ancient 1960s</b> (Gregorian calendar) Earth technology, format strings (in a way, this is similar to the story of coroutines). C++ had this technology all along in the form of the <i>printf </i>family of functions and later rediscovered in <i>std::put_time</i>. </div><div><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTFO-B_vSxKQWeBgjhLtcObzyxZUPxXe51k4g&usqp=CAU" style="margin-left: auto; margin-right: auto; text-align: center;"><img border="0" data-original-height="254" data-original-width="199" height="320" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTFO-B_vSxKQWeBgjhLtcObzyxZUPxXe51k4g&usqp=CAU" width="250" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-size: x-small;">Some current Ardrite technology<br /></span></td></tr></tbody></table></div><div>What makes format strings so useful is expressiveness. With a very simple mini-language, you can easily express complex formatting requirements. To illustrate this, let’s rewrite the example above using <i>printf</i>:</div><div><pre class="brush: cpp">#include <cstdint>
#include <cstdio>
void log_error(std::FILE* log, std::uint_least8_t squishiness) {
std::fprintf(log, "Invalid squishiness: %02x\n", squishiness);
}
</pre>
Isn’t it beautiful in its <b>simplicity</b>? Even if you’ve somehow never seen <i>printf </i>in your life, you can learn<br /> the syntax in no time. In contrast, can you always remember which <i>iostreams </i>manipulator to use? Is it <i>std::fill </i>or <i>std::setfill</i>? Why <i>std::setw </i>and <i>std::setprecision</i> and not, say, <i>std::setwidth</i> or <i>std::setp</i>? </div><div><br /></div><div>A lesser-known advantage of <i>printf </i>is <b>atomicity</b>. A format string and arguments are passed to a formatting function in a single call which makes it easier to write them atomically without having an interleaved output in the case of writing from multiple threads. </div><div><br /></div><div>In contrast, with <i>iostreams</i>, each argument and parts of the message are fed into formatting functions separately, which makes synchronization harder. This problem was only addressed in C++20 with the introduction of an additional layer of <i>std::basic_osyncstream</i>.** </div><div><br /></div><div>However, the C <i>printf </i>comes with its set of problems which <i>iostreams </i>addressed: </div><div><ul style="text-align: left;"><li><b>Safety:</b> C <i>varargs </i>are inherently unsafe, and it is a user’s responsibility to make sure that the type of information is carefully encoded in the format strings. Some compilers issue a warning if the format specification doesn’t match argument types, but only for literal strings. Without extra care, this ability is often lost when wrapping <i>printf </i>in another API layer such as logging. Compilers can also lie to you in these warnings. <br /><br /></li><li><b>Extensibility:</b> you cannot format objects of user-defined types with <i>printf</i>. </li></ul></div><div>With the introduction of variadic templates and <i>constexpr </i>in C++11, it has become possible<b> to combine the advantages</b> of <i>printf </i>and <i>iostreams</i>. This has finally been done in <a href="https://en.cppreference.com/w/cpp/utility/format">C++20 formatting facility</a> based a popular open-source formatting library called <i>{fmt}</i>. </div><div><br /></div><h2 style="text-align: left;"><span>The C++20 formatting library</span></h2><div><br /></div><div>Let’s implement the same logging example using C++20 <i>std::format</i>:
<pre class="brush: cpp">#include <cstdint>
#include <format>
#include <iostream>
void log_error(std::ostream& log, std::uint_least8_t squishiness) {
log << std::format("Invalid squishiness: {:02x}\n", squishiness);
}
</pre>
As you can see, the formatting code is similar to that of <i>printf </i>with a notable difference being <i>{}</i> used as delimiters instead of <i>%</i>. This allows us and the parser to find format specification boundaries easily and is particularly essential for more sophisticated formatting (e.g. formatting of date and time). </div><div><br /></div><div>Unlike standard <i>printf</i>, <i>std::format</i> supports positional arguments i.e. referring to an argument by its index separated from format specifiers by the ':' character:
<pre class="brush: cpp">log << std::format("Invalid squishiness: {0:02x}\n", squishiness);
</pre>
Positional arguments allow using the same argument multiple times. </div><div><br /></div><div>Otherwise, the format syntax of <i>std::format</i> which is largely borrowed from Python is very similar to <i>printf</i>’s. In this case format specifications are identical (02x) and have the same semantics, namely, format a 2-digit integer in hexadecimal with zero padding. </div><div><br /></div><div>But because <i>std::format</i> is based on variadic templates instead of C <i>varargs </i>and is fully type-aware (and type-safe), it simplifies the syntax even further by getting rid of all the numerous <i>printf </i>specifiers that only exist to convey the type information. The <i>printf </i>example from earlier<b> is in fact incorrect exhibiting an undefined behaviour</b>. Strictly speaking, it should have been
<pre class="brush: cpp">#include <cinttypes> // for PRIxLEAST8
#include <cstdint>
#include <cstdio>
void log_error(std::FILE* log, std::uint_least8_t squishiness) {
std::fprintf(log, "Invalid squishiness: %02" PRIxLEAST8 "\n",
squishiness);
}
</pre>
Which doesn’t look as appealing. More importantly, the use of macros is considered inappropriate <b>in a civilized Ardrite society</b>. </div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://www.swiatebookow.pl/media/epub_sample_images/54/epub_54116/Images/3bajki_str006.gif" style="margin-left: auto; margin-right: auto; text-align: center;"><img border="0" data-original-height="800" data-original-width="541" height="320" src="https://www.swiatebookow.pl/media/epub_sample_images/54/epub_54116/Images/3bajki_str006.gif" width="216" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-size: x-small;">What's in vogue in the Ardrite society?<br /></span></td></tr></tbody></table><div></div><div>Here is a (possibly incomplete) list of specifiers made obsolete: <i>hh, h, l, ll, L, z, j, t, I, I32, I64, q</i>, as well as<b> a zoo of 84 macros</b>:
<pre class="brush: cpp"> Prefix intx_t int_leastx_t int_fastx_t intmax_t intptr_t
--------------------------------------------------------------------
d PRIdx PRIdLEASTx PRIdFASTx PRIdMAX PRIdPTR
i PRIix PRIiLEASTx PRIiFASTx PRIiMAX PRIiPTR
u PRIux PRIuLEASTx PRIuFASTx PRIuMAX PRIuPTR
o PRIox PRIoLEASTx PRIoFASTx PRIoMAX PRIoPTR
x PRIxx PRIxLEASTx PRIxFASTx PRIxMAX PRIxPTR
X PRIXx PRIXLEASTx PRIXFASTx PRIXMAX PRIXPTR
</pre>
In fact, even <i>x</i> in the <i>std::format</i> example is not an integer type specifier, but a hexadecimal format specifier, because the information that the argument is an integer is preserved. This allows omitting all format specifiers altogether to get the default (decimal for integers) formatting:
<pre class="brush: cpp">log << std::format("Invalid squishiness: {}\n", squishiness);</pre><h2 style="text-align: left;"><span>
User-defined types </span></h2></div><div><br /></div><div>Following a popular trend in the Ardrite software development community, you decide to switch all your code from <i>std::uint_least8_t</i> to something stronger-typed and introduced the <i>squishiness </i>type:</div><div><pre class="brush: cpp">enum class squishiness : std::uint_least8_t {};
</pre>
Also, you decide that you always want to use ANSI-standard formatting of <i>squishiness </i>which will hopefully allow you to hide all the ugliness in <i>operator<<</i>:
<pre class="brush: cpp">std::ostream& operator<<(std::ostream& os, squishiness s) {
return os << std::setfill('0') << std::setw(2) << std::hex
<< static_cast<unsigned>(s);
}
</pre>
Now your logging function looks much simpler:
<pre class="brush: cpp">void log_error(std::ostream& log, squishiness s) {
log << "Invalid squishiness: " << s << "\n";
}
</pre>
Then you decide to <b>add another important piece of information</b>, sepulka security number (SSN) to the log, although you are afraid it might not pass the review because of privacy concerns:
<pre class="brush: cpp">void log_error(std::ostream& log, squishiness s, unsigned ssn) {
log << "Invalid squishiness: " << s << ", ssn=" << ssn << "\n";
}
</pre>
To your surprise, SSN values in the log are wrong, for example:
<pre class="brush: cpp">log_error(std::cout, squishiness(0x42), 12345);
</pre>
gives
<pre class="brush: cpp">Invalid squishiness: 42, ssn=3039
</pre>
After another debugging session, you realize that the<i> std::hex</i> flag is sticky, and SSN ends up being formatted in hexadecimal. So you have to change your overloaded <i>operator<< </i>to
<pre class="brush: cpp">std::ostream& operator<<(std::ostream& os, squishiness s) {
std::ios_base::fmtflags f(os.flags());
os << std::setfill('0') << std::setw(2) << std::hex
<< static_cast<unsigned>(s);
os.flags(f); // restore state!
return os;
}
</pre>
A pretty complicated piece of code just to print out an SSN in decimal format. <br /></div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://olamundo.pl/wp-content/uploads/2014/09/bajki_robotow_daniel_mroz-2.jpg" style="margin-left: auto; margin-right: auto; text-align: center;"><i><img border="0" data-original-height="480" data-original-width="335" height="320" src="https://olamundo.pl/wp-content/uploads/2014/09/bajki_robotow_daniel_mroz-2.jpg" width="223" /></i></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-size: x-small;">A complicated user type waiting to be printed</span></td></tr></tbody></table><div><i>std::format </i>follows a more functional approach and doesn’t share formatting state between the calls. This<b> makes reasoning about formatting easier</b> and brings performance benefits because you don’t need to save/check/restore state all the time. </div><div><div class="separator" style="clear: both; text-align: center;"><br /></div></div><div>To make <i>squishiness </i>objects formattable you just need to specialize the formatter template and you can reuse existing formatters:
<pre class="brush: cpp">#include <format>
#include <ostream>
template <>
struct std::formatter<squishiness> : std::formatter<unsigned> {
auto format(squishiness s, format_context& ctx) {
return format_to(ctx.out(), "{:02x}", static_cast<unsigned>(s));
}
};
void log_error(std::ostream& log, squishiness s, unsigned ssn) {
log << std::format("Invalid squishiness: {}, ssn={}\n", s, ssn);
}
</pre>
You can see the message <i>"Invalid squishiness: {}, ssn={}\n"</i> as a whole, not interleaved with <i><<</i>, which is more readable and less error-prone. </div><div><br /></div><h2 style="text-align: left;"><span>Custom formatting functions </span></h2><div><br /></div><div>Now you decide that you don’t want to log everything to a stream but use <b>your system’s logging API </b><b>instead</b>. All your servers run the popular on Enteropia GNU/systemd operating system where GNU stands for GNU’s, not Ubuntu, so you implement logging via its <i>journal </i>API. Unfortunately, the <i>journal </i>API is very user-unfriendly and unsafe. So you end up wrapping it in a type-safe layer and making it more generic:</div><div><pre class="brush: cpp">#include <systemd/sd-journal.h>
#include <format> // no need for <ostream> anymore
void vlog_error(std::string_view format_str, std::format_args args) {
sd_journal_send("MESSAGE=%s", std::vformat(format_str, args).c_str(),
"PRIORITY=%i", LOG_ERR, nullptr);
}
template <typename... Args>
inline void log_error(std::string_view format_str,
const Args&... args) {
vlog_error(format_str, std::make_format_args(args...));
}
</pre>
Now you can use <i>log_error</i> as any other formatting function and it will log to the system journal:
<pre class="brush: cpp">log_error("Invalid squishiness: {}, ssn={}\n",
squishiness(0x42), 12345);
</pre>
The reason why we don’t directly call <i>sd_journal_send </i>in <i>log_error</i>, but rather have the intermediary <i>vlog_error</i> is to make <i>vlog_error </i>a normal function rather than a template and <b>avoiding instantiations for all the combinations of argument types passed to it***</b>. This dramatically reduces binary code size. <i>log_error </i>is a template but because it is inlined and doesn’t do anything other than capturing the arguments, it doesn’t add much to the code size either. </div><div><br /></div><div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://vignette.wikia.nocookie.net/cyberiada/images/c/c5/Maszyna_matematyczna.jpg/revision/latest/scale-to-width-down/180?cb=20110621174418&path-prefix=pl" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="255" data-original-width="180" height="255" src="https://vignette.wikia.nocookie.net/cyberiada/images/c/c5/Maszyna_matematyczna.jpg/revision/latest/scale-to-width-down/180?cb=20110621174418&path-prefix=pl" width="180" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-size: x-small;">Ardrite custom formatter machine</span></td></tr></tbody></table>The <i>std::vformat </i>function performs the actual formatting and returns the result as a string which you then pass to sd_journal_send. You can avoid string construction with <i>std::vformat</i>_to which writes to an output iterator, but this code is not performance critical, so you decide to leave it as is. </div><div><br /></div><h2 style="text-align: left;"><span>Date and time formatting </span></h2><div><br /></div><div>Finally you decide to log how long a request took and find out that <i>std::format</i> makes it super easy too:</div><div><pre class="brush: cpp">void log_request_duration(std::ostream& log,
std::chrono::milliseconds ms) {
log << std::format("Processed request in {}.", ms);
}
</pre>
This writes both the duration and its time units, for example: </div>
<pre class="brush: cpp">Processed request in 42ms.
</pre>
<div><i>std::format</i> supports formatting not just durations but all <i>chrono </i>date and time types via expressive <a href="https://en.cppreference.com/w/cpp/chrono/system_clock/formatter">format specifications</a> based on <i>strftime</i>, for example:</div><div><pre class="brush: cpp">std::format("Logged at {:%F %T} UTC.",
std::chrono::system_clock::now());</pre><h2 style="text-align: left;">Beyond std::format </h2></div><div><br /></div><div>In the process of developing your SaaS system you’ve learnt about the features of C++20 <i>std::format</i>,</div><div> namely format strings, positional arguments, date and time formatting, extensibility for user-defined types as well as different output targets and statelessness, and how they compare to the earlier formatting facilities. </div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://www.swiatebookow.pl/media/epub_sample_images/54/epub_54116/Images/3bajki_str016.gif" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="800" data-original-width="478" height="320" src="https://www.swiatebookow.pl/media/epub_sample_images/54/epub_54116/Images/3bajki_str016.gif" width="191" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-size: x-small;">Hello Earthlings!</span></td></tr></tbody></table><div><b>Note to Earthlings:</b> your standard libraries may not yet implement C++20 <i>std::format </i>but <span style="font-size: medium;">don’t panic 🚀</span>: all of these features and much more are available in the <a href="https://github.com/fmtlib/fmt">open-source <i>{fmt}</i> library</a>. Some additional features include: </div><div><ul style="text-align: left;"><li>formatted I/O
high-performance </li><li>floating-point formatting </li><li>compile-time format string checks </li><li>better Unicode support </li><li>text colors and styles </li><li>named arguments </li></ul></div><div>All of the examples will work in <i>{fmt}</i> with minimal changes, mostly replacing <i>std::format </i>with <i>fmt::format</i> and <i><format></i> with <i><fmt/core.h> </i>or other relevant include. </div><div><br /></div><h2 style="text-align: left;"><span>More about std::format </span></h2><div><br /></div><div>If you like to read more about <i>std::forma</i>t here are some good resources: </div><div><ul style="text-align: left;"><li><a href="https://www.modernescpp.com/index.php/std-format-in-c-20"><i>std::format </i>in C++20 - ModernesCpp.com</a> </li><li><a href="https://madridccppug.github.io/posts/stdformat/">String formatting the cool way with C++20 <i>std::format() </i>- Madrid C/C++ </a></li><li><a href="https://www.patreon.com/posts/61059579"><i>std::format </i>and Custom Types (~1500 words) - C++ Stories Premium</a></li><li>(mrkkrj) and, of course, the original Text Formatting proposal: <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0645r10.html">P0645R10</a>!<br /><br /></li></ul></div><h2 style="text-align: left;"><span>Glossary</span> </h2><div><b><br />[1] </b>Ardrites – intelligent beings, polydiaphanohedral, nonbisymmetrical and pelissobrachial, belonging to the genus Siliconoidea, order Polytheria, class Luminifera. </div><div><b>[2] </b>Enteropia – 6th planet of a double (red and blue) star in the Calf constellation</div><div><b>[3]</b> Sepulka – pl: sepulki, a prominent element of the civilization of Ardrites from the planet of Enteropia; see “Sepulkaria” </div><div><b>[4]</b> Sepulkaria – sing: sepulkarium, establishments used for sepuling; see “Sepuling” </div><div><b>[5]</b> Sepuling – an activity of Ardrites from the planet of Enteropia; see “Sepulka” </div><div><br /></div><div>The picture and references come from the book <a href="https://en.wikipedia.org/wiki/The_Star_Diaries">Star Diaries</a> by Stanislaw Lem. <br /></div><div><br /></div><div style="text-align: left;"><span style="color: #e69138; font-size: x-small;">>>>> and here ends the original text... >>>></span></div><div><span style="font-size: small;"><br /></span></div><h2 style="text-align: left;">C++23 improvements </h2><div><br /></div><div>(Added by Bartlomiej Filipek, aka <a href="https://twitter.com/fenbf">Bartek</a> 🙂): </div><div><br /></div><div><i>std::format</i> doesn’t stop with C++20. The ISO Committee and C++ experts have a bunch of additions to this powerful library component. Here’s a quick overview of changes that we’ll get****:</div><div><ul style="text-align: left;"><li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2216r3.html">P2216R3: <i>std::format</i> improvements</a><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2216r3.html"> </a>- improving safety via compile-time format string checks and also reducing the binary size of format_to. This is implemented as Defect Report against C++20, so compiler vendors <b>can implement it earlier than the official C++23 Standard</b> will be approved! </li><li><a href="https://github.com/cplusplus/papers/issues/884">P2093 Formatted output</a> - a better, safer and faster way to output text!
<i>std::print("Hello, {}!", name);</i>. </li><li>possibly in C++23:<a href="https://github.com/cplusplus/papers/issues/977"> P2286 Formatting Ranges</a> - this will add formatters for ranges, tuples and pairs. </li></ul></div><div>As you can see, a lot is going on in this area! </div><div><div><br /></div><div><h2><span>Artworks</span> </h2></div><div><br /></div><div><div><div>Victor* originally wrote that guest blog post for <a href="https://www.fluentcpp.com/2018/12/04/an-extraterrestrial-guide-to-c-formatting/">Fluent C++</a>, then this one on <a href="https://www.cppstories.com/2020/02/extra-format-cpp20.html/">C++ Stories</a>, updated with information about C++20. I just reposted that later version, but also added some of <b>Daniel Mróz's iconic illustrations</b> for S. Lem's <a href="https://en.wikipedia.org/wiki/The_Cyberiad">Cyberiad</a> and <a href="https://en.wikipedia.org/wiki/Fables_for_Robots">Fables of Robots</a> books.</div></div><div><br /></div><div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody><tr><td style="text-align: center;"><a href="https://userscontent2.emaze.com/images/daed02e8-f13a-4956-976d-7327db8547f0/f718026b-961b-492b-bfd4-527237045818" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto; text-align: center;"><img border="0" data-original-height="480" data-original-width="306" height="320" src="https://userscontent2.emaze.com/images/daed02e8-f13a-4956-976d-7327db8547f0/f718026b-961b-492b-bfd4-527237045818" width="203" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-size: x-small;">Fables of Robots in original</span></td></tr></tbody></table><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody><tr><td style="text-align: center;"><a href="https://images-na.ssl-images-amazon.com/images/I/71F3E5BZ09L.gif" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto; text-align: center;"><img border="0" data-original-height="475" data-original-width="284" height="320" src="https://images-na.ssl-images-amazon.com/images/I/71F3E5BZ09L.gif" width="197" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-size: x-small;">The Cyberiad in German</span></td></tr></tbody></table><br /><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody><tr><td style="text-align: center;"><a href="https://bomega.pl/wp-content/uploads/2021/02/Robotimuinasjutud_kaaned_s.jpg" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto; text-align: center;"><img border="0" data-original-height="800" data-original-width="568" height="200" src="https://bomega.pl/wp-content/uploads/2021/02/Robotimuinasjutud_kaaned_s.jpg" width="142" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-size: x-small;">Fables of Robots: <br />the new illustrations <br />for an Estonian edition</span></td></tr></tbody></table></div><div class="separator" style="clear: both; text-align: center;"><div style="text-align: left;"></div></div><div style="text-align: center;"><div style="text-align: left;"> </div></div><div>I know, I know... - these aren't about sepuling, sepulkaria and Ardrites, but the Ion Tichy stories didn't have illustrations as I read them. On the other side, the works of <a href="https://en.wikipedia.org/wiki/Daniel_Mr%C3%B3z">Daniel Mróz</a> are simply out of this world<span style="font-size: x-small;"> <span>🚀</span></span>! Thus I took a littlte bit of <i>licentia poetica</i> and misused robot images to represent Ardrites and their life. I hope you won't be mad with me because it conveys a kind of sci-fi feeling this guest post needed.</div><div><br /></div><div>Now, this is the end, at last!</div><div><br /></div><div><div><span style="font-size: large;">PS:</span> I found the illustrations on internet, so <b>should the links disappear, please let me know</b>!!!<br /><br /></div></div></div><div> --</div><div> * <b>Victor Zverovich</b> is a software engineer at Facebook working on the <a href="https://github.com/facebook/fbthrift">Thrift RPC</a> framework and the author of the popular <i>{fmt}</i> <a href="https://github.com/fmtlib/fmt">library</a>, a subset of which is proposed into C++20 as a new formatting facility. He is passionate about open-source software, designing good APIs, and science fiction.You can find Victor online on <a href="https://twitter.com/vzverovich">Twitter</a>, <a href="https://stackoverflow.com/users/471164/vitaut">StackOverflow</a>, and <a href="https://github.com/vitaut">GitHub</a>.</div><div><br /></div><div> ** C++20 <a href="https://en.cppreference.com/w/cpp/io/basic_osyncstream">std::osyncstream</a> will:<br /><blockquote><i>"std::osyncstream(<a href="http://en.cppreference.com/w/cpp/io/cout">std::cout</a>) << "Hello, " << "World!" << '\n';</i><br /><br />...provide the guarantee that all output made <b>to the same final destination buffer</b> (<i>std::cout</i> in the examples above) will be <b>free of data races</b> and will <b>not be interleaved or garbled in any way</b>, as long as every write to the that final destination buffer is made through (possibly different) instances of <i>std::basic_osyncstream</i>."</blockquote></div></div>See, <b>I learned something new</b>!!! Reading blogposts is helpful!<div><span style="background-color: #fcff01;"><br /></span></div><div>*** As stated in <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0645r10.html">P0645R10</a>:<span><br /><span style="background-color: white;"><blockquote>"<b>Exposing the type-erased AP</b>I rather than making it an implementation detail and only providing variadic functions allows applying the <b>same technique to the user code</b>." 👍</blockquote></span></span></div><div>**** pending C++23 format improvements: </div><div><ul><li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2216r3.html">P2216(R3</a>): checking of format strings in compile-time (metaprogramming FTW!)<br /><br /></li><li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2093r1.html">P2093(R1</a>):<br /><b>a)</b> using <i>std::print(...) </i> instead of <i>std::cout << std::format(...) </i>- because it:<br /><blockquote> "avoids allocating <b>a temporary</b> <i>std::string </i>object and calling <i>operator<<</i> which performs formatted I/O on text that is already formatted. The number of function calls is reduced to one which, together with <i>std::vformat</i>-like <b>type erasure</b>, results in much smaller binary code" !!!</blockquote><b>b)</b> support for Unicode strings, like: <i>std::print("Привет, κόσμος!") <=> printf("Hello world!") </i><br /></li></ul>All in all, this will add the open points Victor complained about it his post here: <a href="https://www.zverovich.net/2019/07/23/std-format-cpp20.html">std::format in C++20</a>!</div><div><br /></div>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-16809348348492483442022-08-26T07:09:00.001-07:002022-08-29T02:19:38.090-07:00Do we need the Y-combinator in C++?<br />
<div style="border-image: none 100% / 1 / 0 stretch;">
<a href="https://2.bp.blogspot.com/--ZGmV662BB0/V5hl-FFfYZI/AAAAAAAAAUk/jfx7EQ_y15A9F0UJxzzIMDsFXlfsvUs0gCPcBGAYYCw/s1600/haskel%2Blogo.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="80" data-original-width="80" src="https://2.bp.blogspot.com/--ZGmV662BB0/V5hl-FFfYZI/AAAAAAAAAUk/jfx7EQ_y15A9F0UJxzzIMDsFXlfsvUs0gCPcBGAYYCw/s1600/haskel%2Blogo.png" /></a>You may (or may not...) have heard of the Y-combinator <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0200r0.html">proposal</a> for the C++ standard library. If you are like me, then you may have been asking yourself <b>why should we need such a thing in C++</b>? Is that because of the current functional programming fad? Keeping up with the (programming-) Joneses? At that point you probably shrugged and went on with your life (like me)...</div>
<br />
But then I met with a similar problem in some template metaprogramming contexts ans I think it is worth a separate blogpost. So I started writing this post... back in 2017 and finished it only now (2022) 😐.<div><br /></div><div><span style="font-size: large;">Y-What???</span></div><div><span style="font-size: large;"><br /></span><span style="font-size: large;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiXjvoDp44LnKy20pobjTQd43Ss2UKNdiYqPOOY6yXR_xz3iYNN8IWElQ0ZN-5W2XIJzLWMkSzA5YDsMenOZlenr5b8Insz3Pwr7eeoFsbcLWaKwSKTuNB3Pq8OFKEXKYyOlehHEXXBClP4ros71Y63b0pEdOASzyQunT41WHRZSiNaI_V7xPzL20yi=s400" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="400" height="72" src="https://blogger.googleusercontent.com/img/a/AVvXsEiXjvoDp44LnKy20pobjTQd43Ss2UKNdiYqPOOY6yXR_xz3iYNN8IWElQ0ZN-5W2XIJzLWMkSzA5YDsMenOZlenr5b8Insz3Pwr7eeoFsbcLWaKwSKTuNB3Pq8OFKEXKYyOlehHEXXBClP4ros71Y63b0pEdOASzyQunT41WHRZSiNaI_V7xPzL20yi=w72-h72" width="72" /></a></div></span>
So let us start with a question: what is the Y-combinator exactly? Do not fear, I won't be citing Wikipedia or some heavy CS-volume, I'll tell you just what it is, as it is. Shortly, it is a device (or more like - a trick) <b>to add recursion to languages which does not support it natively</b>. <br />
<br />
It originates from lambda calculus - this, in its turn is a simple formalization of the notion of mathematical function. And lambda calculus does not have (BTW: did you notice that in modern days you have to know more and more of the CS-gibberish as working programmer?) recursion: a function can call another functions, as this is all that got formalized (see above). No looping there... You cannot loop when everything you have is function call with some parameters. Or can you?<br />
<br />
The inventor of lambda calculus didn't think so, but his PhD student (some guy called, <b>that's not a joke (!!!)</b>, Haskell Curry*) disabused him of that notion - he found the trick. We don't want to discuss it here (this post isn't about lambda calculus** in the end!) but you will maybe get a feeling of it after you have seen the C++ implementation.<br />
<br />
<span style="font-size: large;">Why in C++?</span><br />
<br />
Ok, the Y-combinator stuff is clear now, but why do we need in in C++? AFAIK we have recursion in C++, by Jove, we even are blessed with iteration! Not so fast young Padawan, there is a context in the language where this is not true. Guess what... Of course, the lambdas.<br />
<br />
<b>The problem is, that we cannot refer to the current lambda in its body.</b> When you try <i>*this</i>, this will give you the captured context class - does it ring a bell? Yes, thats the situation we have in Javascript's callbacks! So what can we do about it? in Javascript you just save the value of <i>this</i> in the <i>self</i> variable and forward it to the function. Can we do that in C++ too?<br />
<br />
Well, not really: we'd need the type of lambda to declare a pointer to it, to be given in it's constructor... You see, it's a vicious circle :-/. Loosely typed languages escape this predicament by just not typing anything, but what can we do with our oldskool C++ type system?<br />
<br />
<div class="separator" style="border-image: none 100% / 1 / 0 stretch; clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-0oVCH3_UNK8/Tw34wz-ULsI/AAAAAAAAAJs/jjIOp4qtZsIVg8J1brM3s1gZt53hM1ATQCPcBGAYYCw/s1600/cpp.gif" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="32" data-original-width="32" src="https://2.bp.blogspot.com/-0oVCH3_UNK8/Tw34wz-ULsI/AAAAAAAAAJs/jjIOp4qtZsIVg8J1brM3s1gZt53hM1ATQCPcBGAYYCw/s1600/cpp.gif" /></a></div>
<div style="border-image: none 100% / 1 / 0 stretch;">
First, we could request a new language feature - why not? It's so obvious, that somebody even tried to do this (guess who?***):</div>
<pre class="brush: cpp"> auto foo = [] self (int x) -> int
{
if(x == 0)
return 0;
else
return self(x - 1);
}
</pre>
Here there is additional "parameter" in lambda's definition (i.e. <i>self</i>) that can be used inside of the lambda. But as Bjarne is known to dislike solutions which require a new language features if the problem can be solved in library <span style="font-size: x-small;">(written 2017)</span><span style="font-size: small;"> </span>, the question is: can we have a workaround for this?</div><div>
<br />
<span style="font-size: large;">How?</span><br />
<br />
The easy way is to use <i>std::function</i> to wrap the lambda. As it uses type erasure, there's no need for the exact type and thus we can duplicate the solution of loosely typed languages! Here is the xample code from the proposal:</div><div>
<pre class="brush: cpp"> std::function<int(int, int)> gcd = [&](int a, int b)
{
return b == 0 ? a : gcd(b, a % b);
};
// use:
int res = gcd(20, 110); </pre>
Bingo? Not really, this solution shares one weekness with dynamically typed languages -<b> it sucks at performance</b>! Why's that? I won't discuss it in detail here, let it be enough to say that <i>std::function</i> generally isn't by any means a paragon of performance.<br />
<br />However, <b>we can work around the problem</b> by just defining a, let's call it, "almost"-lambda, and then invoking it form the outside passing its own reference as one of the parameters! But how would that look like? Show me the code! Voila, here is an example implementation for a left fold of a sequence using lambdas:<br />
<pre class="brush: cpp">template <typename Acc, typename F, typename... T>
// wrapper
constexpr auto foldLeft(F func, Acc acc, T... xs)
{
// the "almost"-foldLeft-lambda
auto step = [=](auto self, auto acc_, auto x_, auto... xs_)
{
// calculation
auto sum = func(acc_, x_);
// recursion?
if constexpr(sizeof...(xs_) != 0)
return self(self, sum, xs_...);
else
// finish
return sum;
};
// result: the fully recursive lambda!
return step(step, acc, xs...);
}
</pre>If you pay attention to the comments and give it a little thought, this code should be clear enough. Now let us test it:<pre class="brush: cpp"> #include <iostream>
int main()
{
std::cout << "sum 1,2,3,4,5 = "
<< foldLeft([](int a, int b) { return a + b; },
0,
1,2,3,4,5);
std::cout << "\nfact 1,2,3,4,5 = "
<< foldLeft([] (int a, int b) { return a * b; },
1,
1,2,3,4,5);
}
</pre>
<div>and indeed we get the following output:</div><div>
<pre> sum 1,2,3,4,5 = 15
fact 1,2,3,4,5 = 120
</pre>
<div>Good, seems to be working!</div><div><br /></div><div><span style="font-size: large;">Abstracting things away? </span></div></div><br />As programmers, we are are trying to separate the functionalities for sake of code clarity. Could we somehow abstract away this whole business of forwarding the reference to self? As it seems, this is possible with followintg trick:</div><div>
<pre class="brush: cpp"> #include <utility>
template<class F>
struct y_combinator_impl
{
F func; // recursive lambda (taking self as 1st parameter)
template<class...Args>
decltype(auto) operator()(Args&&...args) const
{
// forward the reference to self when called!
return func(*this, std::forward<Args>(args)...);
}
};
template<class F>
y_combinator_impl<std::decay_t<F>> make_y_combinator(F&& func)
{
return {std::forward<F>(func)};
};
</pre><b>
The trick here is that </b>we do not forward the reference of a lambda directly, but use a plain, old C++ class wrapping the lambda instead! Out of a sudden we have no problems whatsoever with getting a reference of the recursive function object! Problem solved using an additonal level of abstraction! 🙂 </div><div><br /></div><div>With the above code we can simplify our implementation of left fold as follows:
<pre class="brush: cpp">template <typename Acc, typename F, typename... T>
constexpr auto foldLeft(F func, Acc acc, T... xs)
{
// the "almost"-foldLeft-lambda
auto step = [=](auto self, auto acc_, auto x_, auto... xs_)
{
auto sum = func(acc_, x_);
if constexpr(sizeof...(xs_) != 0)
// simplify: no passing of self-reference needed!
return self(sum, xs_...);
else
return sum;
};
// "bless" the almost-lambda, invoke it with arguments
return make_y_combinator(step)(acc, xs...);
}
// use:
std::cout << "sum 1,2,3,4,5 = "
<< foldLeft([](int a, int b) { return a + b; },
0,
1,2,3,4,5);
</pre>
In fact, we can simplify it even further:
<pre class="brush: cpp"> auto almost_lfold = [=](auto self, auto func, auto acc_, auto x_, auto... xs_)
{
auto sum = func(acc_, x_);
if constexpr(sizeof...(xs_) != 0)
return self(func, sum, xs_...);
else
return sum;
};
auto fold_left = make_y_combinator(almost_lfold); // curried with "almost_lfold"!
// use:
std::cout << "sum 1,2,3,4,5 = "
<< fold_left([](int a, int b) { return a + b; },
0,
1,2,3,4,5);
</pre>
Now the trick becoms even clearer - the <i>make_y_combinator()</i> function call only wraps the lambda in a plain, old C++ class and leaves the call operator <b>unspecified at first</b>. Only when the call operator is invoked, will it be generated from its template specification, thus leaving us with the impression of a preexisting curried function. Nice!<br /><br /></div><div><div><span style="font-size: large;">The proposal</span></div><div><br />The proposal we mention (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0200r0.html">P0200R0</a>) includes following example implementation of the Y combinator:</div><div>
<pre class="brush: cpp"> template<class Fun>
class y_combinator_result {
Fun fun_;
public:
template<class T>
explicit y_combinator_result(T &&fun): fun_(std::forward<T>(fun)) {}
template<class ...Args>
decltype(auto) operator()(Args &&...args) {
return fun_(std::ref(*this), std::forward<Args>(args)...);
}
};
template<class FunT>
decltype(auto) y_combinator(Fun &&fun)
{
return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}
</pre>
On a cursory look upon it, we can see that its <i>std::y_combinator() </i>function corresponds to our <i>make_y_combinator() </i>and the <i>std::y_combinator_result </i>class to our <i>y_combinator_impl </i>structure with the applied technique being exactly the same. After having understood our home-made implementation from above, we shouldn't have any problems reading the example implementation from the proposal!<br /><br />Let us finally show the recursive lambda example used in the proposal. The code follows below:</div><div>
<pre class="brush: cpp"> auto almost_gcd = [](auto gcd, int a, int b) -> int
{
return b == 0 ? a : gcd(b, a % b);
};
auto gcd = std::y_combinator(std::ref(almost_gcd));
std::cout << gcd(20, 30) << std::endl;
</pre>
Here you can see the pattern present in all the explanations of the Y combinator - first we define an "almost" implementation, then we "bless" it with the Y combinator and voila, the recursion is automagically there!<br /><br /></div>
<div>OK, next let us try and find out if the above example can be written with our home-made code for Y combinator:</div><div>
<pre class="brush: cpp"> // lambda from the proposal:
auto almost_gcd = [](auto gcd, int a, int b) -> int
{
return b == 0 ? a : gcd(b, a % b);
};
// use our own impl. to "bless" it
auto gcd = make_y_combinator(std::ref(almost_gcd));
// test:
std::cout << "\ngcd 20,30 = " << gcd(20, 30) << std::endl;
std::cout << "\ngcd 77,122 = " << gcd(77, 122) << std::endl;
</pre></div><div><div>and indeed we get the following output:</div><div>
<pre> gcd 20,30 = 10
gcd 77,122 = 11
</pre>
<div>Seems to be working too, cool!</div></div></div><div><br /></div>
<div>
<span style="font-size: large;">Needed?</span></div>
<div><br /></div><div>Now, at last we can respond to the question we posed in the title - do we really need the Y combinator in C++? The short answer is:<b> it depends</b>. The longer answer is: <b>maybe</b>. The long answer follows below.</div><div><br /></div><div>To begin with, passing the <i>self </i>parameter down in the recursion isn't that difficult. We can even get more into functional programming style and write the <i>foldLeft </i>example as follows****:</div><div><br /></div><div>
<pre class="brush: cpp">template <typename Acc, typename F, typename... T>
constexpr auto foldLeft(Acc acc, F func, T... xs)
{
auto step = [=](auto self)
{
return [=](auto acc_, auto x_, auto... xs_)
{
auto sum = func(acc_, x_);
if constexpr(sizeof...(xs_) != 0)
return self(self)(sum, xs_...);
else
return sum;
};
};
return step(step)(acc, xs...);
}
</pre><div>Depending on your background this style can be more or less eaysy on your eyes (admittedly the <i>self(self)</i>/<i>step(step)</i> syntax can look pretty confusing at first 😨). What we are doing here is to define <b>a lambda returning a lambda</b> and then first call the outer lambda to access the inner lambda and call it in its turn. Calling the outer lambda with a parameter is what we call currying in functional languages like Haskell (Haskell's curry anyone? 😉).</div><div><br /></div><div>From this perspective the answer is <b>a maybe</b>, because the Y combinator takes care of passing the <i>self </i>parameter down in the recursion, provided, of course, you know what a Y combinator is. The problem is, not many imperative programmers seem to know that. Maybe <i>recurse() </i>would be a better name for it? </div></div><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSfMvZwf6fhJS7zwI8obCtSJNT7mBQi-3VKTVbIr64U9sHITzVpt8MoY9WTLYP763jQP3CnURkliPjnWWyhN-2QFx3iMkcmMRYf6v5O_YORH7o2hwdgRykTX7ceiymBN0W397G9Zc8HDPRC1PFpdOVLBnI9rfiaS7z0A1Zfj27fkXEaTCTvm6ou9lV/s32/cpp.gif" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="32" data-original-width="32" height="32" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSfMvZwf6fhJS7zwI8obCtSJNT7mBQi-3VKTVbIr64U9sHITzVpt8MoY9WTLYP763jQP3CnURkliPjnWWyhN-2QFx3iMkcmMRYf6v5O_YORH7o2hwdgRykTX7ceiymBN0W397G9Zc8HDPRC1PFpdOVLBnI9rfiaS7z0A1Zfj27fkXEaTCTvm6ou9lV/s1600/cpp.gif" width="32" /></a></div>
In C++23, however, we will have an entire new situation! As it seems, will wil get a new language feature: the "Deducing <i>this</i>". As stated in the recent <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html">P0847R7</a> proposal, we can now (as its side-effect) implement recursive lambdas like that:<br />
<pre class="brush: cpp"> // this proposal
auto fib = [](this auto self, int n) {
if (n < 2) return n;
return self(n-1) + self(n-2);
};
</pre>
So you have it - in C++23 we <b>don't need it al all!</b> </div><div><br /></div><div>So the second answer is then <b>it depends</b>, namely, it depends on what C++ version you are using... Admittedly, the syntax of the of the above recursive lamba maybe isn't that self-explaining, but as this one is already getting too long, I will defer discussion of <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html" style="font-family: serif;">P0847</a> to a separate post. See you there!</div><div><br /></div><div><span style="font-size: large;">PS:</span> Get the code to play with from this Github gist:<a href="https://gist.github.com/mrkkrj/712ad5c1e6cfb6d91262b3582bd691a6"> https://gist.github.com/mrkkrj/712ad5c1e6cfb6d91262b3582bd691a6</a></div><div><br />
--<br />
* he's name should rather be Curry Haskell or Currying Haskell or Haskell "Is-By-Default" Curried! 😊<br /><br />
** you can read about lambda calculs and C++ here: <a href="https://yongweiwu.wordpress.com/2014/12/14/y-combinator-and-cplusplus/">https://yongweiwu.wordpress.com/2014/12/14/y-combinator-and-cplusplus/</a><br /><br />
*** yes, you guessed it: proposal <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0200r0.html">P0200R0</a> (<i>Add Y Combinator to the Standard Library</i>), but only as a side note. Also a separate proposal allowing just that existed: <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0839r0.html">P0839R0</a> (<i>Recursive lambdas</i>)<br /><br /></div><div>**** <a href="https://stackoverflow.com/questions/35608977/understanding-y-combinator-through-generic-lambdas">https://stackoverflow.com/questions/35608977/understanding-y-combinator-through-generic-lambdas</a></div><div><br /></div><div><br /></div>
</div>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-51229505076447306062022-06-30T05:42:00.003-07:002022-07-07T02:58:36.378-07:00Some praise for my Qt book<p style="text-align: left;"></p><div style="text-align: right;"><div style="text-align: justify;"><div class="separator" style="clear: both; text-align: justify;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjebV_XP1NjQZNdpjLyMHzg6pJA7_06KdBxDkoy5GszgpCxG3_BM2oSXl8yNqQznXp4c60Co2MCRT6UAQreaZlznIk0pEoAjDvLQojFfSJUTJRknMmY46-faDUVIic9PvHQse1BxgTLTPZGLIXkSL8PRRvVYg3o0oSlLi2l2ga4p7JQTWVA41qQhNx5/s686/cover%20frontside.jpg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="686" data-original-width="548" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjebV_XP1NjQZNdpjLyMHzg6pJA7_06KdBxDkoy5GszgpCxG3_BM2oSXl8yNqQznXp4c60Co2MCRT6UAQreaZlznIk0pEoAjDvLQojFfSJUTJRknMmY46-faDUVIic9PvHQse1BxgTLTPZGLIXkSL8PRRvVYg3o0oSlLi2l2ga4p7JQTWVA41qQhNx5/w137-h173/cover%20frontside.jpg" width="137" /></a></div><span style="text-align: left;">You might perhaps already know that I recently wrote a </span><a href="https://www.packtpub.com/application-development/hands-high-performance-qt" style="text-align: left;">book</a><span style="text-align: left;"> (blogged about it </span><a href="https://ib-krajewski.blogspot.com/2019/02/holy-cow-i-wrote-book.html" style="text-align: left;">here</a><span style="text-align: left;">)! </span><span style="text-align: left;">In the book I discussed various </span><b style="text-align: left;">general program performance topics</b><span style="text-align: left;"> but also some more specific, Qt related ones, for example</span><b style="text-align: left;"> Qt's graphical</b><span style="text-align: left;"> or </span><b style="text-align: left;">networking performance</b><span style="text-align: left;">.</span></div></div></div> <div>Recently I was very happy (and very surprozed) to have read some kind words about my book, and <b>I just wanted to show off a little</b> 😇 and cite them here. So let's start!</div><div><br /></div><div>First Ivica* mentioned he had my book, and it wouldn't be that bad:<br /><br /></div><div>
<blockquote class="twitter-tweet"><p dir="ltr" lang="en">Some kind words from Ivica (and he knows his stuff!) 🥳😀 <a href="https://t.co/yYA1xGyJnf">https://t.co/yYA1xGyJnf</a></p>— qt5_performance_book (@BookQt5) <a href="https://twitter.com/BookQt5/status/1492065798239760384?ref_src=twsrc%5Etfw">February 11, 2022</a></blockquote> <script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script><div><br /></div>
After I thanked him, he said he actually liked it!</div><div><br /><blockquote class="twitter-tweet"><p dir="ltr" lang="en">I think it is a very good read for an intermmediate/advanced C++ developer, and definitely much more useful than learning about the newest features of C++20.</p>— Ivica Bogosavljevic (@i_bogosavljevic) <a href="https://twitter.com/i_bogosavljevic/status/1492085794764464128?ref_src=twsrc%5Etfw">February 11, 2022</a></blockquote> <script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script><br />What I was particularly pleased about is (beside the <i>"well written"</i> phrase) that:</div><div><ul style="text-align: left;"><li><i>95% ... can be applied to other frameworks</i></li><li><i>very good read for intermediate/advanced C++ developer</i></li></ul></div><div>Why? Because all of that were my goals when writting the book, so I can congratulate myself on a good job! What can I say,<b> thanks a lot, Ivica!<br /><br /></b></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4mujcZGM5_nAD4F36eGxDug5WqehlN1XPKMYFy_mZsQ_C487x7qI38xiZGEHemEL9lnlS-zpxaPHo3EAknxTrOAyn8KohzJ5s0Ouyw2c7cZ4-t5sUolMIy-NtirFQTTNCyivGV4Ruh7EG6UZWN45ZRR1En5Y5Cjba0Tygf-qIdL0o6RxT3qJLYu3h/s400/th.jpg" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="400" data-original-width="256" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4mujcZGM5_nAD4F36eGxDug5WqehlN1XPKMYFy_mZsQ_C487x7qI38xiZGEHemEL9lnlS-zpxaPHo3EAknxTrOAyn8KohzJ5s0Ouyw2c7cZ4-t5sUolMIy-NtirFQTTNCyivGV4Ruh7EG6UZWN45ZRR1En5Y5Cjba0Tygf-qIdL0o6RxT3qJLYu3h/w205-h320/th.jpg" title="Thank you!" width="205" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Thank you!</td></tr></tbody></table><div><br /></div><div>You may ask what the book was about, really? Let's have a look:<br /><ul style="text-align: left;">
<li><b>Part I - Basics</b></li>
<ul><li>Intro - basic performance wisdom and techniques, hardware architecture and its impact.</li><li>Profiling - performance tools and how to use them. As I said, we
don't want to make it easy for us and look at the Windows platform!</li><li>C++ - how performant is C++ really? And what are optimizations the compiler (and linker) can do?</li></ul>
<li><b>Part II - General Techniques</b></li>
<ul><li>Data structures and algorithms - what is the performance of Qt containers and strings? Do we have to use them?</li><li>Multithreading - Qt's take on threading and how to speed up your program with concurrency.</li><li>Fails - some more memorable performance problems I encountered in my programming career.</li></ul>
<li><b>Part III - Selected Qt Modules</b></li>
<ul><li>File I/O etc - Qt and file system performance, JSON and XML parsing. Also memory mapped files and caching.</li><li>Graphic - GUI, OpenGL, widget and QML performance. Probably the most interesting part of the book.</li><li>Networking - network performance and network support in Qt. Because we live in the ubiquitous connectivity era!</li></ul><li><b>Part IV - Goodies</b></li><ul><li>Mobile and embedded - how to use Qt on mobile and embedded (a kind
of advanced chapter applying all we have learned before to two specific
platforms)</li><li>Testing - a goodie chapter about testing techniques, GUI testing and
performance regression tests. At the end this chapter turned out pretty
interesting!</li></ul></ul><div></div></div><div>Got you interested? Then read my detailed <a href="https://ib-krajewski.blogspot.com/2019/02/holy-cow-i-wrote-book.html">blogpost </a>introducing the book!<br /><br /></div><div>--</div><div>* I maybe have to mention, that <a href="https://twitter.com/i_bogosavljevic">Ivica </a>has a well established reputation in the performance community - just look up these links:<br /><ul style="text-align: left;"><li><a href="https://johnysswlab.com/about/">About us - Johny's Software Lab (johnysswlab.com)</a></li><li><a href="https://twitter.com/dendibakh/status/1539792300674629632">PerfChat on Twitter</a></li><li><a href="https://easyperf.net/blog/2021/02/05/Performance-analysis-and-tuning-contest-4">Performance analysis and tuning challenge #4</a><br /></li></ul></div><div><div style="text-align: left;">Impressive, isn't it?</div><div><br /></div></div>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-57127282431275244182022-01-04T01:00:00.007-08:002022-01-07T00:39:26.655-08:00Named parameters for C++11 with variadic templates vs a language feature
<div><br /></div><div>As I'm a little obsessed with emulating Python-style named parameters in C++ (of which several previous posts on this blog could serve as witnesses) when I saw the following line of code*:</div>
<pre class="brush: cpp"> auto p = Popen({"cat", "-"}, input{PIPE}, output{"cat_fredirect.txt"});</pre>
<div>I wanted to see how named parameters are implemented in this library. </div><div><br /></div><div><span style="font-size: large;">Variadic templates implementation</span></div><div><br /></div><div>So, without much ado, here is the implementation of <i>Popen. </i><b>It is using variadic templates, but don't fear</b>, it's not as complicated as it sounds:</div>
<pre class="brush: cpp"> // 1. named parameters are bound to the variadic param set ...args
template <typename... Args>
Popen(std::initializer_list<const char*> cmd_args, Args&& ...args)
{
vargs_.insert(vargs_.end(), cmd_args.begin(), cmd_args.end());
init_args(std::forward<Args>(args)...);
// ...
}
// 2. named params are forwarded to:
template <typename F, typename... Args>
inline void Popen::init_args(F&& farg, Args&&... args)
{
// 3. let ArgumentDeducer do the job!
detail::ArgumentDeducer argd(this);
argd.set_option(std::forward<F>(farg));
// 4. now process next named param from variadic parameter pack:
init_args(std::forward<Args>(args)...);
}
// the ArgumentDeducer class has an overload for each of the named parameter types
inline void ArgumentDeducer::set_option(output&& out) {
if (out.wr_ch_ != -1) popen_->stream_.write_to_parent_ = out.wr_ch_;
if (out.rd_ch_ != -1) popen_->stream_.read_from_child_ = out.rd_ch_;
}
inline void ArgumentDeducer::set_option(environment&& env) {
popen_->env_ = std::move(env.env_);
}
// etc, etc...
</pre><div>This all is very nice, but also very tedious. You can implement it as part of your library to be friendly to your users, but most people won't be bothered to go to that lengths. What about some support from our language? Let have a look at the shiny new C++ standard (most of us aren't allowed to use yet...): </div><div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEj3Y3WxZwH1r3HaLu_XsGTURqnKdDS7cqHYQjw8Exdlw0n7TYJ_rySFVEc2AD9bVWh3aDK1jHazQOJ_Ms3ZJ8gMQKlp_oJp5kYCy07Cng4YO0T94qeDpf_9N3LspZlZJJa0Rzw7s-TNOWO3nrbAVJLpILrpH0DcVskk3VT1wnbiZGko1BkX3_U0hnQM=s300" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="243" height="300" src="https://blogger.googleusercontent.com/img/a/AVvXsEj3Y3WxZwH1r3HaLu_XsGTURqnKdDS7cqHYQjw8Exdlw0n7TYJ_rySFVEc2AD9bVWh3aDK1jHazQOJ_Ms3ZJ8gMQKlp_oJp5kYCy07Cng4YO0T94qeDpf_9N3LspZlZJJa0Rzw7s-TNOWO3nrbAVJLpILrpH0DcVskk3VT1wnbiZGko1BkX3_U0hnQM" width="243" /></a></div></div><div><br /></div>
<span style="font-size: large;">The C++ 20 hack</span>
<div><br />In C++20 we can employ the following hack** that is using C99's init designators:</div>
<pre class="brush: cpp"> struct Named
{
int size; int defaultValue; bool forced; bool verbose;
Named() : size(0), defaultValue(0), forced(false), verbose(false) {};
};
void foo(Named);
void bar()
{
foo({ .size = 44, .forced = true});
}
</pre>
<div>Discussion: OK, this just looks like a hack, sorry! We could as well use a JSON literal as input parameter and circumvent the normal C++ function parameter mechanism altogether: </div><div><div><pre class="brush: cpp"> foo({ "size": 44, "forced": true});</pre></div></div><div>The difference is that the <i>Named</i>-hack will result in members passed in registers, and JSON-hack won't. Unfortunately, the latter is more readable, and that's why we are doing all that in first place! 😞<br /> </div><div><span style="font-size: large;">The language proposal</span></div><div><br />As so often with C++, the various workarounds don't really cut it. So<b> please, please Mr. Stroustrup</b>, can we have named parameters as a language feature?</div><div><br /></div><div>As a matter of fact, there's even a "minimal" proposal for this feature:<br />
<br /> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0671r2.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0671r2.html</a><br />
<br />but unfortunately, I don't know what it's status is just now... Is there even a possibility to check for status of different standard proposals??? <b>Does anybody know?</b> 🤔 (Please respond in the comments!)</div><div><br /></div><div>
If accepted, we could write in our case:</div><div><pre class="brush: cpp"> void bar()
{
foo(size: 44, forced: true);
}</pre></div><div>Another example taken from the proposal:</div><div><div><pre class="brush: cpp"> gauss(x: 0.1, mean: 0., width: 2., height: 1.);</pre></div><div>Here you can see the <b>benefits of that feature in its entirety</b> as all the parameter passed to the <i>gauss()</i> functions are floats!!! </div></div><div><div class="separator" style="clear: both; text-align: center;"><br /></div>Alas, althought this minimalistic proposal stems from 2018 it not part of C++20 (nor of C++23<br /> AFAIK). What can I say - this just fits nicely in the more general notion of <b>legendary user-unfriendliness of C++...</b> 😞 To cheer everybody up - a classic: <i>"but... we have ranges!"</i>.</div><div><br /></div><div><span style="font-size: large;">Update</span></div><div><br />Reading the <i>"2021 C++ Standardization Highlights"</i> <a href=" https://botondballo.wordpress.com/2022/01/03/2021-c-standardization-highlights/">blogpost</a>*** I stumbled upon following formulation:<br /><div></div><blockquote><div><span style="font-size: medium;"><i>"Named Arguments Making a Comeback?</i> </span></div></blockquote><blockquote><div><i>While it has not yet been officially submitted as a P-numbered paper, nor has it been reviewed by EWG, I’ve come across a <a href="https://docs.google.com/document/d/14sQA95BVz8F7y-tqXxqXiRENvEusn8MzZgoBXMu4UbI/edit">draft proposal</a> for <b>named arguments</b> (in this formulation called <b>designated arguments</b>) which was circulated on the committee mailing lists (including the public std-discussion list); there’s also an accompanying video explainer.</i> </div></blockquote><blockquote><i>This looks to me like a thorough, well-researched proposal which addresses the concerns raised during discussions of<b> previous proposals</b> for named arguments</i><i> ..."</i></blockquote><p> So maybe <b>there's hope after all</b>? Never say never!</p></div><div>--</div><div>* Code: <a href="https://github.com/arun11299/cpp-subprocess">https://github.com/arun11299/cpp-subprocess</a></div> Blogpost: <a href="http://templated-thoughts.blogspot.de/2016/03/sub-processing-with-modern-c.html">http://templated-thoughts.blogspot.de/2016/03/sub-processing-with-modern-c.html</a><div><br /></div><div>** source: <a href="https://twitter.com/jfbastien/status/941740836135374848">https://twitter.com/jfbastien/status/941740836135374848</a> -> "Actually you don't even need to repeat "Named". The wonderful ({ .params }) style!"</div><div><br /></div><div>*** found here: <a href="https://botondballo.wordpress.com/2022/01/03/2021-c-standardization-highlights/">https://botondballo.wordpress.com/2022/01/03/2021-c-standardization-highlights/</a>. the referenced quasi-proposal is: <i>"D2288R0 Proposal of Designated Arguments DRAFT 2"</i> to be found at Google Docs <a href="https://docs.google.com/document/d/14sQA95BVz8F7y-tqXxqXiRENvEusn8MzZgoBXMu4UbI/edit">here</a>.</div><div><br /></div>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-12229090520735023212021-12-31T06:18:00.003-08:002023-01-05T03:24:18.688-08:00Beauty in Software Design (and Programming)<br />
Recently I repeatedly heard the phrases <i>"beautiful"/"not beautiful"</i> used to describe and grade a software design, a bugfix or a piece of existing code. <div><br /></div><div>Personally, I didn't like it at all, as it seemed somehow simplistic, but I told to myself: be humble, don't judge, think before you speak... But then, out of the blue, I realized what disturbed me in that phrase! Let me present my argument.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-ZN0TKdAQn5g/TBZaLvLFdbI/AAAAAAAAAGE/y-2AW-bD62s3kyttAJpSie7kVB-RHDvhACPcBGAYYCw/s1600/estimate.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="588" data-original-width="705" height="266" src="https://4.bp.blogspot.com/-ZN0TKdAQn5g/TBZaLvLFdbI/AAAAAAAAAGE/y-2AW-bD62s3kyttAJpSie7kVB-RHDvhACPcBGAYYCw/s320/estimate.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Why didn't I like the <i>"beauty"</i> argument? <b>Because it's too easy, too general and too unspecific.</b></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Software design, as an engineering effort, is an exercise in finding a right tradeoff between different vectors: performance and code readability, code quality and release deadlines, programming effort and importance of a feature, etc.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
When we just fall back to the "beauty" criterion we are just ignoring the more complex reality behind our code. I'd even go as far and venture to say that it is the sign of an immature engineer. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div><div class="separator" style="clear: both; text-align: left;">Let me cite from a blog post*:</div><div class="separator" style="clear: both; text-align: left;"></div><blockquote><div class="separator" style="clear: both; text-align: left;"><i>"- Mature engineers make their trade-offs explicit when making judgements and decisions."</i></div><div class="separator" style="clear: both; text-align: left;"></div></blockquote><div class="separator" style="clear: both; text-align: left;">Let me state it again - we are not looking for beauty when programming, we are trying to survive in a world full of trade-offs. And a mature engineer won't try to ignore that and lock himself up in an ivory tower. Let me cite from a blog post again*:</div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both;"><div class="separator" style="clear: both;"><blockquote><i>"The tl;dr on trade-offs is that everyone cuts corners, in every project. Immature engineers discover them in hindsight, disgusted. Mature engineers spell them out at the onset of a project, accept them and recognize them as part of good engineering."</i></blockquote><div><span style="font-size: x-large;">Mammoths?</span></div></div></div></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">Have you seen the mammoths? They weren't beautiful**, not by any means! But they were optimally adapted to thrive in their habitat!</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://i0.wp.com/arnoldzwicky.s3.amazonaws.com/Mammoth.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="383" data-original-width="510" height="383" src="https://i0.wp.com/arnoldzwicky.s3.amazonaws.com/Mammoth.jpg" width="510" /></a></div><br />Here is one - should we reject him in a code review because of his ugliness?<br />
<div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><span style="font-size: large;">Mathematics?</span></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">What about beauty in mathematics***? Isn't programming <i>"mathematics done with other means"</i>? </div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">Isn't there the old adage among mathematicians that <i>"if it's not beautiful, than it's probably wrong"</i>? And des it apply to programming (via the argument that programming is <i>"mathematics done with other means")? </i></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">Well, my response to that is: <b>mathematics is pure</b>, in the sense that it doesn't have to make any trade-offs. </div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">Besides, I can't see much beauty in modern advanced mathematic like, for example, in proof of Fermat's theorem. Rather than that, it's just complicated and tedious. Looks like the low hanging fruit in mathematics has been already picked... </div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><span style="font-size: large;">Update</span></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">A recent tweet expresses much the same sentiment:</div>
<blockquote class="twitter-tweet"><p dir="ltr" lang="en">Talking about “beautiful code” is a mistake. It elevates subjectivity and personal opinion.<br /><br />What’s deemed good code should be driven by explainable good-faith “metrics” that relate to the purpose of the code: shipping good products on time; *team* productivity; simplicity; etc. <a href="https://t.co/nCgIoBECZ9">https://t.co/nCgIoBECZ9</a></p>— 🙊Christer Ericson (@ChristerEricson) <a href="https://twitter.com/ChristerEricson/status/1500642818850648064?ref_src=twsrc%5Etfw">March 7, 2022</a></blockquote> <script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<div class="separator" style="clear: both; text-align: left;">--</div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both;">* <a href="http://www.kitchensoap.com/2012/10/25/on-being-a-senior-engineer/">http://www.kitchensoap.com/2012/10/25/on-being-a-senior-engineer/</a></div><div class="separator" style="clear: both;"><br /></div><div class="separator" style="clear: both;">** as a classic polish rock songtext stated (credits where credit is due!)<br /><br /></div><div class="separator" style="clear: both;">*** <i>"there is some cold beauty in mathematics..." </i>as Bertrand Russel said</div><div class="separator" style="clear: both;"><br /></div></div><div class="separator" style="clear: both; text-align: left;"><br /></div>
</div>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-69481834598966763942021-12-31T03:48:00.008-08:002022-02-03T01:33:23.374-08:00My talk about the Emma architectural pattern<div><br /></div><div><div style="text-align: right;"><a href="https://1.bp.blogspot.com/-uXAean6aE-c/SfjB0rOYCXI/AAAAAAAAAFM/jW61JoupLIgEA0bJ9T0lqarh1_AEmZWpQCK4BGAsYHg/s796/BeansGraph%2B.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="589" data-original-width="796" height="148" src="https://1.bp.blogspot.com/-uXAean6aE-c/SfjB0rOYCXI/AAAAAAAAAFM/jW61JoupLIgEA0bJ9T0lqarh1_AEmZWpQCK4BGAsYHg/w200-h148/BeansGraph%2B.png" width="200" /></a></div></div><div>When working for one of my clients I learned about Emma (or rather EMMA :-) pattern and it got me quite intrigued. As far as I know, it's never been published anywhere, and frankly, there aren't many publications about embedded systems architecture anyway.</div><div><br /></div><div>In the meanwhile, Burkhard Stuber from <a href="https://embeddeduse.com/">Embedded Use</a> gave a <a href="https://embeddeduse.com/2021/11/07/my-talk-hexagonal-architecture-the-standard-for-qt-embedded-applications-at-meeting-embedded-2021/">talk </a>about Hexagonal Architecture* pattern and argued in his newsletter that:</div><div><i></i><blockquote><i>"In my talk at Meeting Embedded 2021, I argue that the Hexagonal Architecture <b>should be the standard architecture for UI applications on embedded devices.</b> As software and system architects we should never have to justify why we use the Hexagonal Architecture. In contrast, the people, who don't want to use Hexagonal Architecture, should justify their opinion." </i></blockquote></div><div>However, at the time of this talk, these ideas werent yet communicated, but at the moment I still think that even for UI-based applications on embedded devices EMMA could also be an option!</div><div><br /></div><div>The EMMA architecture was successfully used in embedded devices at my client's, it follows an interesting idea and it wasn't published outside of the company before. So I secured an OK from my client and presented it for the general public!</div><div><br /></div><div><span style="font-size: large;">The Talk</span></div><div><br /></div><div>As they gave me permission to blog and speak about it, I gave a presentation on EMMA at the emBO++ 2021** conference:</div><div><div><ul style="text-align: left;"><li>here are my slides: <a href="https://github.com/mrkkrj/presentations/blob/master/EMMA%20architectural%20pattern.pdf">EMMA Software Architecture Pattern for Embedded Systems.pdf</a></li><li>and here is the recorded talk:<br /><br /> <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="332" src="https://www.youtube.com/embed/TxNRLeMUiUw" title="YouTube video player" width="591"></iframe>
</li></ul></div><div><div>The general TOC of the talk looks like this:</div><div style="text-align: left;"><ul style="text-align: left;"><li><b>General intro about architecture patterns </b><br />- and also about embedded software architectures<br /><br /></li><li><b>Motivations and trade-offs </b><br />- the motivation for an the trade-offs taken in the EMMA pattern<br /><br /></li><li><b>Overview of EMMA <br /></b> - its layers, the various conventions it imposes on developers, the standard project structure<br /> - the basic control flow<br /> - the startup phase<br /><br /></li><li><b>Use Case 1 </b><br />- Bootloader on a Device Control MCU<br /><br /></li><li><b>Use Case 2 </b><br />- Target Tests for a Device<br /><br /></li><li><b>Use Case 3 </b><br />- Qt GUI on Yocto Linux and iMX-6</li></ul></div><div><br /></div></div></div><div><span style="font-size: large;">EMMA Architecture</span></div><div><br /></div><div>And here it is, the short, non-formal description of Emma architecture pattern.</div><div><br /></div><div><div>The name of the pattern is an acronym of:</div><div><ul><li><b>E </b>– event-driven (asynchronous events for communication)</li><li><b>M </b>– multi-layered (layering to organize the )</li><li><b>M </b>– multi-threaded (i.e. threading has to follow guidelines)</li><li><b>A </b>– autonomous (i.e. minimal interfaces)</li></ul></div></div><div>The <b>motivation </b>of the pattern is to avoid designs like this:<br /><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhrYnSsnj6t5id5uet7EEPS5w9VymMPJxSZ3dWxDdLLG-6BVuMWxOCYb0a-caKMR9ing83H12IfnL24Jz-9TkHrcU922J_A7ENSPhu0tEhuKwSYvshB5CWB_XzM-lNCEnQOf1S3Cd8_aUz_d2qsbHgSw9FjJjqfmukr6el2GVFMBb8EDOmJd6Fv3JfI=s1248" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="708" data-original-width="1248" height="364" src="https://blogger.googleusercontent.com/img/a/AVvXsEhrYnSsnj6t5id5uet7EEPS5w9VymMPJxSZ3dWxDdLLG-6BVuMWxOCYb0a-caKMR9ing83H12IfnL24Jz-9TkHrcU922J_A7ENSPhu0tEhuKwSYvshB5CWB_XzM-lNCEnQOf1S3Cd8_aUz_d2qsbHgSw9FjJjqfmukr6el2GVFMBb8EDOmJd6Fv3JfI=w640-h364" width="640" /></a></div><br /><div>which, unfortunately, tend to spring to life in many programming projects!</div><div><br /></div><div>The <b>inspiration </b>for the pattern comes from the ISO's seven layer model of a networking stack:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgrQmuoQg54K47WFo9u-4UldzLnadGJV7AX-1uAhuaYYyCyPv-KgrGvNfJRldhYcdMWiDQ9V02Vi2Ujbev_8SvYPGQpm0kWt_7wpVmsXCSVU3Sl2ZOQpL7gKqyCB8pV-XxzXbZGK0dG5rNJPbwkQmq_FjSdrcRAJJg0ryUIyzZZ-aVggnvSA1KltNHv=s1248" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="705" data-original-width="1248" height="362" src="https://blogger.googleusercontent.com/img/a/AVvXsEgrQmuoQg54K47WFo9u-4UldzLnadGJV7AX-1uAhuaYYyCyPv-KgrGvNfJRldhYcdMWiDQ9V02Vi2Ujbev_8SvYPGQpm0kWt_7wpVmsXCSVU3Sl2ZOQpL7gKqyCB8pV-XxzXbZGK0dG5rNJPbwkQmq_FjSdrcRAJJg0ryUIyzZZ-aVggnvSA1KltNHv=w640-h362" width="640" /></a></div><br /><div>We can clearly see, that there are analogies between networking stack decomposition and embedded architecture layers! This is what got me interesten in first pplace</div><div><br /></div><div><div><b>When to use EMMA? </b>The original design argues that it is good for: </div><div><ul style="text-align: left;"><li>Low-power 8-bit MCUs</li><li>Cortex M0-M4 class, 32-bit MCUs (e.g. STM32F4xx), RTOS, C<br /></li></ul><div>But in a recent project we also used it for:</div><ul style="text-align: left;"><li>Cortex A class, Linux, C++, Qt, UI</li></ul><div>I'd say that it can be naturally extended to UI-driven embedded devices, where the A7 (Application) layer isn't a message loop but a Qt-based UI!</div><div><br /></div><div>Thus it can be seen as an alternative to Hexagonal Architecture*, offering the one <b>benefit, that it follows the more widely known Layered Architecture </b>pattern!<br /><br /></div></div></div><div>---</div><div>* <strong><a href="//www.slideshare.net/BurkhardStubert1/hexagonal-architecture-the-standard-for-qt-embedded-applications" target="_blank" title="Hexagonal Architecture: The Standard for Qt Embedded Applications">Hexagonal Architecture: The Standard for Qt Embedded Applications</a> </strong>from <strong><a href="https://www.slideshare.net/BurkhardStubert1" target="_blank">Burkhard Stubert</a></strong></div><div><br /></div><div><div style="text-align: left;"> <iframe allowfullscreen="" frameborder="0" height="485" marginheight="0" marginwidth="0" scrolling="no" src="//www.slideshare.net/slideshow/embed_code/key/C1KYFL6LNiXiQ6" style="border-width: 1px; border: 1px solid #CCC; margin-bottom: 5px; max-width: 100%;" width="595"> </iframe></div><div style="margin-bottom: 5px;"><br /></div><div style="margin-bottom: 5px;">** emBO++ 2021 | the embedded c++ conference in Bochum, 25.-27.03.2021</div><div style="margin-bottom: 5px;"><br /></div>
</div>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-80438740550411344642021-12-30T13:10:00.004-08:002022-02-04T07:14:50.464-08:00My two talks about polymorphic memory resources in C++ 17/20<p></p><p><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjy6S7U-U4tM4TpxokacRjO92m2-LVCFfrbyYgJQ7ZwHqGj0qyK1ECeXQcop0RuR405aLKM51EzK7YU02149TrW3eR1lfu75IGCcIAxrFAjGUwBT1R0VRSKs7EYbJQ8QgNvEeduZ53ypiwZMuZgFjhYud5xKkvgMFpsJMR-TT49Ji2Iznr_kMlikjrD=s200" style="clear: right; display: inline; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"><img border="0" data-original-height="200" data-original-width="200" height="124" src="https://blogger.googleusercontent.com/img/a/AVvXsEjy6S7U-U4tM4TpxokacRjO92m2-LVCFfrbyYgJQ7ZwHqGj0qyK1ECeXQcop0RuR405aLKM51EzK7YU02149TrW3eR1lfu75IGCcIAxrFAjGUwBT1R0VRSKs7EYbJQ8QgNvEeduZ53ypiwZMuZgFjhYud5xKkvgMFpsJMR-TT49Ji2Iznr_kMlikjrD=w124-h124" width="124" /></a> <br />Quite a time ago I was listening to Jason Turner's <a href="https://www.youtube.com/watch?v=5VrX_EXYIaM">C++ Weekly‘s Episode 250</a>* about PMRs (i.e. C++17's Polymorphic Memory Resources) and he mentioned some advanced usage techniques that can be accomplished using them. </p><p></p><p>Althought I dare to consider myself to be quite an knowlegeable C++ programmer, <b>I just couldn't get it </b>- I didn't understand how these techniques are working and what are they good for! <b>What a disaster!</b> Myself not understanding C++??? That cannot be true! Well, it was, but I wasn't willing to leave it like that.</p><p>So I started to look into the whole memory allocators story in C++. </p><p>What have I found? Well:<br /></p><ul style="text-align: left;"><li>the surprisingly lacking design of C++98 allocators</li><li>a fascinating story of library design and evolution</li><li>understanding of some techniques which aren‘t generally known</li></ul><p></p><div><span style="font-size: large;">Talk 1</span></div><div><br /></div><div>So I told myself, that this could be a material for a conference talk, and I just did it! I mean, I gave a presentation at C++Italy 2021 conference**:</div><div><ul><li>here are my slides: <a href="https://github.com/mrkkrj/presentations/blob/master/PMRs%20for%20performance.pdf">PMRs for Performance in C++17-20.pdf</a></li><li>and here is the recorded talk:<br /><br /> <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="332" src="https://www.youtube.com/embed/zB2L6HRR-qQ?list=UUNge3iECU0XKjshac_hdejw" title="YouTube video player" width="591"></iframe>
</li></ul></div><p>I titled the talk <i>"PMRs forPerformance in C++17-20"</i>, but as I can see in retrospect, it was a little misleading because performance wasn't the main theme of it. Instead its TOC looked like this:</p><p></p><ul style="text-align: left;"><li><b>Memory Allocators for Performance </b><br />- how allocators can increase performance (OK, at last <i>some </i>general performance knowledge was brought forth here!)<br /><br /></li><li><b>Allocators in C++98 and C++11</b><br />- how (and why) allocators were broken in C++98, how Bloomberg's design tried to fix it, and what parts of it were incorporated in C++11<br /><br /></li><li><b>Allocators in C++17 and PMRs</b><br />- how the remaining parts of Bloomberg's design were addded in C++17 and what classes in the <i>pmr </i>namespace are implementing it<br /><br /></li><li><b>Usage Examples</b><br />- here more <i>pmr::</i> classes, functions and mechanisms were introduced<br /><br /></li><li><b>Advanced PMR Techniques</b><br />- at last, the 2 techniques that started all of that were explained here - Wink-Out and Localized Garbage Collection, but also the EBO optimization technique for allocators was mentioned<br /><br /></li><li><b>Allocators in C++20 (and Beyond)</b><br />- here I discussed PMR extensions added in C++20, talked about C++23's <i>test_resource</i> proposal and hinted at the possibility of delegating all of the allocator mess (sic!) to the compiler</li></ul><p></p><p>So, it was more a journey through allocator's evolution up to the PMRs and about some more advanced techniques than PMR's impact on performance, I must admit. But all in all, I was rather happy with my talk - there was lot of material covered! </p><p>However, promptly, <b>the inevitable question popped up - is the Wink-Out technique UB-safe</b>***? Ooops, I didn't expect that! I tried to conjecture something but in the end I had to admit that I wasn't sure. 😕 </p><p>Besides, I was only able to give Wink-Out and Localized GC examples in C++20 as C++17 lacked some PMR features added in C++20. 😕 And I also wanted to look on the interplay of PMRs and smart pointers but didn't quite go round to it...</p><p><span style="font-size: x-large;">Talk 2</span></p><p>At that point was clear, that I have to do more digging! The result of it was a second talk, which I proposed for the 2021 Meeting C++ conference. Luckily, it got accepted (yay!): </p><ul><li>here are my slides: <a href="https://github.com/mrkkrj/presentations/blob/master/Two%20advanced%20PMR%20techniques.pdf">Two advanced PMR techniques in C++ 17/20.pdf</a></li><li>and here is the recorded talk:<br /><br /> <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="332" src="https://www.youtube.com/embed/6FDdK4V77tU" title="YouTube video player" width="591"></iframe></li></ul><div>This time I wanted to concertrate on the 2 techniques, that I could only shortly discuss in the previous talk, so I tried to cut out the library evolution stuff and add discussion of the UB problems, C++17 vs C++20 code and smart pointer usage. </div><div><br /></div><div>Finally the TOC of the presentation looked like this:</div><div><ul style="text-align: left;"><li><b>Intro: memory allocators for performance and more</b><br />- again, how and why allocators can increase performance<br /><br /></li><li><b>STL Allocators vs PMRs</b><br />- how PMRs improve on the traditional C++ allocator model (spoiler - by using a virtual base class!)<br /><br /></li><li><b>Advanced techniques</b></li><ol><li><b>Wink Out (and/or arenas)<br /></b>- here I also cleared the Wink-Out UB question. It was already answered in some proposal or TR (as I noticed later!) but I found a C++ Standard's section 9.2.2. [basic.life] which says:<br /><br /><i>"For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released"<br /></i><br />So winking-out is allowed within C++ object lifetime framework!<br /><br />- also real-life examples of the technique were presented: Google's <i>Protocol Buffers</i> and JSON data struct implementation in<i> C++ Actor Framework</i><br /><br /></li><li><b>Localized GC (aka. self contained heaps)</b><br />- with localized GC we also discussed how smart pointers work with PMRs, where they both collide and we even touched on C++20 <i>destroying delete</i> feature!<br /><br /></li></ol><li><b>Some lessons<br /></b>- this time we also discussed the usage costs and open problems with PMRs and concluded that there are still some of them. Maybe pushing it all down to the compiler via a language mechanism could improve the situation?</li></ul></div><div>All in all, I though that I cut out so much from my initial slide set, but I was still short for time! I wonder how I managed to squeeze in so much material in the first talk!</div><p><span style="font-size: xx-large;">The two techniques</span></p><p>The example code for both talks can be found here: <a href="https://github.com/mrkkrj/presentations/blob/master/PmrTests.cpp">PmrTests.cpp</a>, so you can just check it out (or listen to my presentations 🙂), but for completeness' sake I'll briefly introduce those two advanced techniques also in this post.</p><p><b><span style="font-size: medium;">Winking out </span></b>tries to omit all calls to a destructors of in given container and reclaims the used memory when the allocator (and it's PMR) goes out of scope. Of course no side-effects in destructors are allowed here!</p><p>The slide below shows the example code:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjqViioLGjgmiwgzCDeDjW_PvqHZlXxQHxFtzWjpTQ6wr3TyO0e58EETNs1X1kxvDDtFKAgGEb0xLOAmtEbJvRgVbblGjOX1muZx1l9yWQOciDB9RDHQk8tt5fRaG9xSz54WWe0dFT-pceqAHV5SS4xb8biEX3KYIFqaP7synQPawhKMYD4b7K8gMk3=s1374" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="774" data-original-width="1374" height="360" src="https://blogger.googleusercontent.com/img/a/AVvXsEjqViioLGjgmiwgzCDeDjW_PvqHZlXxQHxFtzWjpTQ6wr3TyO0e58EETNs1X1kxvDDtFKAgGEb0xLOAmtEbJvRgVbblGjOX1muZx1l9yWQOciDB9RDHQk8tt5fRaG9xSz54WWe0dFT-pceqAHV5SS4xb8biEX3KYIFqaP7synQPawhKMYD4b7K8gMk3=w640-h360" width="640" /></a></div><br /><b><span style="font-size: medium;">Localized GC</span></b> uses the above technique to avoid unbounded recursion and stack exhaustion when deleting complicated graph structures where nodes are connected by smart pointers. We just fall back to naked pointers and wink-out the entire graph. Graph cycles are also no problem now!<br /><p>The slide below shows the example code:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEipraWGxhjxxdfOCNq5yhUl1JMAfYkuJkBxTDWH910GnMlsmqjwFAhBF-2ra4-CcfMTgeWP-KtZO0lg6oovxevmtGzuOvnqqrAW67GKy4j0beU8y9_KklLfWJ-i3Lvu9QxUM6D39WKXN-nqpXTdh7WT4O9mmAmvh2kjCc2HhzMlKGtbd1L-CrItOQe0=s1292" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="731" data-original-width="1292" height="362" src="https://blogger.googleusercontent.com/img/a/AVvXsEipraWGxhjxxdfOCNq5yhUl1JMAfYkuJkBxTDWH910GnMlsmqjwFAhBF-2ra4-CcfMTgeWP-KtZO0lg6oovxevmtGzuOvnqqrAW67GKy4j0beU8y9_KklLfWJ-i3Lvu9QxUM6D39WKXN-nqpXTdh7WT4O9mmAmvh2kjCc2HhzMlKGtbd1L-CrItOQe0=w640-h362" width="640" /></a></div><div><br /></div>Want to learn more? Listen to presentations or read the slides. Or just ask your question in the comment section.<br /><p><span style="font-size: xx-large;">Resources</span></p><p>Here I will add a list of the resources I used when preparing the 2 talks: mainly standard proposals and technical reports of the C++ standard committee. </p><p><span style="background-color: #fcff01;">--> </span><i><span style="background-color: #fcff01;">OPEN TODO:</span> </i>please be patient a liitle more, I promise it comes soon!</p><p>___</p><p>* C++ Weekly, Ep.250: <i>"Custom Allocation -How, Why, Where (Huge multi threaded gains and more!) "</i> - <a href="https://www.youtube.com/watch?v=5VrX_EXYIaM">https://www.youtube.com/watch?v=5VrX_EXYIaM</a></p><p>** C++Italy 2021 - Italian C++ Conference 2021, 19.06.2021, online</p><p>*** UB: Undefined Behaviour, the bane of C++ developer's existence<br /><br /></p>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-45435214694667791822020-12-31T04:01:00.006-08:002021-12-31T02:20:35.335-08:00A new code example for the "Qt Performance" book<div><br /></div>Recently I added a new example* to my "<i>Qt5 Performance</i>" book's resources that I didn't manage to include in the original release - the trace macros creating output in <i>chrome:tracing </i>format. <div><br /></div><div>I think it's a very cool technique - instrument your code and than inspect the result as a graphic! On <b>Linux </b>we have <i>flame graph</i> support in the standard tooling integrated with Qt Creator.</div><div><div><br /></div><div>On <b>Windows</b>, however, we do not have such a thing! And because I decided to use Windows as the deveolpment platform for my book, we have a kind of problem here, so creative solutions are needed!</div><div><br /></div><div>And I already came up with an idea for that in the book - we can use libraries (like <i><a href="https://github.com/hrydgard/minitrace">minitrace</a></i>, the library we are using in this example ) to generate profiling output in a <a href="https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview">format </a>that the Chrome's** trace viewer will understand! You didn't know that Google's Chrome had a built-in profiler? Some people assume it’s only for profiling “web stuff” like JavaScript and DOM, but we can use it as a really nice frontend for our own profiling data.</div><div><br /></div><div>However, due to lack of time I couldn't try it out when I was writing the book 😞, but with the new example I added I was able to generate output you see visualizedin the figure below:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/blob/master/Chapter%202/QmlWithModelTraced/example%20results/trace%20view%20in%20chrome.jpg?raw=true" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="415" data-original-width="800" height="542" src="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/blob/master/Chapter%202/QmlWithModelTraced/example%20results/trace%20view%20in%20chrome.jpg?raw=true" width="1046" /></a></div><br /><div><br /><br /><br /><br /><br /><br /><br /><br /><br /><i><br /></i></div><div><i><br /></i></div><div><br /></div><div><span style="font-size: large;"><br /></span></div><div><span style="font-size: large;"><br /></span></div><div><span style="font-size: large;"><br /></span></div><div><span style="font-size: large;"><br /></span></div><div><span style="font-size: large;"><br /></span></div><div><span style="font-size: large;"><br /></span></div><div><span style="font-size: large;"><br /></span></div><div><span style="font-size: large;"><br /></span></div><div><br /></div><div><br /></div><div>Here is the <a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/blob/master/Chapter%202/QmlWithModelTraced/main.cpp">code </a>example I used - as you can see, you have only to insert some <i>MTR_()</i> macros here and there:</div>
<pre class="brush: cpp"> int main(int argc, char *argv[])
{
mtr_init("trace.json");
MTR_META_PROCESS_NAME("QmlWithModel");
MTR_META_THREAD_NAME("Main GUI tread");
MTR_BEGIN("main", "main()");
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QStringList countryList;
countryList << "Thinking...";
MTR_BEGIN("main", "load QML View");
QQuickView view;
QQmlContext *ctxt = view.rootContext();
ctxt->setContextProperty("myModel", QVariant::fromValue(countryList));
view.setSource(QUrl("qrc:/main.qml"));
view.show();
MTR_END("main", "load QML View");
// get country names from network
MTR_BEGIN("main", "init NetworkMgr");
QNetworkAccessManager networkManager;
MTR_END("main", "init NetworkMgr");
....
</pre>
<div><br /></div><div><span style="font-size: x-large;">PS: </span><i>heob-3</i> (i.e the new version of the <i>heob</i> memory profiler we discussed in the book) has a sampling profiler with optional flame graph output!!! I think I have to try it out in the near future!<p>--<br />* you can find the new example <a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%202/QmlWithModelTraced" target="_blank">here</a>, and the generated JSON file <a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/blob/master/Chapter%202/QmlWithModelTraced/example%20results/trace.json">here</a></p><p>** Chrome browser's <i>about:tracing</i> tool. You can use it like this:<br /></p><p></p><ul style="text-align: left;"><li>go to <i>chrome://tracing </i>in Chrome</li><li>click “<i>Load</i>” and open your JSON file (or alternatively drag the file into Chrome)</li><li>that's all<br /><br /></li></ul></div></div>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-12907596835258801612020-12-31T03:47:00.000-08:002020-12-31T03:47:42.557-08:00More about basic QML optimizations<div>
<a href="https://1.bp.blogspot.com/-Ty14MOcct54/XJIDHu9fASI/AAAAAAAAAkQ/QAXtXV2fuj0MX1EquxZON5Hwxy2jLINWwCPcBGAYYCw/s1600/cover%2Bfrontside%2B-%2Bsm.jpg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="138" data-original-width="110" src="https://1.bp.blogspot.com/-Ty14MOcct54/XJIDHu9fASI/AAAAAAAAAkQ/QAXtXV2fuj0MX1EquxZON5Hwxy2jLINWwCPcBGAYYCw/s1600/cover%2Bfrontside%2B-%2Bsm.jpg" /></a></div><div><br /></div>
You might perhaps already know that I recently wrote a <a href="https://www.packtpub.com/application-development/hands-high-performance-qt">book</a> (blogged about it <a href="https://ib-krajewski.blogspot.com/2019/02/holy-cow-i-wrote-book.html">here</a>)! In the book we discuss various general program performance topics but also some more specific, Qt related ones, for example Qt's graphical or networking performance.<br />
<div>
<br />
Recently, as I was watching some QML presentation I realized that some very basic pieces of performance advice I just glossed over in the book could (and should) be explained in a much more detailed manner to build a general understanding of this technology's caveats.<br /><br />
In Chapter 8.4, where the book discusses QML's performance, I simply wrote that:<br />
<div>
<blockquote class="tr_bq">
"If an item shouldn't be visible, set its visible attribute to false, this will spare the GPU some work. In the same vein, use opaque primitives and images where possible to spare GPU from alpha blending work."</blockquote>
<i></i>As I re-read this section on some occasion I somehow had to notice that what seemed pretty clear in writing, isn't that clear when read a year later! I started to think why this passage is not that lucid as it should be, and I noticed,<b> that my intended formatting was gone!</b> Now we have in the book:<br /><blockquote>"... set its visible attribute to false" </blockquote></div><div>instead of <br /><blockquote>"... set its <i>visible </i>attribute to <i>false</i>"</blockquote></div><div>as I wrote it initially!!! The formatting went somehow missing and I didn't notice it while proofreading. For me this change rendered the sentence pretty unintelligible :-/.</div><div><br />But anyway, I could have explained it in a little more detailed manner* - so let's try to make a better job and explain why the visible attribute is so important!<br /><br />To state it bluntly - <b>QML won't do any optimizations to prevent drawing items the user cannot see</b>, like items which are out of bounds or are completely obscured or clipped** by other items! It just draws every single item with <i>visible </i>set to <i>true</i>, totally unconcerned with its real visibility! So we have to optimize manually and:<br /></div><blockquote>"... set its <i>visible </i>attribute to <i>false</i>"</blockquote><div>But how on earth should we know which items are invisible in which situation? Easy, just set this environment variable: <i>QSG_VISUALIZE=overdraw </i>and Qt will show the overdrawn items using a different color and making them visible as can be seen in this pic from Qt documentaion:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://doc.qt.io/qt-5/images/visualize-overdraw-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="140" data-original-width="200" height="280" src="https://doc.qt.io/qt-5/images/visualize-overdraw-1.png" width="400" /></a></div><br /><div>That's pretty cool!</div><div><br />This was my state of knowledge until recently (learned about that in <a href="https://www.blogger.com/#">this </a>KDAB presentation) but than I read this line in Qt Quick 2D Renderer's <a href="https://www.blogger.com/#">documentation</a>:</div><div><blockquote><i>Qt Quick 2D Renderer will paint all items that are not hidden explicitly with either the visibility property or with an opacity of 0. <b>Without OpenGL there is no depth buffer</b> to check for items completely obscured by opaque items, so everything will be painted - even if it is unnecessary.</i></blockquote>Qt Quick 2D Renderer is a raster-graphic replacement for the standard OpenGL-based QML renderer. Does that (by <i>tertium non datur</i>) mean that with OpenGL <b>we do use the depth buffer </b>after all? This could be an unfortunate formulation, so we'd like to stay on the conservative side but maybe a little more investigation would be appropriate in this case. Have you heard anything about it?<br /><br /></div>--<br />* This might be due to the very tight deadlines :-(<br /><br />** as Qt <a href="https://www.blogger.com/#">documentation </a>says: <div><blockquote>"If clipping is enabled, an item will clip its own painting, as well as the painting of its children, to its bounding rectangle."</blockquote></div>
</div>
Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-17365690475220656622020-09-26T09:54:00.001-07:002020-09-27T04:58:23.769-07:00Lippincott Pattern<br />
<span style="font-size: large;">1. Intro</span><br />
<a href="https://1.bp.blogspot.com/-htb3Y938H8s/Vg2okXV-BhI/AAAAAAAAAQ8/ZrRuJTigpTs5yC9L7fGBS8EhtOJXcRaugCPcBGAYYCw/s1600/code-820275_1280.jpg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="853" data-original-width="1280" height="133" src="https://1.bp.blogspot.com/-htb3Y938H8s/Vg2okXV-BhI/AAAAAAAAAQ8/ZrRuJTigpTs5yC9L7fGBS8EhtOJXcRaugCPcBGAYYCw/s200/code-820275_1280.jpg" width="200" /></a><br />In one of my recent C++ projects <b>I spotted some giant macro</b> named <i>HANDLE_ALL_EXCEPTIONS() (</i>or so)<i>,</i> immediately noted <b>how ugly it was</b><b> </b>and that a better solution to that problem exists. <div><br /></div><div>My coworkers at the then-customer were nice and open minded people so they didn't bridle at that, on the contrary, they were eager to change it and asked for advice. I simply said that<b> they should google for the "Lippincot Pattern"</b> and thought the matter were settled.<br />
<br />
To my surprise my buddy returned reporting that there's <b>nothing like that on the Internets</b>! As to remedy that sore state of affairs I decided to make a short write-up of that really cool technique.<br />
<br />
<span style="font-size: large;">2. On Naming</span><br />
<br />
An astute reader might have noticed that the whole problem is an artificial one: there is some (admittedly still too little!) information on the <b>"Lippincot function"</b> out there*. And Jason Turner (aka @lefticus) made an entire <a href="https://www.youtube.com/watch?v=-amJL3AyADI">episode of C++ Weekly</a> about it. So why I'm insisting on a different name?<br />
<br />
Well, to be honest, it's mainly because I learned it by this name! Sadly, I cannot find any article on the web, so I cannot present you with any proof, but I assure it that it is true. Has anybody besides me heard of this technique under the name Lippincott Pattern instead of Lippincott Function? Please leave a comment if you did, I'm really curious about it!<br />
<br />
But besides of my inability to change my habits there indeed is a genuine argument for that name. I mean, it is a known technique solving a common programming problem and that's the definition of a programming pattern if I'm not mistaken! And it's of no importance if we are using a function or a set of classes to solve the problem.<br />
<br />
And of course, it sounds much better, and, without a doubt this, counts as a<b> third reason</b>. 🙂<br />
<br />
As we are in a section called "On Naming" you might ask why this technique is called Lippincott function/pattern? Elementary, Dear Watson - it's beacuse it was invented by Lisa Lippincott, a well-known programmer and (as of recent) a C++ committee member with a faible for maths:<br />
<blockquote class="twitter-tweet">
<div dir="ltr" lang="en">
Day 3 Keynote by Lisa Lippincott: <br />
“The Shape of a Program” <br />
Mathematical topology in programming. <a href="https://twitter.com/hashtag/ACCUConf?src=hash&ref_src=twsrc%5Etfw">#ACCUConf</a> <a href="https://t.co/qudggtGJsj">pic.twitter.com/qudggtGJsj</a></div>
— Victor Ciura (@ciura_victor) <a href="https://twitter.com/ciura_victor/status/984730843200540672?ref_src=twsrc%5Etfw">April 13, 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script><span style="font-size: large;">3. The Pattern</span><br />
<br />
But enough of the idle banter, and <i>ad rem</i>! I maybe should have mentioned that this technique is also sometimes called "Exception Dispatcher". Now you probably can already imagine how it works.<br />
<pre class="brush: cpp"> try
{
throw;
}
catch (const MyNetworkException& ex)
{
MY_LOG_ERROR(tags::Networking, QString("Exception occurred: ") + ex.what());
}
catch (const std::exception & ex)
{
MY_LOG_ERROR(tags::Networking, QString("Unexpected exception occurred: ") + ex.what());
}
catch (...)
{
MY_LOG_ERROR(tags::Networking, "Unknown exception occurred.");
}
</pre>
<div>As you see, we rethrow the current exception (notice that we assume we are in an exception handler!!!) and can write reusable exception handling logic without macros! We use it simply like this:</div><div><pre class="brush: cpp"> try
{
a_function_that_may_throw();
}
catch (...)
{
traceException(); // Lippincott!
}
</pre></div><div>Here we just log the error and do nothing, but we could as well translate exceptions in error codes, as it is shown in the already mentioned blogpost*, and then use it like this;</div><div><pre class="brush: cpp"> try
{
a_function_that_may_throw();
}
catch (...)
{
return translateExceptionToErrno(); // Lippincott!
}</pre></div><div>However, that's not all - we can also here more complex logic. Let us have a look at this exception handler function from my recent HTTP project**:<div>
<pre class="brush: cpp"> int CasablancaRestClient::handleException() const
{
QString errText;
int errorCode;
try
{
throw; // Lippincott pattern
}
catch (const web::http::http_exception& e)
{
// probably TCP conn. error!
// - notify conn. status change, trigger HTTP fallback if needed
return HandleHttpError(e);
}
catch (const web::uri_exception& e)
{
QWriteLocker guard(&_serverAliveLock);
if (!_serverAlive)
{
// probalbly server's URL not yet set
errorCode = EC_NO_CONNECTION;
}
else
{
errText = tr("Internal error, bad URL: %1.").arg(e.what());
errorCode = EC_BAD_URL;
}
}
catch (const web::json::json_exception& e)
{
errText = tr("Internal error, bad JSON data: %1.").arg(e.what());
errorCode = EC_JSON_FORMAT;
}
catch (const std::exception& e)
{
errText = tr("Internal error, reason: %1.").arg(e.what());
errorCode = EC_INTERNAL;
}
catch (...)
{
errText = tr("Internal error in CCasablancaRestClientComp!!!!");
errorCode = EC_INTERNAL;
}
WIN_DEBUG_CLIENT_ERR(errText.ToStdString());
// send the error to GUI context
emit connectionErrorMessage(errText);
return errorCode;
}
</pre>
We see, we are just doing the basic translation from exception types to error codes, but <b>also initiate a reconnection</b> or <b>fallback to a non-secure connection</b> in some cases!<br />
<div><br /></div><div>I was using it in following manner:</div><div><pre class="brush: cpp"> try
{
sendHttpRequest(uri, data, headers);
return EC_OK;
}
catch (...)
{
return handleException(); // Lippincott!
} </pre>
The beauty of this lies in its conciseness - no copy-pasted code, no macros, just a natural function call somehow obliterating the ugliness of the try-catch blocks.</div><div>
<br />
<span style="font-size: large;">4. "Modern" Lippincott variants</span><br />
<br />
What we have seen above was the plain, basic, C++98-esque usage. <b>But C++ wouldn't be itself, if we couldn't complicate things</b> in name of progress and fashionable gimmicks <span style="background-color: white;"><span>😇.</span></span><br />
<span style="background-color: yellow;"><br /></span>
Just have a look at this code taken from the already mentioned article*:</div><div><pre class="brush: cpp"> foo_Result lippincott()
try
{
try
{
if (std::exception_ptr eptr = std::current_exception())
{
std::rethrow_exception(eptr);
}
else
{
return FOO_UNKNOWN;
}
}
catch (const MyException1&)
{
return FOO_ERROR1;
}
catch (const MyException2&)
{
return FOO_ERROR2;
}
catch (...)
{
return FOO_UNKNOWN;
}
}
catch (...)
{
return FOO_UNKNOWN;
}
</pre>First irritating thing here is the function-scope try block. C++ allows you to wrap function body in a try/catch clause like this:</div><div><pre class="brush: cpp"> ErrCode getSomeData()
try
{
// do sth....
}
catch (...)
{
return PANIC_ERR;
}</pre><div>What is the purpose of this fature, you might ask? As <i>cppreference.com</i> <a href="https://en.cppreference.com/w/cpp/language/function-try-block">states</a>:<br /><i><blockquote>"The primary purpose of function-try-blocks is to respond to an exception thrown from the member initializer list in a constructor by logging and rethrowing, modifying the exception object and rethrowing, throwing a different exception instead, or terminating the program"</blockquote></i></div>So there aren't any corner cases to justify its usage, and our example we already handle exceptions <b>inside </b>of the function OK, now we can shed this syntax noise off. The second oddness is the usage of std::current_exception() and std::rethrow_exception() - what it is for? <br /></div><div><br />When you call <i>std::current_exception() </i>from within your function you can chek if there currently is an exception being handled and if it returns a <i>nullptr </i>then there is no exception active. Thus in the discussed code, we, in a somehow paranoid manner, are making sure that the exception dispatching function was called from the exception context - so to say implementing a <b>"safe Lippincott"</b> pattern. But ask yourself - would a programmer use a Lippincott function outside of a <i>catch() </i>block? Well, maybe.</div><div><br />However, <b>not all modern features are bad - far from that! </b>Look at this elegant technique that uses lambdas:</div><div><pre class="brush: cpp"> extern "C" errno_t my_amazing_c_function()
{
return translateException(<br /> [&]{
// ... C++ code that may throw ...
});
}
</pre>Here we wrap code that may throw in a lambda and pass it to a generalized exception translation function which can be implemented like that:<br /><div><pre class="brush: cpp"> template<typename Callable>
ErrorCode translateException(Callable&& f)
{
try
{
f();
return NO_ERR;
}
catch (...)
{
return translateExceptionToErrno(); // Lippincott!
}
}</pre>Cool, innit?</div><div><br /></div><div><span style="font-size: large;">P.S.:</span> <i>"Ceterum censeo exceptiones delendam sunt..." - </i>M. Portius Cato</div>
<br />
--<br />
<br />
* for example here: <a href="http://cppsecrets.blogspot.com/2013/12/using-lippincott-function-for.html">http://cppsecrets.blogspot.com/2013/12/using-lippincott-function-for.html</a> plus many mentions of this article on Stack Overflow.<br /><br />
** Look up the Casablanca post: <a href="http://ib-krajewski.blogspot.com/2015/09/casablanca-c-rest-framework-one-year.html">http://ib-krajewski.blogspot.com/2015/09/casablanca-c-rest-framework-one-year.html</a><br /><br /></div>
</div></div></div>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com1tag:blogger.com,1999:blog-3870801931584460413.post-89784381508633201572020-08-18T07:39:00.004-07:002020-08-28T10:11:50.056-07:00The pain(s) of C++11<div class="separator"><a href="https://1.bp.blogspot.com/-htb3Y938H8s/Vg2okXV-BhI/AAAAAAAAAQ8/ZrRuJTigpTs5yC9L7fGBS8EhtOJXcRaugCPcBGAYYCw/s1280/code-820275_1280.jpg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: right;"><img border="0" data-original-height="853" data-original-width="1280" height="133" src="https://1.bp.blogspot.com/-htb3Y938H8s/Vg2okXV-BhI/AAAAAAAAAQ8/ZrRuJTigpTs5yC9L7fGBS8EhtOJXcRaugCPcBGAYYCw/w200-h133/code-820275_1280.jpg" width="200" /></a></div><div><div style="text-align: center;"><br /></div></div>Recently I wrote a small cross-platform library of widgets and didn't think much about the C++ version to be used, as my client's primary platform was Windows plus the latest Visual Studio with C++17. As the Microsoft compiler was normally the slowest to implement new standard's features I didn't worry about problems when compiling the code with GCC on Linux and just settled on the C++17 standard (or at least the subset of it supported by the used Visual Studio version).<div><div>
<br />
However.... it all came out rather differently. </div><div><b> </b></div><div><b>First, I had to back-port it to </b>Visual Studio 2015, which theoretically supported C++17, but didn't have <i>std::optional</i> in its STL 😨, but this is material for another article...</div><div><br /></div><div>If that weren't enough, it turned out that the GCC version used in our build server doesn't support C++17, so <b>I had backport it again to C++11</b>. OK, I thought, C++11 was the giant step for C++ so it shouldn't be that difficult to go back, all the most important language features should already be present there. <br />
<br />You'll imagine my surprise, when this innocent code snippet failed to compile on the build server!<br />
<pre class="brush: cpp"> // impl. helpers:
template<typename Enum>
constexpr auto enumToInt(Enum e) noexcept // C++20: requires(std::is_enum_v<Enum>)
{
return static_cast<std::underlying_type_t<Enum>>(e);
}
</pre><div>You see, optimistic as I am, I was already thinking about what would be possible in C++20!</div><div><br /></div><div>I won't show you the exact error message because it is incomprehensible for most people*. Enough to say it wouldn't compile.</div><div><br /></div><div>So this is what I had to use instead:</div><pre class="brush: cpp"> template<typename Enum>
constexpr auto enumToInt(Enum e) noexcept // C++20: requires(std::is_enum_v<Enum>)
-> typename std::underlying_type<Enum>::type // C++11 backward compatibility :-(
{
return static_cast<typename std::underlying_type<Enum>::type>(e);
}
</pre><div>As we can see, I needed first to sptinkle some <i>typename </i>keyword's instances all over the place to help and guide the compiler in parsing of the template. Secondly, in C++11 the <i>XXX_type_t </i>shortcuts for the standard library types aren't available. I had also to explicitely specify the return type of the lambda.</div><div><br /></div><div>You see - much more mindless typing in the C++11 version! In some respect it's almast as verbose as the older Java releases. And not to mention lots of time used for deciphering template error messages to find out those problems!</div><div><br /></div><div><span style="font-size: x-large;">Conclusion:<br /></span></div><div><br />In conclusion I must say, we <b>should appreciate C++14/17 much more </b>than we do, because it really saves us the time to write and later to read the code!!! Somehow I wasn't fully aware of that.</div><div><br /></div><div><span style="font-size: x-large;">P.S.:<br /></span>Imagine, at first I was even tempted to use this monster<a href="https://1.bp.blogspot.com/-0oVCH3_UNK8/Tw34wz-ULsI/AAAAAAAAAJs/6e4IB-B6XZYcNqSPEonvUUa8DVYXU11QwCK4BGAsYHg/s32/cpp.gif" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="32" data-original-width="32" src="https://1.bp.blogspot.com/-0oVCH3_UNK8/Tw34wz-ULsI/AAAAAAAAAJs/6e4IB-B6XZYcNqSPEonvUUa8DVYXU11QwCK4BGAsYHg/cpp.gif" /></a>:</div><pre class="brush: cpp"> template<typename Enum>
constexpr auto enumToInt(Enum e) noexcept
-> decltype(static_cast<typename std::underlying_type<Enum>::type>(e)) // C++11 backward compatibility :-O
{
return static_cast<typename std::underlying_type<Enum>::type>(e);
}
</pre>
</div></div><div>--</div><div>* Personally. I always found <b>the complaints to be somehow exagerated</b> - with a little practice you can find the problem in not too long a time. But it is a quest and not an automated procedure. On the other hand, isn't it always like that with compilers? Good error messages are rather a recent invention and still more like an exception than a rule.</div><div><br /></div><div><br /></div>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-13455294759157603542020-08-18T06:51:00.000-07:002020-08-18T06:51:53.188-07:00A study in bad naming<div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">
Recently, while working for one of my clients on someone other's code I spotted the following definitions of members in some class:</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-3rimML4mIcg/XsN8BX-FlxI/AAAAAAAAA5E/HJ9eoqEnDGIK4poedAxLVTcr4km6ihk0QCLcBGAsYHQ/s1600/study%2Bin%2Bbad%2Bnaming.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="450" data-original-width="1181" src="https://1.bp.blogspot.com/-3rimML4mIcg/XsN8BX-FlxI/AAAAAAAAA5E/HJ9eoqEnDGIK4poedAxLVTcr4km6ihk0QCLcBGAsYHQ/s1600/study%2Bin%2Bbad%2Bnaming.PNG" /></a></div>
What's that???!!! <img border="0" data-original-height="32" data-original-width="32" src="https://1.bp.blogspot.com/-0oVCH3_UNK8/Tw34wz-ULsI/AAAAAAAAAJs/jjIOp4qtZsIVg8J1brM3s1gZt53hM1ATQCPcBGAYYCw/s0/cpp.gif" /> Can you see it? <b>Are you as much shocked as I was on its first sight?</b> You are not? OK, I will explain my abomination - every declaration had to be commented! And that's not enough - the comments are essential in understanding the purpose of each member!<div><br /></div><div>Why I do not like it, you might ask? Well, I'm lazy and commenting each declaration seems like too much work... You might ask 'why?' again - well, if I would like to add some definition to this code, I'd have to write a comment as well in order to maintain the (arguably flawed) coding style! I'm only a service provider for my client and wouldn't like to break this code's look and feel.</div><div><br /></div><div>As you might know I'm <b>not a friend of the newfangled "no comments" politics</b>, but this is an example where we could definitevely use some of it. But why's that so bad again? It's because you could fix the example code with careful usage of naming* and it's even not that difficult! </div><div><br /></div><div>Let's have a go at it:</div>
<pre class="brush: cpp"> /* State m_state => */ State m_dateValidity;</pre>
<div>here we don't have to include "state" in the name, as it is already stated as the domain of the variable.</div>
<pre class="brush: cpp"> /* QAction* m_action => */ QAction* m_datePickerPopupAction;</pre>
Here, however, we somehow inconsistently included "Action" in the member's name mainly because of my vague gut feeling. In this instance we could indeed try to improve the naming by considering shortening it, maybe even to <i>m_datePickerAction</i>;<pre class="brush: cpp"> /* QDate m_date => */ QDate m_parsedDate;</pre>
A no-brainer.<pre class="brush: cpp"> /* QStringList m_parseFormats => */ QStringList m_dateParsingFormats;</pre>
Another one!<pre class="brush: cpp"> /* bool m_twoYearIsPast => */ bool m_treat2DigitYearsAsPast;</pre>
Here we could try to make the name a little better - maybe <i>m_twoDigitYearsInThePast</i>? <pre class="brush: cpp"> /* QDate m_minDate => */ QDate m_earliestDate;</pre>
As minimum and maximum are't commonly used with dates.<pre class="brush: cpp"> /* QDate m_maxDate => */ QDate m_latestDate;</pre>
Idem.<pre class="brush: cpp"> /* bool m_justFocused => */ bool m_focusReceived; // used for workaround ABC... </pre>
Here I see the only place where a comment is needed.<div><br /></div><div>So, what do you say? <b>It wasn't even that difficult. </b>Arguably the result isn't perfect but it's a lot better than the original. Maybe it's even good enough? </div><div><b><br /></b></div><div>So watch your names, they are important - because code readibility is important!</div><div><br /><div><div>--</div><div>* As they say -"there are only 2 hard problem in comp. sci. - cache invalidation and naming things"...<br /><div><br /></div></div></div></div>Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-60040569936436033702020-05-11T02:54:00.000-07:002020-05-12T01:01:24.179-07:00A technique for connection checking in Qt<a href="https://1.bp.blogspot.com/-XBumVqjYtwM/Xma8K81cxuI/AAAAAAAAAy4/HjZdlDwSbJoBXXbhFQEG6a-6_JY2zp2EQCPcBGAYYCw/s1600/Chap%2B2%2B-%2BQmlWithModel%2B-%2BSM-SM-2.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="511" data-original-width="641" height="159" src="https://1.bp.blogspot.com/-XBumVqjYtwM/Xma8K81cxuI/AAAAAAAAAy4/HjZdlDwSbJoBXXbhFQEG6a-6_JY2zp2EQCPcBGAYYCw/s200/Chap%2B2%2B-%2BQmlWithModel%2B-%2BSM-SM-2.jpg" width="200" /></a><br />
Recently, I stumbled upon a technique for checking if the <i>connect()</i> call for Qt signals/slots was successfull. You may ask what the problem is - just check the result of the call, how difficult can that be?<br />
<pre class="brush: cpp"> bool ok = connect(...);
Q_ASSERT(ok);</pre>
This doesn't look as it's much! However, in a standard Qt project you won't see that because it doesn't scale really well. What you'll normally see is this:<br />
<pre class="brush: cpp"> connect(a, SIGNAL(...), b, SLOT(...));
connect(c, SIGNAL(...), d, SLOT(...));
connect(e, SIGNAL(...), f, SLOT(...));
// etc..</pre>
Repeated insertions of <i>Q_ASSERT(ok)</i> would kill readability in such case! In a couple of projects I've seen that people were trying somehow to have the cake and eat it - do not sacrifice readibility but nonetheless report a failed connect. This was done by means of custom Qt builds, where the <i>connect() </i>function was changed to include an assert or to throw an exception in case of failure.<br />
<br />
<b>Digression: </b>I'm normally not a fan of exceptions but here they seem to be perfect a perfect match, don't they? Just signal some error condition without polluting the code with error handling! What's here not to love? But on a closer inspection it poses problem in Release builds, as in production environment we do not want to crash a program when some connection are not right. Ok, with enough testing and exception handling code it's not a problem, but asserts are a much simpler method to achieve the same goal.<br />
<br />
<span style="font-size: large;">Technique:</span><br />
<br />
So let us proceed to the advertised technique:
<br />
<pre class="brush: cpp"> v << connect(...);</pre>
How is the shift omperator implemented? Let's have a look:<br />
<pre class="brush: cpp"> ConnectionVerifier& ConnectionVerifier::operator<<(const QMetaObject::Connection& connection)
{
verify(connection);
return *this;
}
void ConnectionVerifier::verify(const QMetaObject::Connection& connection)
{
const bool connected = (connection != nullptr);
//Q_ASSERT(connected);
if (!connected)
{
throw Exception("Could not establish signal-slot connection.");
}
}
</pre>
Now we can easily scale:<br />
<pre class="brush: cpp"> v << connect(a, SIGNAL(...), b, SLOT(...));
v << connect(c, SIGNAL(...), d, SLOT(...));
v << connect(e, SIGNAL(...), f, SLOT(...));
// etc..</pre>
Well, this is the code as I found in to be used in the project - somehow the dychotomy of exceptions and asserts we discussed before wasn't resolved by the authors. Admittedly, both alternatives have their merits.<br />
<br />
<span style="font-size: large;">Summing up:</span><br />
<br />
So will I use this technique? Well, it's most useful for the old <i>connect() </i>syntax where the signals and slots are passed as (Q)strings using the <i>SLOT() </i>and <i>SIGNAL() </i>macros - here it is very easy to accidentally misstype the name or parameters of the corresponding slot/signal, believe me,<br />
<br />
But with advent of Qt 5 we have also the modern, type-safe syntax alternative:<br />
<pre class="brush: cpp"> connect(a, &A::singnalA, b, &B::slotB);
</pre>
which I'm using quite exlusively right now. Theoretically there are some corrner cases where it also could fail, but the standard problem we had in the old days, i.e. the typos, is solved now.<br />
<br />
However, if you inherited some giant legacy Qt application wehich uses the old <i>connect()</i> syntax, you might be thankfult to have this trick up your sleeve!<br />
<br />Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com2tag:blogger.com,1999:blog-3870801931584460413.post-8512466773051898562020-05-04T03:32:00.002-07:002020-05-04T03:32:36.469-07:00Example Programs form the Qt 5 Performace Book<br />
<a href="https://1.bp.blogspot.com/-Ty14MOcct54/XJIDHu9fASI/AAAAAAAAAkQ/QAXtXV2fuj0MX1EquxZON5Hwxy2jLINWwCPcBGAYYCw/s1600/cover%2Bfrontside%2B-%2Bsm.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="138" data-original-width="110" src="https://1.bp.blogspot.com/-Ty14MOcct54/XJIDHu9fASI/AAAAAAAAAkQ/QAXtXV2fuj0MX1EquxZON5Hwxy2jLINWwCPcBGAYYCw/s1600/cover%2Bfrontside%2B-%2Bsm.jpg" /></a>Hi all! You will meanwhile probably have learned that I wrote a book about C++ program performance in the context of the Qt framework (you can have a look at the TOC <a href="http://ib-krajewski.blogspot.com/2019/02/holy-cow-i-wrote-book.html#tableofcontents">here</a>).<br />
<br />
But along the book <b>I also created quite a few example programs</b>, which, as a rule, aren't discussed in the book. Some of them are pretty nice, so I decided to write up what they are and what they do.<br />
<br />
There are two kinds of example programs in that collection: ones that illustrate some performance optimization idea, but also ones which just show how to use some of discussed Qt features. So if you want just learn some Qt usage, you might find it interesting. <b>Also if you are interested in details on the techniques mentioned in the book</b>, you'd better look into the examples, because the book didn't have place for step-by-step exlanations.<br />
<br />
<span style="font-size: large;">Chapter 1: Intro</span><br />
<br />
At the moment no code and no resources here. Sorry. Some examples for usage of basic performance techniques would fit here in nicely, so maybe in the future...<br />
<br />
<span style="font-size: large;">Chapter 2: Profiling</span><br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%202/QmlWithModel">QmlWithModel</a><br />
<br />
This is the program we will be using to show how to take advantage of profiling tools. It has a QML GUI showing all the countries where Qt is used. This list is fetched with an HTTP request from the internet:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-XBumVqjYtwM/Xma8K81cxuI/AAAAAAAAAy4/HjZdlDwSbJoBXXbhFQEG6a-6_JY2zp2EQCPcBGAYYCw/s1600/Chap%2B2%2B-%2BQmlWithModel%2B-%2BSM-SM-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="511" data-original-width="641" height="318" src="https://1.bp.blogspot.com/-XBumVqjYtwM/Xma8K81cxuI/AAAAAAAAAy4/HjZdlDwSbJoBXXbhFQEG6a-6_JY2zp2EQCPcBGAYYCw/s400/Chap%2B2%2B-%2BQmlWithModel%2B-%2BSM-SM-2.jpg" width="400" /></a></div>
<br />
As you can check in its code, we can enable:<br />
<ul>
<li> a memory leak and </li>
<li> excessive burning of CPU cycles </li>
</ul>
in order to show how to find these problems using profilers.<br />
<span style="background-color: yellow;"><br /></span>
Additionally, there's a recorded <a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/blob/master/Chapter%202/2018-09-08_11-01-57_Niedobrek.etl">ETW trace file</a> of the above application to be browsed with the <i>UI for ETW</i> tool mentioned in the book:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-9N9aGhmgSQQ/XfqyQZUhQLI/AAAAAAAAAuE/hwWakYV8dBcVOKyS1-hdJrhT3CNGUrdlQCPcBGAYYCw/s1600/Chap%2B2%2B-%2Bviewing%2BETL%2Bdatal.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="794" data-original-width="1600" height="315" src="https://1.bp.blogspot.com/-9N9aGhmgSQQ/XfqyQZUhQLI/AAAAAAAAAuE/hwWakYV8dBcVOKyS1-hdJrhT3CNGUrdlQCPcBGAYYCw/s640/Chap%2B2%2B-%2Bviewing%2BETL%2Bdatal.jpg" width="640" /></a></div>
<br />
Here you can take your time and look into different metrics which can be collected with ETL!<br />
<br />
<b>Addendum: </b>I always wanted to include an example usage of some <b>flame graph generators </b>in your code, but never got round to it. Maybe I'll find some spare time for it.<br />
<br />
<span style="font-size: large;">Chapter 3: C++ and Compilers</span><br />
<span style="font-size: large;"><br /></span>
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%203/ClassicTemplateTricks">ClassicTemplateTricks</a><br />
<br />
Here we show some of the template techniques mentioned in this chapter, e.g, expression templates for optimized string concatenation, CRTP for avoiding run-time polymorphism and compile-time calculations using recursive templates.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-fCD2uSg7jh8/Xma7Gxrz4SI/AAAAAAAAAyM/CdN7WbdohzE-nK2NxyqyrAwLlhUuoIFzgCPcBGAYYCw/s1600/Chap%2B3%2B-%2Bclassic%2Btemplate%2Btricks%2B-%2BSM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="655" data-original-width="980" height="426" src="https://1.bp.blogspot.com/-fCD2uSg7jh8/Xma7Gxrz4SI/AAAAAAAAAyM/CdN7WbdohzE-nK2NxyqyrAwLlhUuoIFzgCPcBGAYYCw/s640/Chap%2B3%2B-%2Bclassic%2Btemplate%2Btricks%2B-%2BSM.jpg" width="640" /></a></div>
<br />
<b>Addendum: </b>Because Qt 5.12 required C++11, the techniques shown in book are the ones supported by that standard. But for example the expression templates could be replaced with <b>fold expressions</b> in C++17!*<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%203/Compiler%20Explorer%20Tests">Compiler Explorer Tests</a><br />
<br />
Some code you can copy and paste into Matt Godboldt's <a href="https://godbolt.org/">Compiler Explorer</a> and look at the assembly it produces. Here we can observe such optimization as:<br />
<br />
<b>- compiler optimization examples:</b> the basic examples discussed in the book - avoidance of direct summation, elision of allocations, etc.<br />
<b><br /></b>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-Yhv1U-Gc8rA/Xma8aEEzu8I/AAAAAAAAAy8/tBWMlcfSB7E_66cy-Pqv72n6bd2RSUtFQCPcBGAYYCw/s1600/Chap%2B3%2B-%2Bcompiler%2Bexplorer%2B-%2BcompilerOptExamples%2B-%2BSM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1007" data-original-width="1335" height="482" src="https://1.bp.blogspot.com/-Yhv1U-Gc8rA/Xma8aEEzu8I/AAAAAAAAAy8/tBWMlcfSB7E_66cy-Pqv72n6bd2RSUtFQCPcBGAYYCw/s640/Chap%2B3%2B-%2Bcompiler%2Bexplorer%2B-%2BcompilerOptExamples%2B-%2BSM.jpg" width="640" /></a></div>
<b><br /></b>
<br />
<b><br /></b>
<b>- constexpr factorial: </b>here you can see the proof that a factorial can be calcualted at comple time! This time without templates, but using <i>constexpr</i> instead!<br />
<b><br /></b>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-xmmAnNep9yI/Xma8aPnmj6I/AAAAAAAAAzA/zLdLN5f51JUL98Lfw0nn6l4YiHKlPeqWACPcBGAYYCw/s1600/Chap%2B3%2B-%2Bcompiler%2Bexplorer%2B-%2BconstexprFactorial%2B-%2BSM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="678" data-original-width="1334" height="324" src="https://1.bp.blogspot.com/-xmmAnNep9yI/Xma8aPnmj6I/AAAAAAAAAzA/zLdLN5f51JUL98Lfw0nn6l4YiHKlPeqWACPcBGAYYCw/s640/Chap%2B3%2B-%2Bcompiler%2Bexplorer%2B-%2BconstexprFactorial%2B-%2BSM.jpg" width="640" /></a></div>
<br />
<b>- constexpr hash: </b>and here is the equivalent proof for a compile-time hash function!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-uCDXb2Jk8y0/Xma8aOcuyYI/AAAAAAAAAzI/jdQfHNDjeKEkjJPj6KAIR45A3z6ynekIACPcBGAYYCw/s1600/Chap%2B3%2B-%2Bcompiler%2Bexplorer%2B-%2BconstexprHash%2B-%2BSM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="999" data-original-width="1335" height="478" src="https://1.bp.blogspot.com/-uCDXb2Jk8y0/Xma8aOcuyYI/AAAAAAAAAzI/jdQfHNDjeKEkjJPj6KAIR45A3z6ynekIACPcBGAYYCw/s640/Chap%2B3%2B-%2Bcompiler%2Bexplorer%2B-%2BconstexprHash%2B-%2BSM.jpg" width="640" /></a></div>
<br />
<b><br /></b>
<b>- restrict and pure:</b> here we can see how the <i>restriced </i>and <i>pure </i>attributes can guide the compiler for better optimization and how it's absence worsens the generated code. Unfortunately these attributes are only avaliable as compiler extensions.<br />
<b><br /></b>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-xbAAimohO18/Xma8a43CT9I/AAAAAAAAAzE/uisSPfHTleEYzMnWYf8oIJljJbNpqtWLACPcBGAYYCw/s1600/Chap%2B3%2B-%2Bcompiler%2Bexplorer%2B-%2BrestictAndPure%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1002" data-original-width="1333" height="480" src="https://1.bp.blogspot.com/-xbAAimohO18/Xma8a43CT9I/AAAAAAAAAzE/uisSPfHTleEYzMnWYf8oIJljJbNpqtWLACPcBGAYYCw/s640/Chap%2B3%2B-%2Bcompiler%2Bexplorer%2B-%2BrestictAndPure%2B-%2BSM%2B.jpg" width="640" /></a></div>
<b><br /></b>
<br />
<b>- UB examples: </b>here we have a few UB cases mentioned in the book<br />
<b><br /></b>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-VlHpdMB-hSk/Xma8bS6qNSI/AAAAAAAAAzI/1dJUjawRJugL6V5u594PBl9CDhCZIKulgCPcBGAYYCw/s1600/Chap%2B3%2B-%2Bcompiler%2Bexplorer%2B-%2BubOptExamples%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1006" data-original-width="1337" height="480" src="https://1.bp.blogspot.com/-VlHpdMB-hSk/Xma8bS6qNSI/AAAAAAAAAzI/1dJUjawRJugL6V5u594PBl9CDhCZIKulgCPcBGAYYCw/s640/Chap%2B3%2B-%2Bcompiler%2Bexplorer%2B-%2BubOptExamples%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
So just grab the snippets from example files, paste them into Compile Explorer an see live how different compilers optimize your code behind the curtains!<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%203/MemoryMgmExamples">MemoryMgmExamples</a> - these are examples of a custom memory managers and allocators. They will trace to <i>cout</i> to show when they are used:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-IiLoqb3mk9w/Xma7kVo2YJI/AAAAAAAAAyU/ovxCGeEk0n43ZekjpZ-4vivR6D5tWnRQgCPcBGAYYCw/s1600/Chap%2B3%2B-%2Bmemory%2Bmgm%2Bexamples%2B-SM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="567" data-original-width="985" height="368" src="https://1.bp.blogspot.com/-IiLoqb3mk9w/Xma7kVo2YJI/AAAAAAAAAyU/ovxCGeEk0n43ZekjpZ-4vivR6D5tWnRQgCPcBGAYYCw/s640/Chap%2B3%2B-%2Bmemory%2Bmgm%2Bexamples%2B-SM.jpg" width="640" /></a></div>
<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%203/MoveTest">MoveTest</a> - in a similar manner, an example usage of the move semantics, also tracing to show that it's working:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-iPQWAvOHSDM/Xma752BDoRI/AAAAAAAAAyg/MSBQj9w9T7IijJj14unC-1oBHhTUGGIcwCPcBGAYYCw/s1600/Chap%2B3%2B-%2Bmove%2Btest%2B-%2BSM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="587" data-original-width="977" height="384" src="https://1.bp.blogspot.com/-iPQWAvOHSDM/Xma752BDoRI/AAAAAAAAAyg/MSBQj9w9T7IijJj14unC-1oBHhTUGGIcwCPcBGAYYCw/s640/Chap%2B3%2B-%2Bmove%2Btest%2B-%2BSM.jpg" width="640" /></a></div>
<br />
<br />
<span style="font-size: large;">Chapter 4: Data Structs and Algorithms</span><br />
<span style="font-size: large;"><br /></span><a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%204/Interning">Interning of strings</a> - an example implementation of string interning. As this would be to detailed to explain in the book, I just provided some code for the curious to read through:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-2JbgDTey1Wo/XmbAf1f13UI/AAAAAAAAAzY/rCz-jEyIUJ84wONglIxrJOn1tlzUegGugCPcBGAYYCw/s1600/Chap%2B4%2B-%2Binterning%2B-%2B%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="983" height="426" src="https://1.bp.blogspot.com/-2JbgDTey1Wo/XmbAf1f13UI/AAAAAAAAAzY/rCz-jEyIUJ84wONglIxrJOn1tlzUegGugCPcBGAYYCw/s640/Chap%2B4%2B-%2Binterning%2B-%2B%2BSM%2B.jpg" width="640" /></a></div>
<br />
Addendum: with Visual Studio compiler we can activate string pooling <a href="https://docs.microsoft.com/en-us/cpp/build/reference/gf-eliminate-duplicate-strings?view=vs-2019">option </a>to automatically remove duplicate strings!<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%204/Schwartzian">Schwartzian transform</a> - here we are using the ominous Schwarzian transforrm to paint triangles and christmas trees 🎄!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-JBeH14MOOPo/XmbAsRWmcFI/AAAAAAAAAzg/1euiuzVc3XcQgllHlbfUQw4FzGDK_fO5wCPcBGAYYCw/s1600/Chap%2B4%2B-%2Bschwartzian%2B-%2BSM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="676" data-original-width="982" height="440" src="https://1.bp.blogspot.com/-JBeH14MOOPo/XmbAsRWmcFI/AAAAAAAAAzg/1euiuzVc3XcQgllHlbfUQw4FzGDK_fO5wCPcBGAYYCw/s640/Chap%2B4%2B-%2Bschwartzian%2B-%2BSM.jpg" width="640" /></a></div>
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%204/StdSearch">StdSearch</a> - here we show the usage of the new C++17 Boyer-Moore searcher<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-AbaJOMC-P-Q/XmbBKh2NeHI/AAAAAAAAAzw/PZldXqBRTKodzUpO8s8ZCFvEsdYMstiRACPcBGAYYCw/s1600/Chap%2B4%2B-%2BStdSearch%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="669" data-original-width="1024" height="418" src="https://1.bp.blogspot.com/-AbaJOMC-P-Q/XmbBKh2NeHI/AAAAAAAAAzw/PZldXqBRTKodzUpO8s8ZCFvEsdYMstiRACPcBGAYYCw/s640/Chap%2B4%2B-%2BStdSearch%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
<br />
<span style="font-size: large;">Chapter 5: Multithreading</span><br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%205/ActiveObject">ActiveObject</a> - an implementation of the <i>"Active Object"</i> pattern. You surely remember that we can use this pattern to implement a (nearly) share-nothing multithreading scheme, do you?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-4qI07u7lty8/XmbA1-gC4lI/AAAAAAAAAzk/sz8w6C5s5GYaRvpm5F-GnI1RswkEyFlAwCPcBGAYYCw/s1600/Chap%2B5%2B-%2BActiveObject%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="671" data-original-width="982" height="436" src="https://1.bp.blogspot.com/-4qI07u7lty8/XmbA1-gC4lI/AAAAAAAAAzk/sz8w6C5s5GYaRvpm5F-GnI1RswkEyFlAwCPcBGAYYCw/s640/Chap%2B5%2B-%2BActiveObject%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%205/ConcurrentAndFutures">ConcurrentAndFutures</a> - here we load images asynchronously using futures and can compare this to a simple synchronous loading strategy by pressing the <i>"Load All at Once"</i> button:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-EXIFfKbLGZs/XmbBZMbZmbI/AAAAAAAAAz8/7bDy19p64YsqQ5B1kp1E1d-OrXmV41Q9gCPcBGAYYCw/s1600/Chap%2B5%2B-%2BConcurrentAndFutures%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="669" data-original-width="1038" height="412" src="https://1.bp.blogspot.com/-EXIFfKbLGZs/XmbBZMbZmbI/AAAAAAAAAz8/7bDy19p64YsqQ5B1kp1E1d-OrXmV41Q9gCPcBGAYYCw/s640/Chap%2B5%2B-%2BConcurrentAndFutures%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%205/QFutureInterfaceExample">QFutureInterfaceExample</a> - this is an example explaining usage of the undocumented QFutureInterface class which is widely used in Qt Creator<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-5jiLWv23zLE/XmbBextGhsI/AAAAAAAAA0A/3vXcfduyqLQsRF_ao_zQPIXijH9gqAnIgCPcBGAYYCw/s1600/Chap%2B5%2B-%2BQFutureInterfaceExample%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="671" data-original-width="1227" height="348" src="https://1.bp.blogspot.com/-5jiLWv23zLE/XmbBextGhsI/AAAAAAAAA0A/3vXcfduyqLQsRF_ao_zQPIXijH9gqAnIgCPcBGAYYCw/s640/Chap%2B5%2B-%2BQFutureInterfaceExample%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%205/ThreadsAndTimers">ThreadsAndTimers</a> - basic example for starting timers in threads (because it can be somehow confusing)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-sosrisx3ykU/XmbBnd0pPdI/AAAAAAAAA0E/_wDSIrhajHwoAZHuUbcNFQ65CIBCYoB9gCPcBGAYYCw/s1600/Chap%2B5%2B-%2BThreadsAndTimers%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="670" data-original-width="984" height="434" src="https://1.bp.blogspot.com/-sosrisx3ykU/XmbBnd0pPdI/AAAAAAAAA0E/_wDSIrhajHwoAZHuUbcNFQ65CIBCYoB9gCPcBGAYYCw/s640/Chap%2B5%2B-%2BThreadsAndTimers%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
<span style="font-size: large;">Chapter 6: Case Studies</span><br />
<br />
In this chapter we could do with some more examples, don't you think? Because we have only this single one:<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%206/SvgCache">SvgCache</a> - here I show an implementation for the SVG cache we discussed in 6.4.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-4u-AF8lwouk/XmgFAsj1CpI/AAAAAAAAA0Q/Ayyf5M7hx488nA1BLmSJ1b0uHWey6bOogCPcBGAYYCw/s1600/Chap%2B6%2B-%2BSvgCache%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="670" data-original-width="1055" height="406" src="https://1.bp.blogspot.com/-4u-AF8lwouk/XmgFAsj1CpI/AAAAAAAAA0Q/Ayyf5M7hx488nA1BLmSJ1b0uHWey6bOogCPcBGAYYCw/s640/Chap%2B6%2B-%2BSvgCache%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
<br />
<span style="font-size: large;">Chapter 7: I/O and Parsing</span><br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%207/JsonExample">JsonExample</a> - example of basic JSON parsing, nothing special, I know<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-uvPqPSE3fZI/XmgFUlfwMUI/AAAAAAAAA0c/D6oY4iQmUWsulqJXquq_QqDXF3_Atf4pgCPcBGAYYCw/s1600/Chap%2B7%2B-%2BJsonExample%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="752" data-original-width="1058" height="454" src="https://1.bp.blogspot.com/-uvPqPSE3fZI/XmgFUlfwMUI/AAAAAAAAA0c/D6oY4iQmUWsulqJXquq_QqDXF3_Atf4pgCPcBGAYYCw/s640/Chap%2B7%2B-%2BJsonExample%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%207/MemMappedFile">MemMappedFile</a> - a hands-on demonstration of how to map a file onto memory:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-KkrSxAecYfE/XmgFbO34SeI/AAAAAAAAA0k/mbdAWgFDDzA6nl-bTut_EqD6EtvcBlqlQCPcBGAYYCw/s1600/Chap%2B7%2B-%2BMemMapedFile%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="670" data-original-width="1144" height="374" src="https://1.bp.blogspot.com/-KkrSxAecYfE/XmgFbO34SeI/AAAAAAAAA0k/mbdAWgFDDzA6nl-bTut_EqD6EtvcBlqlQCPcBGAYYCw/s640/Chap%2B7%2B-%2BMemMapedFile%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%207/SqlLiteExample">SqlLiteExample</a> - shows example usage of the SQLite database.<br />
<br />
First we have to create the DB offline:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-y278JTWfjaE/XmgFlqyyVGI/AAAAAAAAA0s/5jABFP3Af9I1_7kSP_OzpdWlGumXNidtwCPcBGAYYCw/s1600/Chap%2B7%2B-%2BSqlLiteExample%2B-%2Bcreate%2Bdatbase%2B-%2BSM-SM-2%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="128" data-original-width="962" height="84" src="https://1.bp.blogspot.com/-y278JTWfjaE/XmgFlqyyVGI/AAAAAAAAA0s/5jABFP3Af9I1_7kSP_OzpdWlGumXNidtwCPcBGAYYCw/s640/Chap%2B7%2B-%2BSqlLiteExample%2B-%2Bcreate%2Bdatbase%2B-%2BSM-SM-2%2B.jpg" width="640" /></a></div>
<br />
then we wil perform some simple SQL manipulations on it:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-kwZh7mWA9nI/XmgFsbSA-rI/AAAAAAAAA0w/338u1BYvkgAthJx0WDxU9qkYC5AlCL__gCPcBGAYYCw/s1600/Chap%2B7%2B-%2BSqlLiteExample%2B-%2Brun%2Bprogram%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="668" data-original-width="983" height="434" src="https://1.bp.blogspot.com/-kwZh7mWA9nI/XmgFsbSA-rI/AAAAAAAAA0w/338u1BYvkgAthJx0WDxU9qkYC5AlCL__gCPcBGAYYCw/s640/Chap%2B7%2B-%2BSqlLiteExample%2B-%2Brun%2Bprogram%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%207/StreamReaderExample">StreamReaderExample</a> - again a basic example: parsing XML data this time<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-l21ImVkMjYs/XmgF9iyH-2I/AAAAAAAAA1M/8TtJXE9Nhzkupv8dhL1Ib6Zhrs0ZjzhbwCPcBGAYYCw/s1600/Chap%2B7%2B-%2BStreamReaderExample%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="670" data-original-width="1149" height="372" src="https://1.bp.blogspot.com/-l21ImVkMjYs/XmgF9iyH-2I/AAAAAAAAA1M/8TtJXE9Nhzkupv8dhL1Ib6Zhrs0ZjzhbwCPcBGAYYCw/s640/Chap%2B7%2B-%2BStreamReaderExample%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
<span style="font-size: large;"><br /></span>
<span style="font-size: large;">Chapter 8: Graphics</span><br />
<br />
These examples mainly illustrate the discussion of various Qt graphic interfaces, but the minimal FPS counter can be used as a performance tool as well.<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%208/CustomQmlElementsTest">CustomQmlElementsTest</a> - here we paint a simple triangle in QML using several ways to define our own, custom QML element. The <i>FrameBufferTriangle </i>uses custom OpenGL painting on current OpenGL context.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-h3XjaxfSLe0/XmgGEEx8qjI/AAAAAAAAA1E/UUcqQtAVIaku9IQ86ogYIMPiROeUvuw2gCPcBGAYYCw/s1600/Chap%2B8%2B-%2BCustomQmlElementsTest%2B-%2BSM-SM-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="513" data-original-width="642" height="510" src="https://1.bp.blogspot.com/-h3XjaxfSLe0/XmgGEEx8qjI/AAAAAAAAA1E/UUcqQtAVIaku9IQ86ogYIMPiROeUvuw2gCPcBGAYYCw/s640/Chap%2B8%2B-%2BCustomQmlElementsTest%2B-%2BSM-SM-2.jpg" width="640" /></a></div>
<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%208/FpsCounterExample">FpsCounterExample</a> - want to know how to implement a <b>live FPS counter</b> for your application? Here we use a particle system to stress the QML runtime measure (and display it in an extra widget!) the FPS rate that can we are able to achieve:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/--apX0Jsb9mQ/XmgGKN9uZXI/AAAAAAAAA1M/9LTBjjSh4K4qpdsgKnYc946_VxQOlS3swCPcBGAYYCw/s1600/Chap%2B8%2B-%2BFpsCounterExample%2B-%2BSM-SM-2%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="744" height="440" src="https://1.bp.blogspot.com/--apX0Jsb9mQ/XmgGKN9uZXI/AAAAAAAAA1M/9LTBjjSh4K4qpdsgKnYc946_VxQOlS3swCPcBGAYYCw/s640/Chap%2B8%2B-%2BFpsCounterExample%2B-%2BSM-SM-2%2B.jpg" width="640" /></a></div>
<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%208/OpenGLWidgetExample">OpenGLWidgetExample</a> - we use Qt's OpenGL support for widgets to draw this classic triangle picture:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-bAFNW_TIjRE/XmgGQUKI7RI/AAAAAAAAA1Q/hfm17I-DsCM5_hFRduSDvKtlkxiOxAKcwCPcBGAYYCw/s1600/Chap%2B8%2B-%2BOpenGLWidgetExample%2B-%2Brun%2Bprogram%2B-%2BSM-SM-2%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="333" data-original-width="404" height="328" src="https://1.bp.blogspot.com/-bAFNW_TIjRE/XmgGQUKI7RI/AAAAAAAAA1Q/hfm17I-DsCM5_hFRduSDvKtlkxiOxAKcwCPcBGAYYCw/s400/Chap%2B8%2B-%2BOpenGLWidgetExample%2B-%2Brun%2Bprogram%2B-%2BSM-SM-2%2B.jpg" width="400" /></a></div>
<br />
It used the most basic (and old...) OpenGL 1.0 API, but hey, this book isn't a graphic tutorial - I just needed this picture for the explanations of how the graphics pipeline is working. Please bear with me.<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%208/Qt3DSphereExample">Qt3DSphereExample</a> - look what is possible with Qt 3D! We animate a rotating sphere using the Phong lighting model:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-uYG0-W-vWXY/XmgGW96NL6I/AAAAAAAAA1c/tt5D9gGO_xkaMGgJ6KkYTYkJWfpag3QzACPcBGAYYCw/s1600/Chap%2B8%2B-%2BQt3DSphereExample%2B-%2BSM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="695" data-original-width="1213" height="366" src="https://1.bp.blogspot.com/-uYG0-W-vWXY/XmgGW96NL6I/AAAAAAAAA1c/tt5D9gGO_xkaMGgJ6KkYTYkJWfpag3QzACPcBGAYYCw/s640/Chap%2B8%2B-%2BQt3DSphereExample%2B-%2BSM.jpg" width="640" /></a></div>
<br />
It is also a very basic program, but the result is rather cool (at least for me).<br />
<span style="font-size: large;"><br /></span>
<span style="font-size: large;">Chapter 9: Networking</span><br />
<br />
Here I wanted to write some basic demonstrators running client and server on the same machine to show basic usage of TCP sockets and HTTP transport mechanism.<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%209/EchoServerTcpExample">EchoServerTcpExample</a> - an echo server: the client will connect on a given port and the server will echo every data it receives from client!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-t8VSqWdW0IY/XmgGhcYSv1I/AAAAAAAAA1g/sqTG6eJKC4geAD5VD5kT4sk_H6K3G4MWACPcBGAYYCw/s1600/Chap%2B9%2B-%2BEchoServerTcpExample%2B-%2BSM-SM2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="331" data-original-width="454" height="290" src="https://1.bp.blogspot.com/-t8VSqWdW0IY/XmgGhcYSv1I/AAAAAAAAA1g/sqTG6eJKC4geAD5VD5kT4sk_H6K3G4MWACPcBGAYYCw/s400/Chap%2B9%2B-%2BEchoServerTcpExample%2B-%2BSM-SM2.jpg" width="400" /></a></div>
<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%209/HttpDownloadExample">HttpDownloadExample</a> - here we will connect to a given web address, then fetch and save some resources from there. Additionally, the progress of file download is visualised with a progress bar.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-CIVtu-nwbqs/XmgGmAPWQnI/AAAAAAAAA1o/BPYY29oT0SADFtVOjc_HSPZIAZsJWTDqgCPcBGAYYCw/s1600/Chap%2B9%2B-%2BHttpDownloadExample%2B-%2BSM-SM-2%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="331" data-original-width="513" height="257" src="https://1.bp.blogspot.com/-CIVtu-nwbqs/XmgGmAPWQnI/AAAAAAAAA1o/BPYY29oT0SADFtVOjc_HSPZIAZsJWTDqgCPcBGAYYCw/s400/Chap%2B9%2B-%2BHttpDownloadExample%2B-%2BSM-SM-2%2B.jpg" width="400" /></a></div>
<br />
If you have Python installed on your machine, you could start a local web server on some directory and then run this testapp locally. As I mentioned in the book, Qt doesn't have a HTTP server component and doesn't allow us to easily write one.**<br />
<span style="font-size: large;"><br /></span>
<span style="font-size: large;">Chapter 10: Mobile and Embedded</span><br />
<br />
Here we do not have much resources (sorry, publisher's deadline didn't allow that 😒) but at least one example pertinent to embedded data presentation could be included.<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%2010/OpenGLAcceleratedChart">OpenGLAcceleratedChart</a> - an example of using OpenGL acceleration with Qt Charts. You can parametrize the number of points if you want to stress your hardware!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-pRTe0eBWlSI/XmgGziiKPGI/AAAAAAAAA1w/C__Or_3RSdQameS5UemJvKhIOLd6vnuIQCPcBGAYYCw/s1600/Chap%2B10%2B-%2BOpenGLAcceleratedChart%2B-%2BSM-SM-2%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="615" data-original-width="691" height="355" src="https://1.bp.blogspot.com/-pRTe0eBWlSI/XmgGziiKPGI/AAAAAAAAA1w/C__Or_3RSdQameS5UemJvKhIOLd6vnuIQCPcBGAYYCw/s400/Chap%2B10%2B-%2BOpenGLAcceleratedChart%2B-%2BSM-SM-2%2B.jpg" width="400" /></a></div>
<br />
There is another example implementation I should have provided is the <b>polyline simplification</b>, but due to time shortages I missed out on this one. But at least I provided you with this link: <a href="https://www.kdab.com/a-speed-up-for-charting-on-embedded/%C2%A0">https://www.kdab.com/a-speed-up-for-charting-on-embedded/</a>, which describes the implementation of a polyline simplification technique that uses a flattened min-max tree.<br />
<br />
<b>Addendum:</b> If I'll find some time, I could add some example project for my Raspberry-Pi, as I was initially planning. You know, the deadlines etc... :-\.<br /><br /><span style="font-size: large;">Chapter 11: Testing and Deploying</span><br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%2011/ExampleSubdirProjectWithTests">ExampleSubdirProjectWithTests</a> - this is an example of how to add tests to an existing project using the Qt Creator:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-pD6hD5KkrRU/XmgHElI6miI/AAAAAAAAA18/At8FTKdRKvAR0hKWmdzANn_HoDeHwONWgCPcBGAYYCw/s1600/Chap%2B11%2B-%2BExampleSubdirProjectWithTests%2B-%2Btest%2B-SM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="760" data-original-width="979" height="496" src="https://1.bp.blogspot.com/-pD6hD5KkrRU/XmgHElI6miI/AAAAAAAAA18/At8FTKdRKvAR0hKWmdzANn_HoDeHwONWgCPcBGAYYCw/s640/Chap%2B11%2B-%2BExampleSubdirProjectWithTests%2B-%2Btest%2B-SM%2B.jpg" width="640" /></a></div>
<br />
The tests are wiritten using QTest library, and integrate nicely with Qt Creator's UI, as you can see on the above figure. Also a minimal Qt application is created to be tested here and in the Squish tests below.<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%2011/SimplestQMLProject">SimplestQMLProject</a> - this one is a very simple QML project we will need in the example Squish tests below.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-FYxX6l6Yvuk/XmgG9H49n_I/AAAAAAAAA18/QAOd6tXW9gAUjSIN9Rwd_Yxa0hES0NUvACPcBGAYYCw/s1600/Chap%2B11%2B-%2BExampleSubdirProjectWithTests%2B-%2Bprogram%2B-%2BSM%2B.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="646" data-original-width="1138" height="362" src="https://1.bp.blogspot.com/-FYxX6l6Yvuk/XmgG9H49n_I/AAAAAAAAA18/QAOd6tXW9gAUjSIN9Rwd_Yxa0hES0NUvACPcBGAYYCw/s640/Chap%2B11%2B-%2BExampleSubdirProjectWithTests%2B-%2Bprogram%2B-%2BSM%2B.jpg" width="640" /></a></div>
<br />
<br />
<a href="https://github.com/mrkkrj/Hands-On-High-performance-with-QT/tree/master/Chapter%2011/Squish">Squish</a> - here we have a definition of Squish tests for both Widgets and QML applications we've introduced above:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-z4cGVUkP6lc/XmgHNOYVjzI/AAAAAAAAA2A/t9u4wxFH8cMK7JPilDT0gz71mrh0zrYVACPcBGAYYCw/s1600/Chap%2B11%2B-%2BSquish%2B-%2BSM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="747" data-original-width="1145" height="416" src="https://1.bp.blogspot.com/-z4cGVUkP6lc/XmgHNOYVjzI/AAAAAAAAA2A/t9u4wxFH8cMK7JPilDT0gz71mrh0zrYVACPcBGAYYCw/s640/Chap%2B11%2B-%2BSquish%2B-%2BSM.jpg" width="640" /></a></div>
<br />
<span style="font-size: large;">Summing Up</span><br />
<br />
So, that's all. I hope you've found something interesting there!<br />
<br />
---<br />
* expression templates can be replaced with fold expressions (C++17) for string concatenation, as shown in this post: <a href="https://www.qt.io/blog/efficient-qstring-concatenation-with-c17-fold-expressions">https://www.qt.io/blog/efficient-qstring-concatenation-with-c17-fold-expressions</a><br />
<br />
** e.g. I couldn't port my old Qt4-based embeddable <a href="https://github.com/mrkkrj/yawf4q">web server project</a> to Qt5 because of removal of HTTP parsing classes.<br />
<br />Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com2tag:blogger.com,1999:blog-3870801931584460413.post-88689771671571495832020-04-04T07:32:00.002-07:002022-01-07T00:36:02.924-08:00My answer to a young programmer<a href="https://1.bp.blogspot.com/-ZN0TKdAQn5g/TBZaLvLFdbI/AAAAAAAAAGE/y-2AW-bD62s3kyttAJpSie7kVB-RHDvhACPcBGAYYCw/s1600/estimate.jpg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="588" data-original-width="705" height="166" src="https://1.bp.blogspot.com/-ZN0TKdAQn5g/TBZaLvLFdbI/AAAAAAAAAGE/y-2AW-bD62s3kyttAJpSie7kVB-RHDvhACPcBGAYYCw/s200/estimate.jpg" width="200" /></a><br />
You maybe know that I offer C++ mentoring via Twitter (DMs are open!) and, as it happened, someone approached me and wanted to be mentored. So I asked him for his questions and then wrote some responses, which ended up to to be qute long... Then the idea to share what I wrote in this blog - maybe someonw will find it interesing.<br />
<br />
Without much ado, to the questions.<br />
<br />
<span style="font-size: large;">1. Questions</span><br />
<br />
I first asked about the goals. Thes answers are probably in line with many young programmers want:<br />
<blockquote class="tr_bq">
<i>1. I just need to be able to solve programming problems and strong myself in<br />this part, to be qualified for big tech companies interviews like Google,<br />Microsoft and Amazon. </i></blockquote>
<blockquote class="tr_bq">
<i>2. No the programming language doesn't matter for me, I know the basics of C, C++ and Python but I just want to be a problem solver and think like a programmer </i></blockquote>
<blockquote class="tr_bq">
<i>3. I just want to understand the theory behind Algorithms and Data Structure</i></blockquote>
Then also came a list of resources that one finds on the internet using uncle Google. I won't show them here, as thea are quoted in the response.<br />
<br />
<span style="font-size: large;">2 The Response</span><br />
<div>
<br /></div>
<div>
Here's my response, in full, without any later editing:<br />
<blockquote class="tr_bq">
Hi Xyz!<br />
<br />
I had a look at your references:<br />
<br />
<i><b>>Courses:</b></i><br />
<i><br /></i>
<i>>Algorithms and Data structures by Revi</i><br />
<i>><a href="https://youtube.com/playlist?list=PLEbnTDJUr_IeHYw_sfBOJ6gk5pie0yP-0">https://youtube.com/playlist?list=PLEbnTDJUr_IeHYw_sfBOJ6gk5pie0yP-0</a></i><br />
<br />
Here we have much complexity theory but little of algos - only basic sorting methods.<br />
<br />
<i>>Algorithms by Abdul Bari</i><br />
<i>><a href="https://youtube.com/playlist?list=PLDN4rrl48XKpZkf03iYFl-O29szjTrs_O">https://youtube.com/playlist?list=PLDN4rrl48XKpZkf03iYFl-O29szjTrs_O</a></i><br />
<br />
Don't know what to think about it's TOC - maybe too academic (too much about recurrences) but also covers a broad range of themes you'll need. So-so.<br />
<br />
<i>>MIT 6.006 Introduction to Algorithms</i><br />
<i>></i><i><a href="https://youtube.com/playlist?list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb">https://youtube.com/playlist?list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb</a></i></blockquote>
<blockquote class="tr_bq">
Had a look the TOC and liked it! If you can grasp these themes, you'll have good working knowledge of Comp.Sci.<br />
<br />
<b><i>>Books:</i></b><br />
<br />
<i>>Data Structures and Program Design in C by Robert L. Kruse</i><br />
<i>><a href="https://goodreads.com/book/show/27846.Data_Structures_and_Program_Design_in_C">https://goodreads.com/book/show/27846.Data_Structures_and_Program_Design_in_C</a></i></blockquote>
<blockquote class="tr_bq">
Looks like it's pretty old. Probably outdated, looks like waste of time.<br />
<br />
<i>>Introduction to Algorithms By Thomas H. Cormen</i><br />
<i>><a href="https://mitpress.mit.edu/books/introduction-algorithms-third-edition">https://mitpress.mit.edu/books/introduction-algorithms-third-edition</a></i><br />
<br />
This is a classic, maybe a little heavy on the academic side, but a good reference to check what the options are. For an algorithms book the <i>"The Algorithm Design Manual" </i>by Steven Skiena is a much lighter read I'd recommed!<br />
<br />
<i>>Think Like a Programmer by V. Anton Spraul</i><br />
<i>><a href="https://goodreads.com/book/show/13590009-think-like-a-programmer">https://goodreads.com/book/show/13590009-think-like-a-programmer</a></i><br />
<br />
I don't know this one. Had a look at the TOC and it can be OK or even good. It has a couple of programming problems but the title seems to be kind of a clickbait. Notheless. maybe it's good.<br />
<br />
<b><i>>Practice:</i></b><br />
<i><br /></i>
<a href="https://www.blogger.com/%3Ehttps://hackerrank.com"><i>>https://hackerrank.com</i></a><br />
<br />
Don't know this one (sorry) and couldn't check it out, as it requires a login. Back in the day Google recommended topcoder.com for testing your problem-solving skills in competitions, but I don't know the current status of it.<br />
<br />
<a href="https://www.blogger.com/%3Ehttps://leetcode.com"><i>>https://leetcode.com</i></a><br />
<br />
Don't know this one (sorry), but it looks somehow inetersting at first glance. You have specific questions for Google, Facebook, etc. Could be worth it.<br />
<br />
<b>And responses:</b><br />
<br />
<i>>I just need to be able to solve programming problems and strong myself in this part, to be qualified for big tech companies interviews like Google, Microsoft and Amazon.</i><br />
<br />
A classic book for that is <i>"Cracking the Coding Interview"</i> by Gyle Laakmann McDowell - but it's a real tome! <i>"Programming Interviews Exposed"</i> by J. Morgan et. all was a lighte read. <i>"Algorithms for Intreviews"</i> by A. Aziz & A. Prakesh has many tough problems, but the solutions aren't that well explained - a challenge!<br />
<br />
<i>>Q1: No the programming language doesn't matter for me, I know the basics of C, C++ and Python but I just want to be a problem solver and think like a programmer</i><br />
<br />
To be a (real) problem solver you need some deep knowledge in at leas one OO-langauge! Programmers think in patterns, you have to learn them by solving programming problems! On a little higher level, you'll need at least cursory knowledge in design patterns - look at the 4 Amigos book!<br />
<br />
<i>>Q2: I just want to understand the theory behind Algorithms and Data Structure</i><br />
<br />
You'll have to undertstand the O-notation at least and to be able to estimate the O-complexity of your algoriths. The Master theorem is not really needed though. You have at least to understand NP-complete complexity class (NP=P?). You'll have to be able to estimate run time of an algorithm - which algos would need thousands of years to complete?<br />
<br />
Regards,<br />
Marek</blockquote>
<div>
<span style="font-size: large;">3. Summing Up</span><br />
<br />
Hopefully some young programmer(s) will find it helpful!<br />
<br /></div>
</div>
Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-87961138719688980802020-04-04T06:59:00.001-07:002020-04-09T05:37:12.096-07:00Trip Report Qt Word Summit, Berlin, 5-6 November 2019<br />
You've probably noticed that I'm not a hell of a conference goer, didn't you? The last conference I attended was the first "Meeting C++" conference in 2014, at that time still taking place in Neuss, Rhineland* instead of the worldly and hipster Berlin.<br />
<br />
I tried to go to the two consecutive Meeting C++ conferences in Berlin, but I was both times unable to do it, so eventually I gave up and called it a day on this idea.<br />
<br />
But because recently I got somehow more seriously involved with the Qt framework** I thought, hey, why not just go to this one Qt conference*** in Berlin and visit some of my people there as well? No sooner thought than done. And now, three months something later, another idea struck me - <b>why not write up some impressions</b>? So let us go over things I came to remember most vividly.<br />
<br />
Of course you could start moaning that it is <b>much toooo late for a trip report</b>, but better late than sorry, so let us begin!<br />
<br />
<span id="lars_knolls_talk" style="font-size: large;">1. Lars Knoll's talk</span><br />
<br />
Lars Knoll, the CTO of the Qt Company was giving a talk on general directions for the future Qt 6 development and it was rather interesting. You can check it out <a href="https://conf.kde.org/system/event_attachments/attachments/000/000/112/original/Towards_Qt_6.pdf?1568789264">here (PDF)</a>, but basically QML will be reworked to be a typed programming language, Javascript will be only optional and graphics will support not only <i>OpenGL </i>but also newer APIs like <i>Vulcan</i>, <i>Metal </i>or <i>Direct3D 12</i>. All that's very interesting, but what struck me the most was the following slide: <img /><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-KtUOxkKgSfc/XkwAF7i6hFI/AAAAAAAAAvk/o2ryRMC63fA6RGvDjvYXsBvx3RtsDlM4wCLcBGAsYHQ/s1600/Lars%2BKnoll%2B-%2BQT%2Bhost%2Bplatforms%2B2019.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="569" data-original-width="1043" height="348" src="https://1.bp.blogspot.com/-KtUOxkKgSfc/XkwAF7i6hFI/AAAAAAAAAvk/o2ryRMC63fA6RGvDjvYXsBvx3RtsDlM4wCLcBGAsYHQ/s640/Lars%2BKnoll%2B-%2BQT%2Bhost%2Bplatforms%2B2019.jpg" width="640" /></a></div>
<br />
As it seems <b>Qt is predominantly used on Windows!</b> That's kind of surprising, taking into account that all the books and articles you read always assume Linux as a platform! I personally did a lot of Qt work on Windows and couldn't ever understand that.<br />
<br />
This slide gave me a nice, fuzzy feeling, because my <b>decision to write my <a href="https://www.packtpub.com/application-development/hands-high-performance-programming-qt-5">Qt book</a> from a point of view of a Windows developer was a right one!</b><br />
<br />
Other books always describe the tooling you can use on Linux, but this doesn't help me on Windows, because most of that tooling (open source) doesn't exist there. So writing of the <i>Chapter 2 </i>(Profiling and Profilers) was a kind of a discovery journey - how can I make open source tooling run and correctly work on Windows?<br />
<br />
<span style="font-size: large;">2. Keynotes</span><br />
<br />
As much as I don't like keynotes - normally they are rather full of business-y bla bla - but one slide of the Natalie Nahai's presentation really impressed me, I mean this one:<br />
<blockquote class="twitter-tweet">
<div dir="ltr" lang="es">
Un ejemplo de <a href="https://twitter.com/NathalieNahai?ref_src=twsrc%5Etfw">@NathalieNahai</a> de mejora de <a href="https://twitter.com/hashtag/UX?src=hash&ref_src=twsrc%5Etfw">#UX</a>: Más donaciones solo por cambiar la página: los botones, Obama mirando los botones.. En <a href="https://twitter.com/hashtag/QtWs19?src=hash&ref_src=twsrc%5Etfw">#QtWs19</a> <a href="https://t.co/th2eC527q8">pic.twitter.com/th2eC527q8</a></div>
— fgutierrez (@fgutierrez_) <a href="https://twitter.com/fgutierrez_/status/1191660750017708032?ref_src=twsrc%5Etfw">November 5, 2019</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
You can see the change of the vibes of a webpage from the left (boring, lots of distractions, unusable!) to right (cool, clear, using 1-click donation buttons). Nice! And it really happened during Obama's campaign.<br />
<br />
<span style="font-size: large;">3. Caliatys hydrogen mobility talk</span><br />
<br />
This one was also a keynote (or I think so...) but the CTO of the company has shown us the slide containing a decision table they used for choosing the Qt framework as a platform for mobile development. The application in question should run on both iPhone and Android device. After the recent switch of Dropbox away from a commonn C++ codebase for both platforms you would maybe expect that C++ isn't good for mobile.<br />
<br />
See their reasons for choosing Qt in the pic below:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-Za_kYMuDIN4/XkwAKpJIpZI/AAAAAAAAAvo/I8HVHvY2iOsZfHmTfAH47mimRQ1lMMrUwCLcBGAsYHQ/s1600/Caliatys%252C%2Bhydrogen%2Bmobility%2B-%2Btechnology%2Bevaluation%2B-%2Bsm.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="569" data-original-width="1027" height="354" src="https://1.bp.blogspot.com/-Za_kYMuDIN4/XkwAKpJIpZI/AAAAAAAAAvo/I8HVHvY2iOsZfHmTfAH47mimRQ1lMMrUwCLcBGAsYHQ/s640/Caliatys%252C%2Bhydrogen%2Bmobility%2B-%2Btechnology%2Bevaluation%2B-%2Bsm.jpg" width="640" /></a></div>
<br />
The cloud connector had to be written separately for each platform, apart from this Qt provided for platform-independence!<br />
<br />
<span style="font-size: large;">4. QML on Microcontrollers</span><br />
<br />
I already said, that the new QML will be a compiled, statically typed language in Qt 6. Already today, we can have a foretaste of the future with Qt Quick Ultralite (<a href="https://www.qt.io/blog/qt-for-mcus-1.0">Qt QUL</a>) that can be run on MCUs (microcontrollers) - a feat in itself, as up to this day Qt and QML needed a much more beefy processors to be run onto! There were quite a few talks centering around that theme, because it seems to be the future of Qt.<br />
<br />
Qt Quick Ultralite is thus basically<b> a subset of QML</b> which can be compiled to C++ and run on bare metal (or an RTOS). This is also a direction in which QML will be going in Qt 6. I was pleasently surprised to learn, that Qt QUL was developed by the Qt Company in cooperation with a polish enterprise that ported it to many MCUs (see the picture below 👇).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-fe9moL-C3YI/XkwARC1P65I/AAAAAAAAAvs/YTZ8Z-AFFhkrb3OJM7E9N5Zoq7TPqm_wgCLcBGAsYHQ/s1600/siili_auto.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1200" height="300" src="https://1.bp.blogspot.com/-fe9moL-C3YI/XkwARC1P65I/AAAAAAAAAvs/YTZ8Z-AFFhkrb3OJM7E9N5Zoq7TPqm_wgCLcBGAsYHQ/s400/siili_auto.jpg" width="400" /></a></div>
<br />
As it's my native country, I couldn't help but to be very pleased. Good job Poland! 😍<br />
<br />
<span id="people_and_stories" style="font-size: large;">5. People and stories</span><br />
<br />
As it goes, I stumbled upon 2 of my old clients at the conference! I tool the opportunity and asked them about how my old projects fared after I left. We had quite good chats and I wanted to talk to them on the next day also, but - you won't believe it - <b>I couldn't spot them anymore</b>! The conference is a pretty big event with masses of people and finding someone is rather matter of luck.<br />
<br />
I also could (and was honored to) meet some, i.e. two 🙂, Qt-involved people, I only knew from Twitter, in the real world. As I expected. they turned out to be very nice indeed! Plus I also wound up talking to people in the queue to the canteen and at the exhibitor stands - I even could ask Qt's CTO a question face-to-face after his talk.<br />
<br />
Now let us proceed to the <b>"stories" part of this section</b>:
<br />
<br />
<div id="perf_story">
<a href="https://1.bp.blogspot.com/-MqTYbLzQtyk/Td51zJinckI/AAAAAAAAAHE/KjN7-6QlEQ4emhpqtL3s_NQm0szb0qMTwCPcBGAYYCw/s1600/bug%2B1763.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="408" data-original-width="400" height="200" src="https://1.bp.blogspot.com/-MqTYbLzQtyk/Td51zJinckI/AAAAAAAAAHE/KjN7-6QlEQ4emhpqtL3s_NQm0szb0qMTwCPcBGAYYCw/s200/bug%2B1763.jpg" width="196" /></a>One of my customers I met at the venue told me a nice story right form the threnches, They had <b>a beast of a performance problem</b> with the embedded device in my old project (accidentally same project as in the perf. story 6.4 in the book**), namely, after a day being powered on, the device started to slow down up to a total grind - the UI became totally unresponsive and you had to reboot it. What is your guess for the reason of that?<br />
<br />
<b>Yes, you are right</b>, a memory leak.<br />
<br />
But you'll never guess what couse it! When displaying the time of the day, on every update (i.e. every second) the displayed string was changed and then restyled using CSS styles. As it turned out, there was <b>a bug in the Qt version we used </b>and restyling leaked memory at that place! <b>How could you possibly find that?!?!</b>, I asked, quite shocked. Well, it was accomplished by the old and proven method of pinching off parts of the programm until the problem disappears. A kind of <i>"divide and conquer" </i>of debugging. The solution? Quite a pragmatic one - just don't use styling in the updates. Unfortunaltely, I forgot to ask how's the look and feel of the widget now.</div>
<div>
<br /></div>
<div>
Want another story? Here we go - I met 2 guys in the queue in the canteen and chattet with them for quite a long time. At the evening, I went out with my Berlin people to their favourite craft beer bar in the neighbourhood. After a couple of pints I catched a glimple of some guy at the counter and had to ask myself - do I know that guy? No, impossible, only locals frequent this bar... But after a couple of further glimpses I just had to settle that and chatted up the guy and his friend. Guess what - they were the exact people I met at the conference. Then we had one more chat and I even could pitch my book** to them! Moral - everybody can google,<b> there isn't such a thing like a hidden gem or an insider-only venue</b>. 😔</div>
<br />
<span style="font-size: large;">6. Merchandise</span><br />
<a href="https://1.bp.blogspot.com/-q2Ezjoo9QKw/XnjYLwZbpOI/AAAAAAAAA3E/Y5Aj0pJM5RAhPL1NuQgVDz6pb9XFTcAKgCLcBGAsYHQ/s1600/IMG_20200116_093035505.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="200" src="https://1.bp.blogspot.com/-q2Ezjoo9QKw/XnjYLwZbpOI/AAAAAAAAA3E/Y5Aj0pJM5RAhPL1NuQgVDz6pb9XFTcAKgCLcBGAsYHQ/s200/IMG_20200116_093035505.jpg" width="150" /></a><br />
Of course I also got some merchandise:<br />
<ul>
<li>a Qt sticker set 📗,</li>
<li>a T-shirt and a lanyard keychain from Qt 👉,</li>
<li>sleeping mask (Batman style!) 🦇, also from Qt,</li>
<li>some small stickers from exhibitor companies </li>
</ul>
But not that much I'd expect. There was a raffle where you could win a cool drone (sponsored by one of the exhibitors), but this time I was kinda outta luck.<br />
<br />
<span style="font-size: large;">7. Summing up</span><br />
<br />
You tell me - do you think it was a good conference? The main lecture hall was very impressive in any case. An you could see the Berlin TV-tower right out of the window.<br />
<br />
---<br />
* early supporter! 🙋<br />
<br />
** see this book: <a href="https://www.packtpub.com/application-development/hands-high-performance-programming-qt-5">https://www.packtpub.com/application-development/hands-high-performance-programming-qt-5</a><br />
<br />
*** i.e. to the Qt World Summit conference. BTW, here are all QtWS-2019 videos to watch: <a href="https://resources.qt.io/qt-world-summit-2019">https://resources.qt.io/qt-world-summit-2019</a><br />
<br />Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-50136449012164158242020-02-29T03:09:00.001-08:002020-03-03T02:18:47.477-08:00Export your Qt Project from VisualStudio to CMake (...or how I stopped worrying and learned to love CMake!)<br />
<a href="https://1.bp.blogspot.com/-kIFEQ6eCKLE/XkvRCYmqygI/AAAAAAAAAvY/VerdjGpTAq0YXVZwolXZy0rR5mKY9FHdgCLcBGAsYHQ/s1600/VStudio%2Bwith%2BCmake%2B-%2Bsm%2B-%2Bsm.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="269" data-original-width="318" height="168" src="https://1.bp.blogspot.com/-kIFEQ6eCKLE/XkvRCYmqygI/AAAAAAAAAvY/VerdjGpTAq0YXVZwolXZy0rR5mKY9FHdgCLcBGAsYHQ/s200/VStudio%2Bwith%2BCmake%2B-%2Bsm%2B-%2Bsm.jpg" width="200" /></a>Yes, I know, this blog was supposed to discuss <b>the high-church themes</b> of languages and system design, and I didn't quite abandoned these goals, but at the momenet I don't have many time to write about deep and interesting things (as you guess, it's time-consuming). To make a long story short, I decided that I'll write about things <b>I'm working on/with just now</b>.<br />
<br />
So let us start with <i>CMake </i>and Qt.<br />
<br />
<span style="font-size: large;">1. Intro</span><br />
<br />
You might already have learned that in the next major Qt version (it will be Qt 6) the framework will abandon its old and trusty <i>qmake_</i>build tool and switch to <i>CMake</i>. Why's that?<br />
<br />
Although as of lately <i>CMake </i>has acquired a standard tool status in the C++ community, I don't think the desire to be with the cool crowd motivated that change. Rather (AFAIK), <i>qmake</i>'s source code developed into an unmaintainable mess, so that nobody wanted to change anything for fear of a total disaster (but feel free to correct me if I'm wrong).<br />
<br />
So, as the last alternative to <i>CMake </i>went away, I couldn't advise my client to use qmake for cross platform builds on Windows and Linux with a clear conscience, so in the current project I voted in favour of <i>CMake </i>as our build tool.<br />
<br />
You might ask yourself <i>"So what? Just use another tool!"</i>. Well, <i>CMake </i>has <b>quite a reputation for being overcomplicated and error-prone</b>. Additionally, it has a text based format, so you will have to become friends with the text editor again.<br />
<br />
Before that we could just use convenient graphical IDEs to define the structure of a project, should we lose that comfort now!? If I use Visual Studio with the Qt plugin, I can <b>just drag and drop </b>the <i>Q_OBJECT </i>files into a project and everything just jumps into its place. And what can I do if I already started out with a Visual Studio in first place (as I did in the current project, silly me)!?<br />
<br />
<span style="font-size: large;">2. Convert your Visual Studio Project</span><br />
<br />
So I was loking for some converter of Visual Studion projects and I stumbled upon the the <i>cmake-converter</i> Python tool*. I decised to give it a try and:<br />
<br />
<b>1.</b> installed Python 3 first (just googled for the installer and let ir run)<br />
<br />
<b>2.</b> Installed the last stable release of <i>cmake-converter</i>:<br />
<pre class="brush: bash"> pip install cmake-converter
</pre>
<b>3.</b> Let it run it with:<br />
<pre class="brush: bash"> cmake-converter -pi -s path/to/file.sln
</pre>
Where <i>-pi</i> means that we ant use private** includes with <i>CMake </i>and <i>-s </i>specifies a path to the soultion file. You can list all the tool's options using the <i>-h</i> switch. You will see the following output (here I used the verbose output option):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-9Ki2f-936u0/XkwA4DOQ51I/AAAAAAAAAv4/DLOlY9y5QqAut98Hrv-vvlCQ1MUbHK8iACLcBGAsYHQ/s1600/cmake-converter%2B-%2Bsm%2B-%2Bverb.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="564" data-original-width="979" height="368" src="https://1.bp.blogspot.com/-9Ki2f-936u0/XkwA4DOQ51I/AAAAAAAAAv4/DLOlY9y5QqAut98Hrv-vvlCQ1MUbHK8iACLcBGAsYHQ/s640/cmake-converter%2B-%2Bsm%2B-%2Bverb.jpg" width="640" /></a></div>
<br />
The tool will generate the <i>CMakeLists.txt </i>file as result.<br />
<br />
After reading the result file I decided to delete all the generated contents up to the "<i>Source Groups</i>" section and replaced it by my generic Qt-project prologue, i.e.:<br />
<pre class="brush: bash"> if(UNIX)
cmake_minimum_required(VERSION 3.10)
else()
cmake_minimum_required(VERSION 3.13)
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(GdmRestApiTest VERSION 0.1.0 LANGUAGES CXX)
################################################################################
# Use solution folders feature
################################################################################
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
################################################################################
# Use Qt
################################################################################
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
#set(CMAKE_AUTOUIC_SEARCH_PATHS "src/ui")
find_package(Qt5 COMPONENTS Core Widgets Gui Network REQUIRED)
</pre>
<b>Why did I do that?</b> First, the generated <i>CMake </i>file uses some custom Cmake-Tools file which was a little too complicated at the first sight, and secondly, the generated <i>CMake </i>code<b> doesn't take into account that we are using a Qt plugin!</b><br />
<br />
Thus we added the <i>AUTO-MOC/RC/UI</i> lines and the required Qt packages. However, for that to work we have to tell <i>CMake</i> where the Qt framework files are to be found. It can be done by setting an environment variable <i>CMAKE_PREFIX_PATH </i>to the directory wher the Qt CMake integration files can be found, In my case:<br />
<br />
<i> CMAKE_PREFIX_PATH=C:\Qt\Qt5.12.5\5.12.5\msvc2017_64\lib\cmake</i> .<br />
<br />
Next we need to manually add the <i>Form_Files </i>and <i>Resource_Files </i>source groups:<br />
<pre class="brush: bash"> set(Form_Files
"./GdmRestApiTest.ui"
)
source_group("Form Files" FILES ${Form_Files})
set(Resource_Files
"./GdmRestApiTest.qrc"
)
source_group("Resource Files" FILES ${Resource_Files})
</pre>
Now the generated source groups can be reused.<br />
<br />
Next we need to include the <i>Form_Files</i> and <i>Resource_Files </i>source groups in ALL_FILES so that AUTO-UI/RC can be applied:<br />
<pre class="brush: bash"> set(ALL_FILES
${Form_Files}
${Resource_Files}
${Header_Files__generated}
${Source_Files}
${Source_Files__generated}
)
</pre>
Now, all the source files of the project are specified and we can turn to the definitions needed by compiler and linker. Again I deleted the <i>Target </i>and all the consecutive sections (because, you know, too complicated...) and replaced them by my generic Qt definitions:<br />
<pre class="brush: bash"> ################################################################################
# Target
################################################################################
if(MSVC)
# set /SUBSYSTEM:WINDOWS
add_executable(${PROJECT_NAME} WIN32 ${ALL_FILES})
else()
add_executable(${PROJECT_NAME} ${ALL_FILES})
endif()
################################################################################
# Include directories
################################################################################
target_include_directories(${PROJECT_NAME} PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/../qt5cpp-openapi/client;"
"${CMAKE_CURRENT_SOURCE_DIR}/GeneratedFiles;"
)
################################################################################
# Compiler flags
################################################################################
if(MSVC)
# quiet warnings related to fopen, sscanf, etc.
target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS)
endif()
# force more warnings!
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
Wall>
$<$<CXX_COMPILER_ID:MSVC>:
/W4>)
################################################################################
# Dependencies
################################################################################
set(ADDITIONAL_LIBRARY_DEPENDENCIES
"Qt5::Core;"
"Qt5::Gui;"
"Qt5::Network;"
"Qt5::Widgets"
)
target_link_libraries(${PROJECT_NAME} PUBLIC "${ADDITIONAL_LIBRARY_DEPENDENCIES}")
</pre>
As we see, they define the executable, additional include directories, the compiler flags we need and the library dependencies for the linker. Ready!<br />
<br />
<span style="font-size: large;">3. Run your CMake project</span><br />
<br />
Now it's time to test it out. As Visual Studio has acquired support for directly working with <i>CMake </i>lately, we can use it to test our <i>CMake </i>file right away!<br />
<br />
In my Visual Studio 2019 installation (version 16.3.8, Professional) I do the following:<br />
<ul>
<li>Start Visual Studio</li>
<li>Choose "Proceed without file" in the starting screen that appears first</li>
<li>In Visual Studio's IDE I click <i>"File" > "Open" > "CMake" </i>menu item and choose the <i>CMakeLists.txt </i>file we created.</li>
<li>Now we have to wait, as Visual Studio tries to perform the "Configure" and "Generate" steps for the <i>CMakeLists.txt </i>file.</li>
<li>After that, we should be able to build the project - select the <i>CMakeLists.txt </i>file in the project panel on the left and choose "Build" in it's context menu (see the pic below).</li>
<li>If you want to start the debugger, select the <i>CMakeLists.txt </i>file in the project panel and choose "Set as Current Project". Then just start the debugger clicking on the green arrow button in the toolbar (see the pic below).</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-Nq--thUOcGg/Xlo3qVLqLvI/AAAAAAAAAw8/UYLhi2afr_IWLmTjv3hLSl8_8BdFj_TpwCLcBGAsYHQ/s1600/VStudio%2Bwith%2BCmake%2B-%2Bsm.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="446" data-original-width="1101" height="259" src="https://1.bp.blogspot.com/-Nq--thUOcGg/Xlo3qVLqLvI/AAAAAAAAAw8/UYLhi2afr_IWLmTjv3hLSl8_8BdFj_TpwCLcBGAsYHQ/s640/VStudio%2Bwith%2BCmake%2B-%2Bsm.jpg" width="640" /></a></div>
<div>
<br /></div>
<div>
Sometimes the automatic <i>CMake </i>generation might fail, or you'd like to reset the project. In that case you select select the <i>CMakeLists.txt </i>file in the project panel and</div>
<div>
<ul>
<li>choose "Delete CMake Cache" to reset the project</li>
<li>choose "Generate CMake Cache" to recreate the build files</li>
<li>start the build as described above</li>
</ul>
<div>
Ready! To thest my Qt application on Linux I have only to:</div>
</div>
<div>
<ul>
<li>check out the project on the Linux machine</li>
<li>open it in <i>Qt Creator</i></li>
<li>and let it build and run!</li>
</ul>
</div>
<span style="font-size: large;">4. The Moral</span><br />
<br />
I hope you fear <i>CMake </i>no more now! If we aren't overcomplicating things,<b> <i>CMake </i>might indeed be a pretty nice and handy tool</b> for building projects on both Windows and Linux (and of course also on other platforms).<br />
<br />
The technique I currently use is:<br />
<ul>
<li>add all <i>.cpp </i>and <i>.hpp</i> files to the Visual Studio project</li>
<li>export the project using the <i>cmake-converter</i> tool</li>
<li>replace all generated content beside the file lists with my generic CMake prologue and epilogue</li>
<li>slightly adapt prologue/epilogue if needed</li>
</ul>
This works and won't cost you a lot of time.<br />
<br />
--<br />
* <i>"CMake converter for Visual Studio projects"</i> - <a href="https://pypi.org/project/cmake-converter/">https://pypi.org/project/cmake-converter/</a><br />
<br />
** private CMake includes (i.e. include directories) aren't exported to other CMake projects, <br />
<br />Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-61635772200414464692019-12-18T08:21:00.000-08:002019-12-18T08:24:13.914-08:00No cursor in your embedded Qt-App on iMX-6?<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-MqTYbLzQtyk/Td51zJinckI/AAAAAAAAAHE/KjN7-6QlEQ4emhpqtL3s_NQm0szb0qMTwCPcBGAYYCw/s1600/bug%2B1763.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="408" data-original-width="400" height="200" src="https://1.bp.blogspot.com/-MqTYbLzQtyk/Td51zJinckI/AAAAAAAAAHE/KjN7-6QlEQ4emhpqtL3s_NQm0szb0qMTwCPcBGAYYCw/s200/bug%2B1763.jpg" width="195" /></a></div>
This one is a continuation of (meanwhile) a series of bughunting/bugfixing posts*. As I already wrote once:<br />
<blockquote class="tr_bq">
<i>"You'll maybe complain that this site is degenerating into a mingle-mangle of bug descriptions, but if you've ever had a pesky problem and couldn't find anything about it on the web, you'll understand my urge to document such things for the fellow hackers."**</i></blockquote>
So I'll just document this one gotcha to help the googling programmer, because on that way I received help from others multiple times. I hope it'll make someone's life easier.<br />
<br />
<span style="font-size: large;">1. The Problem</span><br />
<br />
In the current project for one of my customers I'm writing a Qt UI for an application running on embedded Linux. We are using the open source version of Qt, so we build the system image with <i>yocto </i>using standard Qt5 recipies. We are also using the tried and tested <a href="https://en.wikipedia.org/wiki/I.MX#i.MX_6_series">iMX-6 </a>board, that was used in iPhones time and ago.<br />
<br />
This board has a GPU and we are using Qt's EGLFS platform plugin which enables standard OpenGL graphics. Everything should hunky-dory, no surprizes, this configuration is well-tested, and it should just work. And it worked, a demo Qt application showed on the attached VGG screen. But then we plugged in a mouse, whisked it to and fro, but nothing happened. <b>No mouse cursor on the screen</b>!<br />
<br />
<span style="font-size: large;">2. The Solution</span><br />
<br />
I tried to google the problem away, but no ready-made solution could be found. But then a small hint set the ball rolling, namely this one:<br />
<blockquote class="tr_bq">
<i>"... very likely the hardware or the drivers doen't support a hardware-accelerated mouse cursor."</i></blockquote>
Wait, wait... And what does the <i>"i.MX Graphics User’s Guide"</i> say about this exaclty? Let have a <a href="https://usermanual.wiki/Document/iMXGraphicsUsersGuide.671323818/html#pf47">look</a>:<br />
<div>
<blockquote>
<i><b>"10.1.5 Cursor</b><br /> Hardware IPU does not provide a hardware cursor."</i></blockquote>
In no uncertain terms! </div>
<div>
<br /></div>
<div>
Problem solved: Qt will by default try to use the hardware cursor to speed things up, but in such a case it will fail in name of performance. A very honourable end - <b>dulce et decorum est pro performancem mori, </b>as the ancient Romans used to say! </div>
<div>
<br /></div>
<div>
After we clearified that question the fix "follows trivially" 😉 - we only have to turn on Qt's software cursor option. How to do that? As Qt's <a href="https://doc.qt.io/qt-5/embedded-linux.html">documentation </a>says:</div>
<blockquote class="tr_bq">
<i>"The KMS/DRM backend also supports custom configurations via a JSON file."</i></blockquote>
This is our way. We habe to create a JSON config file and point to it with the <i>QT_QPA_EGLFS_KMS_CONFIG</i> environment variable. The contents should be looking roughly like that:<br />
<br />
<pre class="brush: javascript"> {
"device": "/dev/dri/card0",
"hwcursor": false,
"pbuffers": true,
"outputs": [
{
"name": "LVDS0",
"mode": "800x480"
}
]
}
</pre>
with <i>"device"</i> set to your device name and <i>"pbuffers"</i> enabling usage of standard EGL pbuffer surfaces.<br />
<br />
<span style="font-size: large;">3. The Moral</span><br />
<br />
There isn't one this time 😕. I you can think about one that could fit in here, say it in the comments.<br />
<br />
--<br />
* like <a href="http://ib-krajewski.blogspot.com/2017/05/qt-and-missing-vtable-usually-means.html">this</a>, <a href="http://ib-krajewski.blogspot.com/2018/07/qlabel-swallows-mouse-clicks-in.html">this</a>, <a href="http://ib-krajewski.blogspot.com/2014/02/whos-to-blame-or-most-amazing.html">this</a>, <a href="http://ib-krajewski.blogspot.com/2012/01/assertafxgetthread-null-with.html">this</a> and even <a href="http://ib-krajewski.blogspot.com/2012/11/simplecv-install-and-you-need-python.html">this one</a> for Python!<br />
** in one of the above posts <a href="http://ib-krajewski.blogspot.com/2012/11/simplecv-install-and-you-need-python.html">here</a>.<br />
<br />Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-23738576813769024202019-07-05T06:28:00.000-07:002019-10-02T01:57:39.936-07:00VTune Amplifier and profiling MinGW on Windows<br />
<a href="https://1.bp.blogspot.com/-Ty14MOcct54/XJIDHu9fASI/AAAAAAAAAkQ/QAXtXV2fuj0MX1EquxZON5Hwxy2jLINWwCPcBGAYYCw/s1600/cover%2Bfrontside%2B-%2Bsm.jpg" imageanchor="1" style="-webkit-text-stroke-width: 0px; clear: right; color: #0066cc; float: right; font-family: Times New Roman; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; margin-bottom: 1em; margin-left: 1em; orphans: 2; text-align: center; text-decoration: underline; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><img border="0" data-original-height="138" data-original-width="110" src="https://1.bp.blogspot.com/-Ty14MOcct54/XJIDHu9fASI/AAAAAAAAAkQ/QAXtXV2fuj0MX1EquxZON5Hwxy2jLINWwCPcBGAYYCw/s1600/cover%2Bfrontside%2B-%2Bsm.jpg" /></a><span lang="EN-US" style="mso-ansi-language: EN-US;">You might perhaps know that I recently wrote a <a href="https://www.packtpub.com/application-development/hands-high-performance-qt">book</a> (and blogged about it <a href="https://ib-krajewski.blogspot.com/2019/02/holy-cow-i-wrote-book.html">here</a>). In its second
chapter, where we discuss profiling and profilers, I mentioned Intel's <a href="https://software.intel.com/en-us/vtune">VTune Amplifier</a>, but
because the book only uses open source tools I just wrote that:</span><br />
<blockquote class="tr_bq">
<i>"The commercial Intel performance suite comprises of VTune Amplifier, Intel Advisor, and Intel Inspector. VTune Amplifier is an advanced sampling profiler using hardware and OS counters, providing information on CPU, threading, memory, cache, and storage…"</i></blockquote>
Admittedly, there was some free version of <i>VTune </i>at the time, but you had to request it and you could use it only for a limited time for evaluation (if my memory serves me right), so I just classified it as a commercial tool.<br />
<br />
But this week I learned, that there is a <b>free version of <i>VTune 2019</i></b> everybody can use. I didn’t believe that but I went to <i>VTune</i>’s homepage to check it – and indeed, an entirely free versions is available there. The commercial version simply comes with commercial-level support, and there are no other differences AFAICS.<br />
<span style="font-size: large;"></span><br />
<span style="font-size: large;">Stress-Test with MinGW</span><b></b><i></i><u></u><sub></sub><sup></sup><strike></strike><br />
<br />
So I downloaded the free version and wanted to try it. I knew that Intel tools integrate tightly with Visual Studio, and that Intel’s compiler is (still is?) binary compatible with Microsoft’s compilers, so I was interested if <i>VTune</i> would be able to understand MinGW’s symbol information. I know for sure, that in the past <i>VTune</i> only could understand Microsoft’s debug info format.<br />
<br />
<span lang="EN-US" style="mso-ansi-language: EN-US;">I wanted to test it out, because in my book I am using the standard Qt distribution for Windows (at the time of writing it was Qt 5.9) and this distribution is using MinGW as compiler. This also means that the provided Qt DLLs contained symbol information is stored in the MinGW format (i.e. Dwarf2). </span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span>
<span lang="EN-US" style="mso-ansi-language: EN-US;">To test <i>VTune</i>'s support for various debug info format I profiled a following application of mine:</span><br />
<pre> +-----------------+
| | +-------------+
| | | |
| QML GUI +--------->+ QProcess |
| | | |
| (MinGW) | +---+----^-+--+
| | | | |
+-----------------+ start | | | cin, cout, cerr
| | |
| | |
| | |
+------v----+-v---------+
| | +------------------+
| | | |
| "Backend" Executable +--------+ Some SDK DLLs |
| | | |
| (Visual Studio) | | (MinGW) |
| | +------------------+
+-----------------------+
</pre>
<span lang="EN-US" style="mso-ansi-language: EN-US;"><b></b>As you can see, it’s rather a complicated situation where a MinGW-based GUI is starting a Visual Studio-base executable that is loading some SDK DLLs that export a plain C API, but are internally using MinGW! So let have a try and see how <i>VTune</i> will cope with that mess. </span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span>
<span lang="EN-US" style="mso-ansi-language: EN-US;">Surprisingly, when I started <i>VTune</i> and let my example application be started and profiled by it I saw the following picture:</span><span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span>
<br />
<a href="https://1.bp.blogspot.com/-2FtkThhgstM/XRSIqO5JEII/AAAAAAAAAog/Kg-mDCt5x18CvQqJPAllP4oMsBOFxXWyQCLcBGAs/s1600/VTune%2Bin%2Baction.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1056" data-original-width="1600" height="422" src="https://1.bp.blogspot.com/-2FtkThhgstM/XRSIqO5JEII/AAAAAAAAAog/Kg-mDCt5x18CvQqJPAllP4oMsBOFxXWyQCLcBGAs/s640/VTune%2Bin%2Baction.jpg" width="640" /></a><br />
<br />
We see that <i>VTune </i>can indeed see and <b>understand symbols from Qt’s QML libraries</b>, as well as from <b>my own C++ code</b> in some QML extension modules, which were also compiled with MinGW. A great hooray! But that’s not enough – on closer inspection I found out, that <b>also the “backend” executable symbols</b> (Microsoft format) were visible in profile data, and then even one step further, i.e. the internal symbols of the SDK DLL it is using (MinGW format again)!<br />
<br />
Surprise, surprise, it seems to be working rather neatly. Nice one! It turned out that in a new profiling project the "Analyze child processes" option is turned on by default. I had only to provide the location of my sources, everything else just worked!<br />
<br />
<span style="font-size: large;">Summing Up</span><br />
<br />
As an addendum (or call it correction) to the book, I can say that the <a href="https://software.intel.com/en-us/vtune">VTune Amplifier</a> is another option when profiling Qt applications on Windows!<br />
<br />
Besides the traditional profiling to find execution hotspots, <i>VTune </i>has a very nice support for diagnosing multithreaded performance, visualizing lock contentions, it can help with the Intel CPUs by showing cache misses and pipeline stalls, it can diagnose memory access bottlenecks and also profile entire system with multiple applications. You’ll admit it’s quite a mighty* tool! <br />
<br />
--<br />
* Want to see ho to use all these features? There is a video guiding you around the GUI <a href="https://software.intel.com/en-us/videos/introduction-to-intel-vtune-amplifier">here</a>, and here is an <a href="https://techdecoded.intel.io/resources/code-modernization-in-action-threading-memory-and-vectorization-optimizations/#gs.nlj4ys">article</a> about <i>"Thread, Memory, and Vector Optimizations"</i> using <i>VTune </i>and <i>Intel Advisor, </i>showing how to diagnose and improve usage of the available cores, optimize cache usage and introduce vectorization.<br />
<br />Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com1tag:blogger.com,1999:blog-3870801931584460413.post-2774552330901222912019-04-28T12:23:00.002-07:002022-02-03T01:17:31.697-08:00For last 2 days - my book for $10 only!<br />
There are a couple of days left for you all, if you want to get my book for $10 only!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-wXfFUMOD3bg/XMX7WzM-1WI/AAAAAAAAAmM/gqPkSuCt2R0FHR-ZM1s4bYJnOpEhEUt4QCLcBGAs/s1600/spring-author-sm_ebook.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="631" data-original-width="1201" height="336" src="https://2.bp.blogspot.com/-wXfFUMOD3bg/XMX7WzM-1WI/AAAAAAAAAmM/gqPkSuCt2R0FHR-ZM1s4bYJnOpEhEUt4QCLcBGAs/s640/spring-author-sm_ebook.png" width="640" /></a></div>
<br />
In the course of the "Spring $10 Campaign" on <a href="http://packtpub.com/">packtpub.com</a> you can purchase the eBook version of my <i>"Hands-On High Performance Programming with Qt 5"</i> book <b>for $10 only </b>until <b>30th of April</b>. <br />
<br />
So hurry on! here's the link: <a href="https://www.packtpub.com/application-development/hands-high-performance-programming-qt-5">https://www.packtpub.com/application-development/hands-high-performance-programming-qt-5</a>.<br />
<br />
Get it when it's still fresh. It only came out this January!<br />
<br />
<span style="font-size: large;">PS:</span> Sorry for the short notice, but somehow I overslept... Shame on me. 😞 Sorry.<br />
<br />Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com8tag:blogger.com,1999:blog-3870801931584460413.post-36405752439895332232019-02-25T00:35:00.000-08:002022-02-03T01:18:36.691-08:00Holy cow, I wrote a book!<br />
I always wanted to say that since I saw Raymond Chen's <a href="https://blogs.msdn.microsoft.com/oldnewthing/">blog</a>, and now. at last, I can! The title of the book is <i>"Hands-On High Performance Programming with Qt 5"</i> and you can get it from Amazon (<a href="https://www.amazon.com/Hands-High-Performance-Programming-cross-platform/dp/1789531241">here</a>) or Packt Publishing (<a href="https://www.packtpub.com/application-development/hands-high-performance-qt">here</a>). The book's cover looks like that:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-6LNjB9LFOWk/XHMJdZq-0-I/AAAAAAAAAjM/ouD2sRQXTmsm4W8Laby1ivBrbp-CE6gAACLcBGAs/s1600/B11480_New1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="373" data-original-width="302" height="400" src="https://1.bp.blogspot.com/-6LNjB9LFOWk/XHMJdZq-0-I/AAAAAAAAAjM/ouD2sRQXTmsm4W8Laby1ivBrbp-CE6gAACLcBGAs/s400/B11480_New1.png" width="323" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I have to say that I rather like the look of it!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-size: large;">TL;DR</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
A new book About <b>Qt's and C++ performance</b>. Uses Qt 5.9 - 5.12 on Windows. Guides the reader from an <b>intermediate to the (lower) advanced</b> level. 4 of 5 stars 😉.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
There are also code examples illustrating some of the discussed concetps (to be found at <a href="https://github.com/PacktPublishing/Hands-On-High-performance-with-QT">https://github.com/PacktPublishing/Hands-On-High-performance-with-QT</a>).</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<span style="font-size: large;">What this book is about.</span><br />
<br />
This book is about many things. Judging from the title it's about performance optimization of Qt 5 <br />
(Qt 5.9 - Qt 5.12) programs. But because Qt's underlying language is C++ it is also <b>about C++ optimizations</b> and performance. Because C++ is a close-to-the-metal language (some would say low-level) we also discuss the<b> hardware architectures</b>. Also because Qt framework covers so many areas we also discuss <b>data structures </b>and <b>algorithms</b>, <b>multithreading</b>, <b>file I/O </b>and <b>parsing</b>, <b>GUI </b>and <b>graphics</b>, <b>networking</b>, and even <b>mobile </b>and <b>embedded </b>platforms.<br />
<br />
Quite a mouthful, you'd say? Yes, it's true. But it also makes it interesting, and shows how many facets there are to the performance optimization.<br />
<br />
Additionally, I decided to use <b>Windows as the development platform</b> for this book. Most Qt books use Linux, probably because Qt Creator IDE offers a much better tooling there. But because Windows is also a very popular platform I wanted to take <b>the road less traveled</b> and try to find out how to compensate the lack of the standard Linux performance tools on Windows.<br />
<br />
We use only open-source or free tools, Qt Creator as development environment and Qt 5.9 LTE version for code examples (as it was the last LTE version at the time I started writing this book).<br />
<br />
<span style="font-size: large;">Why did I write it?</span><br />
<br />
Well, because I always found performance optimization very interesting. And because I have been working with Qt for quite a long time now, nothing to say about C++! So, as the publishers approached me with a proposed book title I knew I could write rather a good book about it!<br />
<br />
The second reason was that there <b>wasn't a resource about performance optimization I would be content with</b>. There area a couple of C++ performance books, but I wasn't entirely convinced by them. As of Qt and its specific problems there was nothing! Well, there was a host of information scattered in blogs, Stack Overflow, books, articles and Twitter threads. So I thought that before I forget it all, I'd better put it to paper!<br />
<br />
I also wanted to write a book I'd have liked to read when I first started to learn about performance and optimizations, because there wasn't such a thing either. Thus I settled on a intermediate-level, approachable, but not trivial book.<br />
<br />
<span style="font-size: large;">What material is covered</span><br />
<br />
This book was planned as an intermediate level read. If you can write some C++ and have learned to write basic Qt application then it is for you. No further knowledge is requires, as every topic (e.g. data structures, graphics, networking) will be introduced in a understandable and (I hope so) entertaining manner.<br />
<br />
My initial plan for the book was:<br />
<ul>
<li><b>Part I - Basics</b></li>
<li>Intro - basic performance wisdom and techniques, hardware architecture and its impact.</li>
<li>Profiling - performance tools and how to use them. As I said, we don't want to make it easy for us and look at the Windows platform!</li>
<li>C++ - how performant is C++ really? And what are optimizations the compiler (and linker) can do?</li>
<li><b>Part II - General Techniques</b></li>
<li>Data structures and algorithms - what is the performance of Qt containers and strings? Do we have to use them?</li>
<li>Multithreading - Qt's take on threading and how to speed up your program with concurrency.</li>
<li>Fails - some more memorable performance problems I encountered in my career</li>
<li><b>Part III - Selected Qt Modules</b></li>
<li>File I/O etc - Qt and file system performance, JSON and XML parsing. Also memory mapped files and caching.</li>
<li>Graphic - GUI, widget and QML performance. Probably the most interesting part of the book.</li>
<li>Networking - network performance and network support in Qt. Because we live in the ubiquitous connectivity era!</li>
</ul>
<div>
However, the editors wished two additional chapters, so I also added them (<span style="background-color: transparent; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">unfortunately, this made the three-part structure obsolete</span>):</div>
<div>
<ul>
<li>Mobile and embedded - how to use Qt on mobile and embedded (a kind of advanced chapter applying all we have learned before to two specific platforms)</li>
<li>Testing - a goodie chapter about testing techniques, GUI testing and performance regression tests. At the end this chapter turned out pretty interesting!</li>
</ul>
</div>
<br />
I really think that this book can do a good job to guide the reader from an intermediate to the (lower) advanced level!<br />
<br />
<span style="font-size: large;">Table of Contents</span><br />
<br />
On the publisher's book page there is a TOC (<a href="https://www.packtpub.com/application-development/hands-high-performance-qt">here</a>), but it is very high level, and doesn't really show the real contents of the book. It goes rather monotonously like "Some intro for topic", "Qt classes fro that", "Performance techniques for that", "Summary", "Questions" and "Further reading". I agree with you that one cannot judge the level and quality of the book from that. It could be everything - from horrible to superb.<br />
<br />
For that reason I include here a complete TOC as it appears in the book, so you can have a better idea of themes covered. Without much further ado, here it is:<br />
<br />
<a href="https://2.bp.blogspot.com/-0oVCH3_UNK8/Tw34wz-ULsI/AAAAAAAAAJs/jjIOp4qtZsIVg8J1brM3s1gZt53hM1ATQCPcBGAYYCw/s1600/cpp.gif" imageanchor="1" style="-webkit-text-stroke-width: 0px; background-color: transparent; clear: left; color: #0066cc; float: left; font-family: Times New Roman; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; margin-bottom: 1em; margin-right: 1em; orphans: 2; text-align: center; text-decoration: underline; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"> <img border="0" data-original-height="32" data-original-width="32" src="https://2.bp.blogspot.com/-0oVCH3_UNK8/Tw34wz-ULsI/AAAAAAAAAJs/jjIOp4qtZsIVg8J1brM3s1gZt53hM1ATQCPcBGAYYCw/s1600/cpp.gif" /></a><a href="https://2.bp.blogspot.com/-0oVCH3_UNK8/Tw34wz-ULsI/AAAAAAAAAJs/jjIOp4qtZsIVg8J1brM3s1gZt53hM1ATQCPcBGAYYCw/s1600/cpp.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><br /></a>OK, I tried, but it's way too long, it follows at the end* of the post.<br />
<a href="https://2.bp.blogspot.com/-0oVCH3_UNK8/Tw34wz-ULsI/AAAAAAAAAJs/jjIOp4qtZsIVg8J1brM3s1gZt53hM1ATQCPcBGAYYCw/s1600/cpp.gif" imageanchor="1" style="-webkit-text-stroke-width: 0px; background-color: transparent; clear: right; color: #0066cc; float: right; font-family: Times New Roman; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; margin-bottom: 1em; margin-left: 1em; orphans: 2; text-align: center; text-decoration: underline; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"></a><br />
<br />
You can see from that more detailed TOC that there is a wealth of information and techniques in there! I really think that This book can do a good job to guide the reader from an intermediate to the (lower) advanced level!<br />
<br />
<span style="font-size: large;">The "Questions" and "Further Reading" sections</span><br />
<br />
As unseemly as they look in the TOC, these sections were my secret personal favorites. The "Questions" sections contain, as you probably guessed, some questions to test your understanding of themes discussed in the given chapter, but they also will try to deepen your understanding and sometimes even to introduce new and interesting information! I enjoyed writhing them because it was fun trying to find out how could I keep an intelligent reader still interested after the real material was already introduced.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-ZN0TKdAQn5g/TBZaLvLFdbI/AAAAAAAAAGE/y-2AW-bD62s3kyttAJpSie7kVB-RHDvhACPcBGAYYCw/s1600/estimate.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="588" data-original-width="705" height="266" src="https://4.bp.blogspot.com/-ZN0TKdAQn5g/TBZaLvLFdbI/AAAAAAAAAGE/y-2AW-bD62s3kyttAJpSie7kVB-RHDvhACPcBGAYYCw/s320/estimate.jpg" width="320" /></a></div>
<br />
As this is an intermediate-level book, and because I didn't want to write a 500-600 pages tome, it couldn't go deep on every of the introduced themes. Because of that I also included the "Further Reading" sections, where more advanced materials are referenced. Qt covers so many areas, and some themes like networking, graphics, embedded or mobile are so deep, that you will definitely need to consult more books and articles! In hindsight I should have to include even more references, but you know, If I had more time etc...<br />
<br />
<span style="font-size: large;">Summary</span><br />
<br />
If I had more time, this book could (of course) be much better. But even so I'm rather content with it, considering that I wrote it in half of a year only, in parallel with my normal working hours. I hope you will enjoy it!<br />
<br />
<span style="font-size: large;">PS:</span> Maybe I will start some kind of online addendum/errata for this book, as there are quite many things I'm still leaning after I finished writing it.<br />
<br />
--<br />
* Here comes the TOC in its whole glory:<br />
<br />
<div id="tableofcontents" class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-Ty14MOcct54/XJIDHu9fASI/AAAAAAAAAkQ/E6YWCjPGnFoRr_vGFKw73jCFSVTIt2ONwCEwYBhgL/s1600/cover%2Bfrontside%2B-%2Bsm.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="138" data-original-width="110" src="https://4.bp.blogspot.com/-Ty14MOcct54/XJIDHu9fASI/AAAAAAAAAkQ/E6YWCjPGnFoRr_vGFKw73jCFSVTIt2ONwCEwYBhgL/s1600/cover%2Bfrontside%2B-%2Bsm.jpg" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b><span lang="EN-US" style="color: black; margin: 0px;">Preface</span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b><span lang="EN-US" style="color: black; margin: 0px;">Chapter 1: Understanding Performant
Programs 1</span></b><span lang="EN-US" style="color: black; margin: 0px;"></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b><span lang="EN-US" style="color: black; margin: 0px;"> Why performance is
important 1</span></b><span lang="EN-US" style="color: black; margin: 0px;"></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"> The price of performance
optimization 2</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Traditional wisdom and basic guidelines 2</b></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Avoiding
repeated computation 4</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Avoiding
paying the high price 4</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Avoiding
copying data around 5</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>General performance
optimization approach 6</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Modern processor architectures</b> 7</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Caches 7 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Pipelining 8
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Speculative execution and branch
prediction 10 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Out-of-order execution 10 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Multicore 11
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Additional
instruction sets 12 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Impact on
performance 13 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Keeping your caches hot 14 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Don't confuse your branch predictor 15 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Parallelizing your application 16 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Summary 16
</span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Questions
17 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Further
reading 17 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Chapter 2:
Profiling to Find Bottlenecks 19 </span></b><br />
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Types of profilers 20 </b></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Instrumenting
profilers 20 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Sampling
profilers 21 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>External
counters 22 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span></span><span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;">Note on Read Time-Stamp Counter 22 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Platform and tools 22 </b></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Development
environment 23 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Profiling
tools 24 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Just use gprof? 25<br /><br />
<span style="margin: 0px;"> </span>Windows system tools 25 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Program profiling tools 27 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Visualizing performance data 30 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Memory tools
30 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Profiling CPU usage 31 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Poor man's
sampling technique 31<br /><br />
<span style="margin: 0px;"> </span>Using Qt Creator's QML profiler 32 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Using
standalone CPU profilers 35 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span></span><span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;">Reiterating on sampling profiling's limitations 39 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Investigating memory usage 39 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Poor man's
memory profiling 40 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Using Qt
Creator's heob integration 41 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Manual instrumentation and benchmarks 45 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Debug outputs
45 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Benchmarks
46 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span></span><span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;">Benchmarks in regression testing 46 </span><span lang="EN-US" style="color: black; margin: 0px;"></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Manual
instrumentation 47 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Further advanced tools 48 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Event
Tracing for Windows (ETW) and xperf 48 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Installation 48 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Recording and visualizing traces 50 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Conclusion 53 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>GammaRay 54 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Building GammaRay 54 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>When can we use it? 56 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Other tools
57 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Graphic profilers 57 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Commercial Intel tools 58 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Visual Studio tools 58 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Summary 59 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Questions 59 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Chapter 3:
Deep Dive into C++ and Performance 61 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">C++ philosophy and design 61 </b></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Problems
with exceptions 62 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Run-time
overheads 63 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Non-determinism
63 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>RTTI
64 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Conclusion
64 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Virtual
functions 64 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Traditional C++ optimizations 65 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Low-hanging
fruit 65 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Temporaries 66 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Return values and RVO 66 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Conversions 67 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Memory management 68 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Basic
truths 68 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Replacing
the global memory manager 69 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Custom
memory allocators 70 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Where
they do make sense 71 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Stack
allocators 71 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Conclusion
71 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span></span><span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;">Custom STL allocators 72 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Template
trickery 73<br /><br />
</span><span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;">
</span>Template computations 73 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Expression templates 74 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>CRTP for static polymorphism 75 <br />
<span style="margin: 0px;"> </span>Removing branches 76 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">C++11/14/17 and performance 77 </b></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Move
semantics 77 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Passing by value fashionable again 78 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Compile time
computations 78 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Other
improvements 80 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>What your compiler can do for you 81 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Examples of
compiler tricks 81 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>More on
compiler optimizations 85 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Inlining of functions 86 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Loop unrolling and vectorization 86 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>What
compilers do not like 87 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Aliasing 87 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>External functions 88 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>How can you
help the compiler? 89 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span></span><span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;">Profile Guided Optimization 90 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>When compilers
get overzealous 90 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Optimization tools beyond compiler 92</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Link time
optimization and link time code generation 93 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Workaround –
unity builds 93 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Beyond
linkers 94 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Summary 95 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Questions 95 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Further reading 96 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Chapter 4:
Using Data Structures and Algorithms Efficiently 97 </span></b><br />
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Algorithms, data structures, and performance
98 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Algorithm
classes 98 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span></span><span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;">Algorithmic complexity warning 100 </span><span lang="EN-US" style="color: black; margin: 0px;"></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Types of
data structures 100 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Arrays 100 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Lists 101 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Trees 101 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Hash tables 102 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Using Qt containers 103</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>General
design 103 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Implicit
sharing 103 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Relocatability
105 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Container
classes overview 105 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Basic
Qt containers 106 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>QList
106 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>QVarLengthArray
107 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>QCache
108 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>C++11
features 108<br /><br />
<span style="margin: 0px;"> </span></span><span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;">Memory management 109 </span><span lang="EN-US" style="color: black; margin: 0px;"></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Should we
use Qt containers? 110 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Qt algorithms, iterators, and gotchas 110 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Iterators
and iterations 111 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Gotcha -
accidental deep copies 111 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Working with strings 113</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Qt string
classes 113 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QByteArray 113 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QString 114 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QStringBuilder 114 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Substring classes 115 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>More string
advice 115 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Interning 115 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Hashing 116 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Searching substrings 117 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Fixing the size 117 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Optimizing with algorithms and data
structures 118 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Optimizing
with algorithms 118 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Reusing other people's work 120 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Optimizing
with data structures 120 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Be cache-friendly 121 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Flatten your data structures 122 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Improve access patterns 122 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Structure
of arrays 122 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Polymorphism avoidance 123 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Hot-cold data separation 123 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Use a custom allocator 124 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Fixed size containers 124 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Write your own 125 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Summary 125 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Questions 125 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Further reading 126 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Chapter 5:
An In-Depth Guide to Concurrency and Multithreading 128 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><b><span style="margin: 0px;"> </span>Concurrency,
parallelism, and multithreading 128 </b></span></div>
<b></b><br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Problems
with threads 130 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>More
problems – false sharing 131 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><b><span style="margin: 0px;"> </span>Threading
support classes in Qt 133 </b></span></div>
<b></b><br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Threads 134 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Mutexes 134 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Condition
variables 135 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Atomic
variables 136 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Thread local
storage 136 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Q_GLOBAL_STATIC
136 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Threads, events, and QObjects 137</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Events and
event loop 137 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>QThreads and
object affinities 138</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span></span><span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Getting rid
of the QThread class 142 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Thread
safety of Qt objects 142 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Higher level Qt concurrency mechanisms 142 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>QThreadPool
143 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>QFuture 143 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>QFutureInterface
145 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Should we use it? 146 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Map, filter,
and reduce 147 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Which
concurrency class should I use? 149 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Multithreading and performance 150 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Costs of multithreading 150 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Thread costs 150 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Synchronization costs 151 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QMutex implementation and performance
151 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Atomic operation costs 151 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Memory allocation costs 152 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt's signals and slots performance 152 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Speeding up
programs with threads 153 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Do not block the GUI thread 153 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Use the correct number of threads 154 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Avoid thread creation and switching cost
154 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Avoid locking costs 154 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Fine-grained locks 155 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Lock coarsening 155 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Duplicate or partition resources 156 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Use concurrent data structures 157 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Know your concurrent access patterns
157 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Do not share any data 157 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Double-checked
locking and a note on static objects 158 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Just switch to lock-free and be fine? 159
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Lock-free performance 159 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Progress guarantees 160 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Messing with thread scheduling? 161 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Use a share nothing architecture 162 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Implementing
a worker thread 162 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Active object pattern 163 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Command queue pattern 164 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Beyond threading 164 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>User-space
scheduling 164 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Transactional
memory 165 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Continuations
165 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Coroutines
166 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Summary 167 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Questions 168 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Further reading 168 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Chapter 6:
Performance Failures and How to Overcome Them 170 </span></b><br />
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><b><span style="margin: 0px;"> </span>Linear search
storm 170 </b></span></div>
<b></b><br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Context 171</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Problem 172 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Solution 172
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Conclusion
173 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Results dialog window opening very slowly
173</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Context 173 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Problem 174 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Solution 174
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Conclusion
174 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Increasing HTTP file transfer times 174</b>
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Context 175 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Problem 175 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Solution 176
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Conclusion
177 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Loading SVGs 177</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Context 177 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Problem 178 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Solution 178
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Conclusion
179 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Quadratic algorithm trap 179</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Context 180 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Problem 180</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Solution 180
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Conclusion
180 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Stalls when displaying widget with QML
contents 181</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Context 181 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Problem 181 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Solution 182
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Conclusion
182 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Too many items in view 182</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Context 183 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Problem 183</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Solution 183
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Conclusion
183 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Two program startup stories 184 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Time system
calls 184 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Font cache
184 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Conclusion
185 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Hardware shutting down after an error message
185</span></b><span lang="EN-US" style="color: black; margin: 0px;"> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Context 185 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Problem 185 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Solution 185
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Conclusion
186 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Overly generic design 186</span></b><span lang="EN-US" style="color: black; margin: 0px;"> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Context 186 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Problem 187</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Solution 187
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Conclusion
187 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Other examples 187 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Summary 188 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Questions 189 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Further reading 189 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Chapter 7:
Understanding I/O Performance and Overcoming Related Problems 190 </span></b><br />
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Reading and writing files in Qt 191</span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Basics of
file I/O performance 191 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Buffering and flushing 191 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Tied and synchronized streams 192 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Reading and writing 193 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Seeking 194 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Caching files 194 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Qt's I/O
classes 195 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QFile 195 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QTextStream and QDataStream 196 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Other helper I/O classes 198 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QDebug and friends 198 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Parsing XML and JSON at the speed of light
199 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>QtXml
classes 200 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QDomDocument 200 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QXmlSimpleReader 201 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>New stream
classes in QtCore 201 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Quick
parsing of XML 202 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Reading JSON
203 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span></span><span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;">QJsonDocument's performance 204 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Connecting databases 204 </b></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Basic
example using SQLite 204 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Some
performance considerations 205</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>More about operating system interactions 206 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Paging,
swapping, and the TLB 206 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Reading from
disk 207 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Completion
ports 208 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Summary 208 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Questions 208 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Further reading 209 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Chapter 8:
Optimizing Graphical Performance 210 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><b><span style="margin: 0px;"> </span>Introduction
to graphics performance 211 </b></span></div>
<b></b><br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Graphics
hardware's inner workings 211 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>What is a
GPU? 211 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>OpenGL
pipeline model 213 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Performance
of the graphics pipeline 215 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>CPU problems 217</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Data transfer optimization 217 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Costly GPU operations 217 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Newer
graphics programming APIs 218 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Qt graphics architecture and its history
218</b></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>The graphics
API Zoo 219 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt Widget 219 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QGraphicalView 220 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QOpenGLWidget 221 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QVulkanWindow 222 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Qt
Quick 223 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QtQuick Controls 1 and 2 224 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Extending QML 224 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Canvas 2D 224 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QQuickPaintedItem 225 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QQuickItem 226 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QQuickFrameBufferObject 227 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>More APIs 228 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt 3D 229 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>OpenGL drivers
and Qt 231 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Graphic drivers and performance 231 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Setting the OpenGL implementation for QML
233 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Qt Widget's performance 234</span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>QPainter 234 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Images 234 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Optimized calls 235 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>OpenGL
rendering with QOpenGLWidget 236 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Images 236 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Threading
and context sharing 236 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Usage of QPainter 237 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>QGraphicsView
237 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Model/view
framework 237 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>QML performance 238 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Improvements
in 5.9 and beyond 239 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Measuring
QML performance 240 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Startup of a
QML application 242 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>QML
rendering 243 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Scene graph optimizations 243 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Scene graph and threading 245 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Scene graph performance gotchas 245 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Batching 245 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Texture atlas 246 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Occlusion, blending, and other costly
operations 246 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Antialiasing
246 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Use caching 247 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Which QML custom item should you choose?
247 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>JavaScript usage 247 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt Quick Controls 248 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Other modules 248 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Qt 3D
performance 249</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Hybrid web
applications 249 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Summary 249 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Questions 250 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Further reading 251 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Chapter 9:
Optimizing Network Performance 252 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Introduction to networking 253 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Transport
layer 254 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>User Datagram Protocol (UDP) 254 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Transmission Control Protocol (TCP) 254 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>A better TCP? 256 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><span style="margin: 0px;"> </span>Application layer 256 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Domain Name Service (DNS) 256 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>HyperText Transfer Protocol (HTTP) 257 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Secure data transfer 258 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>A better HTTP? 259 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Qt networking classes 259</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>TCP and UDP
networking classes 259 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QTcpServer and QTcpSocket 260 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QUdpSocket 261 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QAbstractSocket 262 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>QSslSocket 264 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Other socket types 265 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>HTTP
networking using Qt classes 265 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>DNS queries 265 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Basic HTTP 266 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>HTTPS and other extensions 267 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt WebSocket classes 267 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Miscallaneous classes 268 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Other
higher-level communication classes 269 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt WebChannel 269 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt WebGL streaming 269 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt remote objects 269 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Improving network performance 270</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>General
network performance techniques 270 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Receive
buffers and copying 271 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>TCP
performance 271 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>HTTP and
HTTPS performance 272 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Connection reuse 273 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Resuming SSL connections 273 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Preconnecting 274 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Pipelining 275 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Caching and compression 276 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Using HTTP/2 and WebSocket 276 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Advanced networking themes 278 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Summary 278 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Questions 279</span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Further reading 279 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Chapter
10: Qt Performance on Embedded and Mobile Platforms 281 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Challenges
in embedded and mobile development 282 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Basic performance
themes 282 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Run to idle
283 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Some
hardware data 283 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Embedded
hardware and performance 285 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Qt usage in embedded and mobile worlds 285</b>
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Qt for
embedded 286 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt usage on embedded Linux 286 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt's embedded tooling 287 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Supported hardware 288 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Example usage with Raspberry Pi 288 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Qt for
mobile 289 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Android support in Qt Creator 289 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Profiling Android applications 290 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Mobile APIs in Qt 290 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Embedded Linux and Qt performance 291</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Executable
size 291 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Minimizing
assets 292 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Power
consumption 292 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Start-up
time 293 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Using the current Qt version 293 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Using loaders 294 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>3D asset conditioning 294 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Linux start-up optimizations 294 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Hardware matters! 295 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Graphical
performance 295 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Time series
chart display 296 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt Charts and OpenGL acceleration 296 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Polyline simplifications 297 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Floating-point
considerations 298 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Mobile-specific performance concerns 299</b>
</span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Executable
size 299 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Power usage
299 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Mobile
networking 300 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Batch and piggyback 301 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Consider a push model 302 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Prefetch data 302 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Reuse connections 303 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Adapting to the current network
connection type 303 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Graphic
hardware 304 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Summary 304 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Questions 305 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Further reading 305 </span></b></div>
<br />
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><b>Chapter 11: Testing and Deploying Qt Applications 307</b></span></div>
<b></b><br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Testing of Qt code 307 </b></span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Unit testing
308 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Qt Test 308 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Test support in Qt Creator 310 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Automated
GUI testing 312 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Squish 312 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Example Squish test 313 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Performance
regression testing 316 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Adding a qmlbench benchmark 316 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; font-size: 11pt; margin: 0px;"><span style="margin: 0px;"> </span>Using Squish 317 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span><b style="mso-bidi-font-weight: normal;">Deploying Qt applications 318</b> </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Flying parts
318 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Static
versus dynamic builds 319 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Deploying on
Windows 320 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Windows
deployment tool 320 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Installation
and paths 320 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Summary and farewell 321 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Questions 322 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;"><span style="margin: 0px;"> </span>Further reading 323 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="color: black; margin: 0px;">Appendix
A: Responses to questions 324 </span></b></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;">Chapter 1 324 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;">Chapter 2 325 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;">Chapter 3 326 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;">Chapter 4 328 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;">Chapter 5 329 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;">Chapter 6 331 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;">Chapter 7 332 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;">Chapter 8 333 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;">Chapter 9 334 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;">Chapter 10 336 </span></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="EN-US" style="color: black; margin: 0px;">Chapter 11 337</span></div>
<b></b><i></i><u></u><sub></sub><sup></sup><strike></strike><br />
<br />Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-9465962224875291012018-08-31T13:47:00.003-07:002018-09-20T14:45:51.085-07:00Crazy UB when casting to enum values in C++<br />
Hi folks, this time it will be a kind of photo story! Something new this time, aaaaand I must type much less text!<br />
<br />
It started a couple of day ago, when I saw following quiz on Twitter:<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
In C++20 given<br />
<br />
enum A { e1=1, e2 } ;<br />
enum class B { e1=1, e2 } ;<br />
<br />
Which of the following invokes undefined behavior <br />
<br />
A. <br />
A a = (A)(3); <br />
B. <br />
A a = (A)(4);<br />
C.<br />
B b = (B)(std::numeric_limits<std::underlying_type<B>::type >::max());<a href="https://twitter.com/hashtag/Cplusplus?src=hash&ref_src=twsrc%5Etfw">#Cplusplus</a> <a href="https://twitter.com/hashtag/Cpp20?src=hash&ref_src=twsrc%5Etfw">#Cpp20</a> <a href="https://twitter.com/hashtag/CppPolls?src=hash&ref_src=twsrc%5Etfw">#CppPolls</a> <a href="https://twitter.com/hashtag/Programming?src=hash&ref_src=twsrc%5Etfw">#Programming</a></div>
— Shafik Yaghmour (@shafikyaghmour) <a href="https://twitter.com/shafikyaghmour/status/1034665721286950913?ref_src=twsrc%5Etfw">August 29, 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<br />
<b>My answer was: all of them of course</b>, in C or C++98 they would be probably all fine, but who knows what crazy UB stuff did they prepare for us in C++20. So when seen logically, all of that stuff should be undefined behaviour! But wait, dind't I used extensions to enum ranges in some project in some framework by casting integers to enums? That did work ok, didn't it? Ok, it was couple of years ago, C++03 I suppose, but AFAIK nothing has changed in C++11 in that respect, so maybe we did it wrong all the time back than? So how did it work?<br />
<br />
So I wasn't so sure anymore, and would say A+B are UB, C is something that C++11 introduced, so no idea, but probably UB too. But wait, all of them are UB again? Probably, but the trouble with that was that there wasn't such an answer in the quiz! Crazy!<br />
<br />
When I saw the answer I was even more perplexed:<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
|<br />
V<br />
<br />
For an enum w/ a fixed underlying type all values of the underlying type are valid <br />
<br />
For an enum w/o a fixed type, the range is limited and based on the values of enumerators, specified in [dcl.enum]p8<br />
<br />
roughly limited to the bits needed to represent the values</div>
— Shafik Yaghmour (@shafikyaghmour) <a href="https://twitter.com/shafikyaghmour/status/1034666116365209600?ref_src=twsrc%5Etfw">August 29, 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script><b>
What? Why 3 but not 4?</b> And that <i>numeric_limits<>::max() </i>can't be right either! In a following tween the relevant spots in the standard were shown, and I read them, but was none the wiser - standardese isn't the lightest read on earth. ☹️<br />
<br />
But before I gave up I remembered that I've seen something similar on Twitter already, namely in (accidently also cited) tweet by @lefticus:<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
I'm pretty sure I have this right, but this is Undefined Behavior, right?<br />
<br />
enum struct Values {<br />
val1 = 1,<br />
val2 = 2<br />
};<br />
<br />
Values val = static_cast<Values>(3);</div>
— Jason Turner (@lefticus) <a href="https://twitter.com/lefticus/status/1027928945604218881?ref_src=twsrc%5Etfw">August 10, 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
So had the same gut feeling as me, but he was corrected by some people well-versed in interpreting the standard (which I also happen to follow):<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
No, it is not. Enums with a fixed underlying type (which is int by default for enum class/struct) can have all the values of the underlying type. For enums without a fixed underlying type it gets more complicated.<a href="https://t.co/pVZoTBpIt2">https://t.co/pVZoTBpIt2</a></div>
— Miro Knejp (@mknejp) <a href="https://twitter.com/mknejp/status/1027930816507068416?ref_src=twsrc%5Etfw">August 10, 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
and:
<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
In this particular case there is no UB even if it was an oldschool enum because 3 can be represented by the two bits required to store the enumerators 1 and 2.</div>
— Miro Knejp (@mknejp) <a href="https://twitter.com/mknejp/status/1027931377847730176?ref_src=twsrc%5Etfw">August 10, 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<br />
That was than even confirmed by @CppSage himself:<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
That's not UB. It's also perfectly fine for a regular enum. However, for a regular enum, casting the value 4 *would* be UB (even though 3 is okay). For an enum class/struct, casting the value 4 would *not* be UB.</div>
— Matt Calabrese (@CppSage) <a href="https://twitter.com/CppSage/status/1027931327121768448?ref_src=twsrc%5Etfw">August 10, 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<br />
<a href="https://2.bp.blogspot.com/-0oVCH3_UNK8/Tw34wz-ULsI/AAAAAAAAAJs/jjIOp4qtZsIVg8J1brM3s1gZt53hM1ATQCPcBGAYYCw/s1600/cpp.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="32" data-original-width="32" src="https://2.bp.blogspot.com/-0oVCH3_UNK8/Tw34wz-ULsI/AAAAAAAAAJs/jjIOp4qtZsIVg8J1brM3s1gZt53hM1ATQCPcBGAYYCw/s1600/cpp.gif" /></a>This all explains it pretty well. <b>But isn't that crazy? Binding logical range of a type to its underlying representation? </b>I'd understand that if we were in the 80-ties, but in C++20 standard with all that lofty newfangled features? OK, I suppose it was always like that in C, but I'm too lazy to check it, sorry.... 😩<br />
<br />
BTW, now I've got an idea why this enum casting in a distant project might even have been working - we used Visual Studio compiler! And I dimly remember that there were some Microsoft extension for enums setting int as their underlying type. Was it so? For that I'd have to check my own blogpost from last year, but frankly, I cannot be bothered. 😩 That project has died already long ago.<br />
<br />
<span style="font-size: large;">TL;DR:</span> Twitter is a good place to learn about C++, I learn almost every day!<br />
<br />Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-72616913798664088552018-08-06T01:04:00.004-07:002018-08-07T02:27:14.039-07:00Scripting my Vim Editor<a href="https://2.bp.blogspot.com/-htb3Y938H8s/Vg2okXV-BhI/AAAAAAAAAQ8/ZrRuJTigpTs5yC9L7fGBS8EhtOJXcRaugCPcBGAYYCw/s1600/code-820275_1280.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="853" data-original-width="1280" height="133" src="https://2.bp.blogspot.com/-htb3Y938H8s/Vg2okXV-BhI/AAAAAAAAAQ8/ZrRuJTigpTs5yC9L7fGBS8EhtOJXcRaugCPcBGAYYCw/s200/code-820275_1280.jpg" width="200" /></a><br />
As an inveterate <i>vim </i>user the first thing (or one of the first things) I'd do when starting a new project under Windows is installing <i>vim </i>to use it for searching, grapping and editing logfiles when I'm bugfixing. Or just a to use it as a general viewer for all sorts of files. <br />
<br />
Typically I'd set up my toolbar buttons (for vim 7.4) like that:
<br />
<pre class="brush: ruby">"" Caution: Needs 18x18 bitmaps in "C:\Program Files (x86)\Vim\vim73\bitmaps" !!!
:amenu ToolBar.-SEP- :
:tmenu ToolBar.tabedit Open new tab (mrkkrj)
:amenu ToolBar.tabedit :tabedit<cr>
:tmenu ToolBar.darklight Switch color themes (mrkkrj)
:amenu ToolBar.darklight :colo zellner<cr>
:tmenu ToolBar.lightdark Switch color themes (mrkkrj)
:amenu ToolBar.lightdark :colo torte<cr>
:tmenu ToolBar.smallfont Smaller font (mrkkrj)
:amenu ToolBar.smallfont :set guifont=Lucida_Console:h9<cr>
:tmenu ToolBar.bigfont Bigger font (mrkkrj)
:amenu ToolBar.bigfont :set guifont=Lucida_Console:h10<c>
</pre>
This gives me my standard button toolbar with buttons for switching fonts and and colors from big to small and from dark to light, plus a button for opening new tabs:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-FH7fVJvRVds/W2f3efRJdKI/AAAAAAAAAcw/Ll-3tBF6Wjo48JNeqp86bdYaCPtK8IOlACLcBGAs/s1600/vim%2Btool%2Bbar.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="58" data-original-width="287" src="https://2.bp.blogspot.com/-FH7fVJvRVds/W2f3efRJdKI/AAAAAAAAAcw/Ll-3tBF6Wjo48JNeqp86bdYaCPtK8IOlACLcBGAs/s1600/vim%2Btool%2Bbar.jpg" /></a></div>
<br />
Somehow this was always enough, beacuse I just used my default dark scheme plus one more dark and an alternative light one. As you know the colors depend on the monitir you are using and the room you are sitting in, so in my new project I wanted to toggle through several schemes and font sizes before I settle down with my favorite. Thus I introduced following functions:<br />
<pre class="brush: ruby">:tmenu ToolBar.darklight Switch color themes (mrkkrj)
:amenu ToolBar.darklight :call ToggleLightScheme()<cr>
:tmenu ToolBar.lightdark Switch color themes (mrkkrj)
:amenu ToolBar.lightdark :call ToggleDarkScheme()<cr>
:tmenu ToolBar.smallfont Smaller font (mrkkrj)
:amenu ToolBar.smallfont :set guifont=Lucida_Console:h9<cr>
:tmenu ToolBar.bigfont Bigger font (mrkkrj)
:amenu ToolBar.bigfont :call ToggleBigFontSize()<c>
</pre>
Next thing is to write the actual functions to toggle between dark and light color schemes. What I did was toggling between 2 light and 2 dark color schemes like that:
<br />
<pre class="brush: ruby">:function ToggleDarkScheme()
: if exists('g:colors_name')
: if g:colors_name == 'evening'
: colo darkblue
: else
: colo evening
: endif
: else
: colo evening
: endif
:endfunction
:function ToggleLightScheme()
: if exists('g:colors_name')
: if g:colors_name == 'zellner'
: colo delek
: else
: colo zellner
: endif
: else
: colo delek
: endif
:endfunction
</pre>
Toggling of fonts had to be done a little different, because there's no global variable that vim would set when fonts are changing like the <em>g:colors_name </em>above. So I had to introduce my own: <em>g:guifonts_name</em>:
<br />
<pre class="brush: ruby">let g:guifonts_name = 'Lucida_Console:h10'
:function ToggleBigFontSize()
: if g:guifonts_name == 'Lucida_Console:h10'
: set guifont=Lucida_Console:h12
: let g:guifonts_name = 'Lucida_Console:h12'
: else
: set guifont=Lucida_Console:h10
: let g:guifonts_name = 'Lucida_Console:h10'
: endif
:endfunction
</pre>
Admittedly this is not a pretty and general solution: if I needed more colors or fonts I'd have to add more ugly if-else clauses. The ceneral soultion would be of course to create a local array of color schemes and cycle through it like it is shown <a href="http://vim.wikia.com/wiki/Switch_color_schemes">here</a>*. But <em>"form follows function..."</em> and <em>"use before reuse..." </em>😉 - and frankly, I didn't have time for that, vimscript's syntax** is pretty weird.<br />
<br />
--<br />
* <em>"Switch Color Schemes" </em>in Vim Tips Wiki: <a href="http://vim.wikia.com/wiki/Switch_color_schemes">http://vim.wikia.com/wiki/Switch_color_schemes</a>
<br />
<br />
** There some good intros you can use to deepen your knowledge of vim scripting:<br />
<ul>
<li><em>"Five Minute Vimscript"</em> by Andrew Scala: <a href="http://andrewscala.com/vimscript/">http://andrewscala.com/vimscript/</a></li>
<li><em>"Scripting the vim editor"</em>series by Damian Conway: <a href="https://www.ibm.com/developerworks/library/l-vim-script-1/index.html">https://www.ibm.com/developerworks/library/l-vim-script-1/index.html</a></li>
<li>The <em>"Learn Vimscript the Hard Way"</em> book online: <a href="http://learnvimscriptthehardway.stevelosh.com/">http://learnvimscriptthehardway.stevelosh.com/</a><em></em></li>
</ul>
<div>
</div>
Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com0tag:blogger.com,1999:blog-3870801931584460413.post-70081355022722788312018-07-21T01:56:00.003-07:002018-08-05T23:58:43.634-07:00More on Casablanca/cpprestdsk - Design and Comparisons<div>
</div>
<br />
<a href="https://4.bp.blogspot.com/-bbaYsKW15hA/VYPsG7QEVNI/AAAAAAAAAOo/k5x96UFB5lIPo-tHHu0y0hfjOE3wiTRHgCPcBGAYYCw/s1600/logo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="62" data-original-width="80" height="152" src="https://4.bp.blogspot.com/-bbaYsKW15hA/VYPsG7QEVNI/AAAAAAAAAOo/k5x96UFB5lIPo-tHHu0y0hfjOE3wiTRHgCPcBGAYYCw/s200/logo.png" width="200" /></a>After I finished my Casablanca (aka C++ REST SDK)* project for some time then, I noticed** a new Boost library: <a href="https://www.boost.org/doc/libs/1_67_0/libs/beast/doc/html/index.html">Boost.Beast</a>***, a library implementing: <i>"HTTP and WebSocket built on Boost.Asio in C++11". </i><br />
<br />
That sounded interesting so I had a quick look at it, and I even found (surprise, surprise) the design rationale and <a href="http://vinniefalco.github.io/stage/beast/review/beast/design_choices/http_comparison_to_other_librari.html">comparison</a> with other HTTP libraries. Because of my previous involvement with Casablanca* I simply had to read it. So here is my take on Beasts's critique and some closing discussion of Casablanca's* design and how I see it.<br />
<div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/-3zSKEPwHlSg/Wz36_EL-ikI/AAAAAAAAAcI/xyoBJ-5xpVI-Lhsn7X645_xzIJW8VCc8ACLcBGAs/s1600/WP_20160909_16_39_45_Pro.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="899" data-original-width="1600" height="355" src="https://3.bp.blogspot.com/-3zSKEPwHlSg/Wz36_EL-ikI/AAAAAAAAAcI/xyoBJ-5xpVI-Lhsn7X645_xzIJW8VCc8ACLcBGAs/s640/WP_20160909_16_39_45_Pro.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">My involvement with Casablanca*/C++ REST-SDK code...<span style="font-size: small;">☺</span></td></tr>
</tbody></table>
Let us start with a lengthy citation from Beast's analysis of Casablanca*, where the author lists all the missing customization points of the library:<br />
<blockquote class="tr_bq">
<i>"It is clear from this declaration that the goal of the message model in this library is <b>driven by its use-case </b>(interacting with REST servers) and not to model HTTP messages generally. We note problems similar to the other declarations: </i><br />
<ul>
<li><i>There are no compile-time customization points at all. The only customization is in the concurrency::streams::istream and concurrency::streams::ostream reference parameters. Presumably, these are abstract interfaces which may be subclassed by users to achieve custom behaviors. </i></li>
</ul>
<ul>
<li><i>The extraction of the body is conflated with the asynchronous model. </i></li>
</ul>
<ul>
<li><i>No way to define an allocator for the container used when extracting the body. </i></li>
</ul>
<ul>
<li><i>A body can only be extracted once, limiting the use of this container when using a functional programming style. </i></li>
</ul>
<ul>
<li><i>Setting the body requires either a vector or a concurrency::streams::istream. No user defined types are possible. </i></li>
</ul>
<ul>
<li><i>The HTTP request container conflates HTTP response behavior (see the set_response_stream member). Again this is likely purpose-driven but the lack of separation of concerns limits this library to only the uses explicitly envisioned by the authors."</i></li>
</ul>
</blockquote>
</div>
<div>
Then the author restates it in a more concise manner:<br />
<blockquote class="tr_bq">
<i>"The general theme of the HTTP message model in cpprestsdk is "no user definable customizations". There is no allocator support, and no separation of concerns. It is <b>designed to perform a specific set of behaviors</b>. In other words, it <b>does not follow the open/closed principle</b>.</i></blockquote>
<blockquote class="tr_bq">
<i>Tasks in the Concurrency Runtime operate in a fashion similar to std::future, but with some improvements such as continuations which are not yet in the C++ standard. The costs of using a task based asynchronous interface instead of completion handlers is well documented: synchronization points along the call chain of composed task operations which cannot be optimized away. See: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf">A Universal Model for Asynchronous Operations</a> (Kohlhoff)."</i></blockquote>
</div>
<div>
<b>Let me state my opinion bluntly</b>: I didn't miss these customization features at all during my almost 3 years long involvement with Casablanca*! The framework just did its work as it should, we could use it without much hassle and it <a href="http://ib-krajewski.blogspot.com/2015/09/casablanca-c-rest-framework-one-year.html">performed reasonably good</a> under load on Windows - probably through its usage of completion ports (Boost.Asio is only used on Mac Os and Linux).<br />
<br />
OK, there was a single time where one of the above concerns did cause problems, namely:<br />
<ul>
<li><i>A body can only be extracted once, limiting the use of this container when using a functional programming style,</i></li>
</ul>
but I solved it by setting the data into the message back again. Mischief managed 😈, work can be continued! You could say it's not very functional programming style, but we are not in the academy but in real life.<br />
<br />
On the other side the Boost.Beast itself library seems a little hard to use, and more like a base for another libraries than a independent library on its own, as it is stated in the project's own FAQ:<br />
<blockquote class="tr_bq">
<i>"It is not the intention of the library to provide turn-key solutions for specific HTTP or WebSocket use-cases. Instead, it is a sensible protocol layering on top of Boost.Asio which retains the Boost.Asio memory management style and asynchronous model."</i></blockquote>
So OK, <b>we must be aware of Casablanca's* limitations,</b> but for the real REST use case they somehow<b> carried no weight</b>.<br />
<b><br /></b>
<b><span style="font-size: large;">TL;DR:</span> </b>I cannot really relate to the critique stated in the <a href="http://vinniefalco.github.io/stage/beast/review/beast/design_choices/http_comparison_to_other_librari.html">comparison</a>, for us Casablanca <a href="http://ib-krajewski.blogspot.com/2015/09/casablanca-c-rest-framework-one-year.html">worked out </a>pretty well in general and the product we build with it is alive and kicking!<br />
<br />
<b><span style="font-size: large;">Note: </span></b><a href="https://www.bishopfox.com/case_study/securing-beast/">Here </a>and <a href="https://www.youtube.com/watch?v=4TtyYbGDAj0">here </a>I found <b>quite interesting results of a security review</b> of Boost.Beast by Bishop Fox. They found vulnerabilities, and I don't want to even think about their analysis of Casablanca*! Fortunately our product was set up forca more or less trusted environment. But this could be maybe a material for a separate blog post.<br />
<br />
--<br />
* Casablanca is the old code name for Microsoft's <a href="https://github.com/Microsoft/cpprestsdk">C++ REST SDK</a> and <b>I'll use it in the rest of that post, </b>because it<b> rolls better off the tongue than cpprestsdk!</b> Besides during the years I grew accustomed to it and even a little nostalgic...<br />
<br />
** to be more specific, I noticed it through Meeting C++'s <a href="https://www.reddit.com/r/cpp_review/">library reviews</a> <a href="http://meetingcpp.com/blog/items/a-cpp-review-community.html">initiative</a>!<br />
<div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.reddit.com/r/cpp_review/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="400" height="200" src="https://meetingcpp.com/files/mcpp/meetingcppcertifiedlibrarylogo.png" width="200" /></a></div>
<div class="separator" style="clear: both;">
*** see "<i>Beast: Version 100, ACCEPTED to Boost!" </i><a href="https://www.reddit.com/r/cpp/comments/6rp32l/beast_version_100_accepted_to_boost/">here</a>.</div>
<br /></div>
Marek Krjhttp://www.blogger.com/profile/16877868679118775297noreply@blogger.com6