Skip to content
  • Jeff King's avatar
    bswap.h: drop unaligned loads · c578e29b
    Jeff King authored and Junio C Hamano's avatar Junio C Hamano committed
    Our put_be32() routine and its variants (get_be32(), put_be64(), etc)
    has two implementations: on some platforms we cast memory in place and
    use nothl()/htonl(), which can cause unaligned memory access. And on
    others, we pick out the individual bytes using bitshifts.
    
    This introduces extra complexity, and sometimes causes compilers to
    generate warnings about type-punning. And it's not clear there's any
    performance advantage.
    
    This split goes back to 660231aa (block-sha1: support for
    architectures with memory alignment restrictions, 2009-08-12). The
    unaligned versions were part of the original block-sha1 code in
    d7c208a9 (Add new optimized C 'block-sha1' routines, 2009-08-05),
    which says it is:
    
       Based on the mozilla SHA1 routine, but doing the input data accesses a
       word at a time and with 'htonl()' instead of loading bytes and shifting.
    
    Back then, Linus provided timings versus the mozilla code which showed a
    27% improvement:
    
      https://lore.kernel.org/git/alpine.LFD.2.01.0908051545000.3390@localhost.localdomain/
    
    
    
    However, the unaligned loads were either not the useful part of that
    speedup, or perhaps compilers and processors have changed since then.
    Here are times for computing the sha1 of 4GB of random data, with and
    without -DNO_UNALIGNED_LOADS (and BLK_SHA1=1, of course). This is with
    gcc 10, -O2, and the processor is a Core i9-9880H.
    
      [stock]
      Benchmark #1: t/helper/test-tool sha1 <foo.rand
        Time (mean ± σ):      6.638 s ±  0.081 s    [User: 6.269 s, System: 0.368 s]
        Range (min … max):    6.550 s …  6.841 s    10 runs
    
      [-DNO_UNALIGNED_LOADS]
      Benchmark #1: t/helper/test-tool sha1 <foo.rand
        Time (mean ± σ):      6.418 s ±  0.015 s    [User: 6.058 s, System: 0.360 s]
        Range (min … max):    6.394 s …  6.447 s    10 runs
    
    And here's the same test run on an AMD A8-7600, using gcc 8.
    
      [stock]
      Benchmark #1: t/helper/test-tool sha1 <foo.rand
        Time (mean ± σ):     11.721 s ±  0.113 s    [User: 10.761 s, System: 0.951 s]
        Range (min … max):   11.509 s … 11.861 s    10 runs
    
      [-DNO_UNALIGNED_LOADS]
      Benchmark #1: t/helper/test-tool sha1 <foo.rand
        Time (mean ± σ):     11.744 s ±  0.066 s    [User: 10.807 s, System: 0.928 s]
        Range (min … max):   11.637 s … 11.863 s    10 runs
    
    So the unaligned loads don't seem to help much, and actually make things
    worse. It's possible there are platforms where they provide more
    benefit, but:
    
      - the non-x86 platforms for which we use this code are old and obscure
        (powerpc and s390).
    
      - the main caller that cares about performance is block-sha1. But
        these days it is rarely used anyway, in favor of sha1dc (which is
        already much slower, and nobody seems to have cared that much).
    
    Let's just drop unaligned versions entirely in the name of simplicity.
    
    Signed-off-by: default avatarJeff King <peff@peff.net>
    Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
    c578e29b