boolean bit fields

From: Alex Rousskov <rousskov_at_measurement-factory.com>
Date: Wed, 23 Jan 2013 23:51:16 -0700

On 01/23/2013 07:05 PM, Amos Jeffries wrote:
> On 24/01/2013 7:20 a.m., Kinkie wrote:

>> the attached patch turns the unsigned int:1 flags in CachePeer to
>> bools.

> Please retain the :1 bitmasking. My microbench is showing a consistent
> ~50ms speed gain on bitmasks over full bool, particularly when there are
> multiple bools in the structure. We also get some useful object size gains.

Hello,

    FYI: With g++ -O3, there is no measureable performance difference
between bool and bool:1 in my primitive tests (sources attached). I do
see that non-bool bit fields are consistently slower though ("foo:0"
below means type "foo" without bit fields; bool tests are repeated to
show result variance):

host1:
> bool:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.206s
> bool:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.203s
> uint32_t:0 size: 20 final: -1085972333.443588956 iterations: 100M time: 1.191s
> uint32_t:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.525s
> uint8_t:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.204s
> uint8_t:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.527s
> bool:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.204s
> bool:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.204s

host2:
> bool:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.851s
> bool:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.848s
> uint32_t:0 size: 20 final: -1085972333.443588956 iterations: 100M time: 0.863s
> uint32_t:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.150s
> uint8_t:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.849s
> uint8_t:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.150s
> bool:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.848s
> bool:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.849s

host3:
> bool:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.615s
> bool:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.615s
> uint32_t:0 size: 20 final: -1085972333.443588956 iterations: 100M time: 0.696s
> uint32_t:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.928s
> uint8_t:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.615s
> uint8_t:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.928s
> bool:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.615s
> bool:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 0.615s

With g++ -00, boolean bit fields become slower than plain bool as well:

> bool:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.347s
> bool:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 2.023s
> uint32_t:0 size: 20 final: -1085972333.443588956 iterations: 100M time: 1.448s
> uint32_t:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 2.002s
> uint8_t:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.371s
> uint8_t:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 2.034s
> bool:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 1.348s
> bool:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 2.095s

The same is actually true for -O3 with an older g++ v3.4.6 on a
different host:

> bool:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 4.468s
> bool:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 6.238s
> uint32_t:0 size: 20 final: -1085972333.443588956 iterations: 100M time: 4.876s
> uint32_t:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 6.209s
> uint8_t:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 4.470s
> uint8_t:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 6.208s
> bool:0 size: 12 final: -1085972333.443588956 iterations: 100M time: 4.471s
> bool:1 size: 12 final: -1085972333.443588956 iterations: 100M time: 6.231s

To me, it looks like bit fields in general may hurt performance where
memory composition is not important (as expected, I guess), and that
some compilers remove any difference between full and bit boolean with
-O3 (that surprised me).

G++ assembly source comparison seem to confirm that -- boolean-based
full and bit assembly sources are virtually identical with -O3 and newer
g++ versions, while bit fields show a lot more assembly operations with
-O0 (both diffs attached). Assembly is well beyond my expertise though.

Am I testing this wrong or is it a case of YMMV? If it is "YMMV", should
we err on the side of simplicity and use simple bool where memory
savings are not important or not existent?

Thank you,

Alex.

Received on Thu Jan 24 2013 - 06:51:41 MST

This archive was generated by hypermail 2.2.0 : Thu Jan 24 2013 - 12:00:08 MST