Rust is a compiled, hybrid imperative/object- oriented/functional language. It appeals directly to any C++ developer who has battled with memory management, and Python developers who long for faster code. So why might you be interested in learning Rust?
My favourite bug of all time was uncovered because I was just too impatient.
I was working on a fairly large and complex embedded project. A microcontroller was interfacing with some custom hardware. It would configure, control, and monitor the hardware. The microprocessor was running an RTOS with a lightweight TCP/IP stack, so remote clients could connect to the device via Ethernet and perform remote configuration. We also used this for diagnostics and testing during development. We had successfully used a similar design on several products, with great results. We had also designed a protocol for monitoring and control that was used in earlier models, and we extended it here – though this product was significantly larger and more complex than its predecessors. What could possibly go wrong?
During a code review at work recently, we had an interesting discussion about code maintenance. You could say that coding is a bit like gardening: while you are planting new seedlings, do you weed nearby areas as you go, or save up all the weeding for the next sunny weekend? Should code maintenance be a continual, gradual process, or does it warrant being scheduled as a task in its own right?
I recently read an interesting article by Andy Jeffries entitled 25 Tips for Intermediate Git Users (linked to via proggit) . It had lots of useful information condensed into bite-sized task-oriented chunks.
I’ve been using Mercurial for a while now, so I thought I would write a similar set of tips by translating from
git to the equivalent
hg commands. Thanks to Andy for blessing this translation work. There may well be some mistakes herein – please leave a comment if you have any improvements or fixes to suggest.
In Part I of this series on Boost, we looked at the basics of how to create and run threads using the Boost libraries. But once you have more than one thread running in a process, you have to deal with the problems and challenges that threads can introduce. So, before delving into the mechanics of how to use mutexes and other threading constructs, we look at what can go wrong – and how to avoid it.
The STL makes it easy to create lists, iterate over lists, and apply a function to each member of a list. So how do you filter a vector according to some criteria? It’s not hard, but the obvious solution isn’t quite enough. Here’s how.
Boost is an incredibly powerful collection of portable class libraries for C++. There are classes for such tasks as date/time manipulation, filesystem interfaces, networking, numerical programming, interprocess communication and much more.
The Boost documentation is substantial, but can still be daunting to new users. So this article is the first of a series on using Boost, starting with basic threading. It aims to provide an accessible introduction, with complete working examples.
When you are developing a new piece of software, you typically first spend quite some time setting up your development environment. As you progress, your application becomes a very cozy inhabitant of this environment, a safe happy cocoon that has evolved as you make lots of small changes to the application or your system. What could possibly go wrong?
Writing “const-correct” code will improve the quality and maintainability of your code. It is especially important and useful when writing Object-Oriented code, as objects are often passed around as constant references. Properly declaring non-mutating methods as
const allows you to safely call any
const method on such a reference. It is part of good type-safe practice and good code hygiene. So how do we do it?
The Standard Template Library (STL) for C++ provides a set of powerful and flexible templated container classes. Never again will you have to hand-craft a doubly-linked list (and get your pointer arithmetic mixed up) — just use
Now most of the idiomatic C++ code I’ve read that uses STL iterators uses the prefix
operator++ to move the iterator forward. And so I had long ago adopted this too, with a vague recollection of having read somewhere that it performed better. But why? Good question… (Updated: fixed formatting, got numbers the right way around.)
The use of the post-increment operator is well established idiomatic code for looping (in both C and C++):
1 2 3 4 5
When the indexing variable is an ordinal type (usually an integer), the incrementing order makes no difference. The expressions
i++ are identical in this case. And so many people developing in C++ simply use the same style in C++ with their iterator code. Why would it matter?
Well, it turns out that it does. If the indexing variable is a class, such as an iterator, there are some subtle differences between the pre-increment and post-increment operators that may have a big impact on performance.
Referring back to Scott Meyer’s wonderful More Effective C++ book, I tracked down the explanation (item 6, page 31), which I will attempt to reproduce here in simplified form. The signature of the pre-increment
operator++ for a class T is:
while the post-increment operator had a dummy parameter added to make the signature unique:
But that isn’t the only difference – notice that the prefix operator returns a reference to the object itself (permitting chaining of method calls), while the postfix operator returns a const object, semantically defined as the previous value. (This is for consistency with the behaviour of ordinal types.)
The result is that the pre-increment operator modifies the object in-place, whereas the post-increment operator will result in temporaries being created, invoking the constructor and destructor. So something as simple as
it++ turns out to have some significant side-effects when applied to an object with overloaded operators. Since this is the case with virtually all iterators in the STL, as well as many other similar objects, it is worth investigating.
So I decided to quantify the difference, to see how much of a difference it made. I wrote a test program that created a very large (5 million) array of integers, and iterated over the array. I used a high-resolution timer to time two versions of the loop, identical save for one being pre-increment and one being post-increment. After a warmup of 3 runs, I ran the test 10 times, collected the timings and compared them.
The results were very interesting: on an Intel workstation, the pre-increment code took an average of 14.1ns per call, while the post-increment code took 27.6ns per call. That’s a significant difference of 49%, or nearly twice as fast! A plot of 10 iterations each is shown below:
So – it really does improve the performance of your code to write:
1 2 3 4 5
For small arrays, it may not make much of a noticeable difference, but every cycle counts, and a little consistency goes a long way. Using the prefix increment will enable your application to scale better.
Using the prefix form won’t make your actual loop run twice as fast, as the iterator increment is only one component contributing to the performance, and the looping overhead may indeed be swamped by the execution time of the body. So as always, YMMV!
I have provided the test source in C++, along with an R script to summarise and plot the output. You can download it via the attachment linked at the end of this article. The code should compile on any POSIX-conforming system with a decent C++ compiler. And if you do your own performance tests, please drop me a line and let me know what you found.
As one final note, the wonderful Boost++ library provides the
foreach module, which provides a powerful wrapper to iterate over containers with a nice clean simple syntax:
1 2 3 4 5
And yes, it uses the pre-increment operator for maximum performance.
Download the source used for this article:
AUTHOR: bynio DATE: 04/15/2009 03:17:24 AM “the post-increment code took an average of 14.1ns per call, while the pre-increment code took 27.6ns per call”, so actually post-increment is faster?
AUTHOR: Reid Ellis DATE: 04/28/2009 01:48:50 AM
the post-increment code took an average of 14.1ns per call, while the pre-increment code took 27.6ns per callDo you have these numbers backwards? Because otherwise you are saying that the post-increment code is faster than the pre-increment code. Reid
AUTHOR: Gavin Baker DATE: 05/02/2009 10:50:17 PM Hi Reid, you’re right – I got the names back-to-front (the article is updated now). The post-increment is definitely twice as fast, and I have repeated the test on other machines, with the same relative results.
In the migration from my old blog setup, this article lost a plot of the data, as well as the source of the test code. I’ve added the plot and linked the source tarball in here.