давненько я не видал стоящего кода на C, но тут мне в глаза попался lz4 :
http://code.google.com/p/lz4/
это библиотека компрессии и распаковки данных, судя по тестам она далеко обошла snappy (
http://code.google.com/p/snappy/ один из быстрейших архиваторов, разработан и используется гуглом), а качество сжатия на уровне zlib
библиотека написана чтобы выжать всё без ориентировки на конкретный cpu (быстрее будут аппаратно заточенный код), в коде обширно используются встроенные функции компилятора
к примеру :
if unlikely(cpy>oend-COPYLENGTH)
что же это за unlikely ? а вот что :
#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
# define expect(expr,value) (__builtin_expect ((expr),(value)) )
#else
# define expect(expr,value) (expr)
#endif
#define likely(expr) expect((expr) != 0, 1)
#define unlikely(expr) expect((expr) != 0, 0)
где функция :
— Built-in Function: long __builtin_expect (long exp, long c)
You may use __builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (-fprofile-arcs), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect.
|
те исходя из анализа данных мы делаем вывод о вероятности события и заставляем компилятор учитывать это для предсказателя ветвлений, кунг-фу !
или другой пример :
// Unaligned memory access is automatically enabled for "common" CPU, such as x86.
// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected
// If you know your target CPU supports unaligned memory access, you may want to force this option manually to improve performance
#if defined(__ARM_FEATURE_UNALIGNED)
# define LZ4_FORCE_UNALIGNED_ACCESS 1
#endif
как мы знаем (или узнаем) RISC архитектуры выдают максимум только если тип выравнен на размер, те MIPS и некоторые ARM'ы требуют чтобы short был выравнен на 2 байта, int на 4 байта, (для справки, ARM до сих пор требует чтобы float был выравнен на 4 байта, если нет то clang будет генерировать просто не валидный код, потому при играх с выравниванием ваш код может просто не разработать)
а теперь посмотрим как это здесь реализовано :
#if defined(_MSC_VER) // Visual Studio does not support 'stdint' natively
# define BYTE unsigned __int8
# define U16 unsigned __int16
# define U32 unsigned __int32
# define S32 __int32
# define U64 unsigned __int64
#else
# include <stdint.h>
# define BYTE uint8_t
# define U16 uint16_t
# define U32 uint32_t
# define S32 int32_t
# define U64 uint64_t
#endif
#ifndef LZ4_FORCE_UNALIGNED_ACCESS
# pragma pack(push, 1)
#endif
typedef struct _U16_S { U16 v; } U16_S;
typedef struct _U32_S { U32 v; } U32_S;
typedef struct _U64_S { U64 v; } U64_S;
#ifndef LZ4_FORCE_UNALIGNED_ACCESS
# pragma pack(pop)
#endif
#define A64(x) (((U64_S *)(x))->v)
#define A32(x) (((U32_S *)(x))->v)
#define A16(x) (((U16_S *)(x))->v)
довольно красиво, да ? при включенном макросе компилятор просто выравняет поля в структуре как нужно, а при выключенном мы форсируем ему выравнивание на 1 байт
думаю заинтересовал обывателя по-изучать исходник для саморазвития