Сравнение компиляторов для разработки на микроконтроллерах с ядром ARM Cortex-M


    В этой статье протестируем 3-и компилятора для микроконтроллеров Kinetis с ядром ARM Cortex-M4.
    Запустим тесты CoreMark, Whetstone, Dhrystone.
    Исследуем алгоритмы сжатия с минимальным потреблением ОЗУ и выясним как влияют на их быстродействие разные компиляторы.
    И даже попытаемся узнать насколько отстает Kinetis по быстродействию от Intel Core I7.




    Предыдущие статьи о разработке на микроконтроллерах Kinetis:



    В статье “Начало разработки на микроконтроллерах Kinetis. Быстрый старт” была описана среда разработки Kinetis Design Studio v3.0.0 (KDS). Среда KDS использует в качестве инструмента компиляции и сборки программного обеспечения пакет GNU Tools for ARM Embedded Processors. Туда в частности входит компилятор GCC для ARM. Компилятор неплохой во всех смыслах. Но если мы посмотрим сколько существует у него ветвей в директории gcc.gnu.org/svn/gcc/branches, то увидим их более 300! Сколько же сил надо чтобы поддерживать такое огромное количество ветвей!? А ведь проект не коммерческий. С другой стороны серия ARM Cortex-M не мэйнстрим, не используются в смартфонах, к ним не привлечено так много внимания сообщества поддерживающего Open Source.

    Это все заставляет подумать, особенно если собираться втягиваться в долгое и изнурительное программирование микроконтроллеров с мегабайтами непроходимых исходников, ограниченным пространством памяти, неизвестными требованиями но с молниеносной реакцией на их изменения.

    К счастью KDS обеспечена плагинами для конвертации под другие известные пакеты компиляции и сборки — Keil и IAR. Большинство демо-проектов для Kinetis сопровождается 3-мя конфигурациями для сборки средствами GCC, Keil и IAR. Однако в наборе программного обеспечения для Kinetis нет достаточно всеобъемлющего теста для сравнения этих инструментов компиляции между собой. Поэтому пришлось создать свой.
    Проект создан в KDS с использованием плагина ProcessorExpert для микроконтроллера MK60FN1M0VLQ12 на плате представленной в статье “Умная плата для управления силовыми 3-х фазными нагрузками”

    Вот экран проекта в KDS:


    Что входит в пакет тестов


    Проект Whetstone . Очень старый и простой тест производительности вычислений с плавающей точкой. Тест очень легко портируется и может выполняться на простейших микроконтроллерах. В нашем случае представлено две реализации: вариант вычислений c типом float и вариант с типом double. Это важно, поскольку в первом случае у Cortex-M4 используется сопроцессор, а во втором нет.

    Проект Dhrystone. Тест производительности целочисленных операций. Типы float и double нигде не применяются. Тест тоже легко портируется и имеется огромный архив результатов для всевозможных микроконтроллеров и компьютеров.

    Проект CoreMark. Современный тест, специально разработанный для встраиваемых систем. Может стать индустриальным стандартом. Его результаты сертифицируются организацией EEMBC, а значит защищены в какой-то мере от читинга и фальсификации.
    Результаты теста CoreMark вызывают наибольшее доверие при комплексном тестировании производительности микроконтроллеров и сравнении компиляторов. На нем в принципе можно было бы и ограничится, но тесты сами по себе не несут никакой практической пользы для встраиваемых приложений, и чтобы придать большее прикладное значение этим тестам я добавил еще тестирование алгоритмов сжатия.

    Для начала пришлось найти подходящий менеджер памяти (менеджер кучи или heap).

    Проект umm_malloc. Нашелся на Github. С виду показался вполне подходящим. Стандартный менеджер кучи из библиотеки C-и я использовать отказался по двум причинам. Во-первых, в каждой из сред Keil, IAR, GCC будет своя библиотека кучи и не хотелось тратить время на исследование особенностей каждой из них. Во-вторых, алгоритмы сжатия критически зависят от объемы выделяемой им памяти. А памяти в обрез. Нужен был механизм точного контроля выделяемой памяти. И здесь umm_malloc предоставляет такую возможность. А попутно мы протестируем и быстродействие самого алгоритма umm_malloc.

    Алгоритмы сжатия


    Все алгоритмы пришлось подстраивать для того чтобы они использовали как можно меньше ОЗУ.
    Сколько памяти нужно этим алгоритмам, насколько они могут сжать данные и каково их быстродействие можно посмотреть в результатах тестов и в листинге вывода в терминал.

    А вот результаты:


    -У всех компиляторов была включена опция максимальной оптимизации. Точный состав опций можно посмотреть в прилагающемся проекте.
    -Алгоритмы сжатия сжимали участок бинарного кода прошивки, полученной из проекта этого теста, скомпилированного в IAR.
    -Время компиляции GCC измерено при компиляции из среды KDS.
    -Помимо скорости работы алгоритмов также в таблицу вставлены строчки с дополнительными важными для разработчика метриками, это: время полной перекомпиляции проекта, размер бинарного файла при оптимизации по скорости и размер бинарного файла при оптимизации по размеру.

    Вывод в терминал результатов теста скомпилированного в IAR
    ----------- Speed Test -------------
    
    
    Reference time = 100001 us
    
    ----------- umm malloc test -------------
    ...........................................................
    |0x1fff1b44|B     0|NB     1|PB     0|Z     1|NF     1|PF     0|USED
    |0x1fff1b4c|B     1|NB  4223|PB     0|Z  4222|NF  4223|PF     0|FREE
    |0x1fff9f3c|B  4223|NB     0|PB     1|Z     1|NF     0|PF     1|USED
    ...........................................................
    Total Entries     1    Used Entries      0    Free Entries      1
    Total Blocks   4223    Used Blocks       0    Free Blocks    4223
                           Used space =      0    Free space =  33784
    ...........................................................
    
    umm malloc test   time  = 1447071 uS
    Allocations =  40000, uSec per allocation = 36
    
    ----------- Compressor LZSS test -------------
    Uncompressed size = 2048
    Compressed   size = 1858. Max. alloc.= 14384. Time = 6627 uS
    Decompress                Max. alloc.= 1048. Time = 981 uS
    Decompress Ok!
    
    ----------- Compressor Zlib test -------------
    Uncompressed size = 2048
    Compressed   size = 1740. Max. alloc.= 24288. Time = 12179 uS
    Decompress                Max. alloc.= 15768. Time = 764 uS
    Decompress Ok!
    
    ----------- Compressor S-LZW test -------------
    Uncompressed size = 2048
    Compressed   size = 2035. Max. alloc.= 4320. Time = 2542 uS
    Decompress                Max. alloc.= 4320. Time = 3816 uS
    Decompress Ok!
    
    ----------- Compressor FastLZ test -------------
    Uncompressed size = 2048
    Compressed   size = 1834. Max. alloc.= 32776. Time = 1010 uS
    Decompress                Max. alloc.= 0. Time = 152 uS
    Decompress Ok!
    
    
    ----------- WHETSTONE FLOAT -------------
    
    .........MODULE 1:  simple identifiers...
      xx1  = -0.06679254770278930664
      xx2  = -0.46633863449096679688
      xx3  = -0.73303699493408203125
      xx4  = -1.13254797458648681641
    .........MODULE 2:  array elements.......
      e10  = -0.06834230571985244751
      e11  = -0.46263590455055236816
      e12  = -0.72971796989440917969
      e13  = -1.12397670745849609375
    .........MODULE 3:  array as parameter...
      e1_0 = -0.05533060804009437561
      e1_1 = -0.44743216037750244141
      e1_2 = -0.71096724271774291992
      e1_3 = -1.10309338569641113281
    .........MODULE 4:  conditional jumps....
      val  = 1
    .........MODULE 6:  integer arithmetic...
      e1k  = 6.00000000000000000000
      e1l  = 6.00000000000000000000
    .........MODULE 7:  trig. functions......
      x1   = 0.49041154980659484863
      y1   = 0.49039667844772338867
    .........MODULE 8:  procedure calls......
      z    = 0.99993747472763061523
    .........MODULE9:  array references......
      e1_j = -1.10309338569641113281
      e1_k = 3.00000000000000000000
      e1_l = -1.10309338569641113281
    .........MODULE10:  integer arithmetic...
      j    = 2
      k    = 3
    .........MODULE11:  standard functions...
      x    = 0.83466047048568725586
    ........................................
    Whetstone last    time (uS) = 10960.00
    Whetstone max     time (uS) = 10961.00
    Whetstone min     time (uS) = 10960.00
    
    
    ----------- WHETSTONE DOUBLE -------------
    
    .........MODULE 1:  simple identifiers...
      xx1  = -0.06679268039452399826
      xx2  = -0.46633881454398036003
      xx3  = -0.73303694842681344599
      xx4  = -1.13254799829068817198
    .........MODULE 2:  array elements.......
      e10  = -0.06834219862995164003
      e11  = -0.46263765626356890425
      e12  = -0.72971838784369053319
      e13  = -1.12397907004612833261
    .........MODULE 3:  array as parameter...
      e1_0 = -0.05533645259179445915
      e1_1 = -0.44743656275474680588
      e1_2 = -0.71097338928518248722
      e1_3 = -1.10309805692560095340
    .........MODULE 4:  conditional jumps....
      val  = 1
    .........MODULE 6:  integer arithmetic...
      e1k  = 6.00000000000000000000
      e1l  = 6.00000000000000000000
    .........MODULE 7:  trig. functions......
      x1   = 0.49040731615907084197
      y1   = 0.49039249795612543821
    .........MODULE 8:  procedure calls......
      z    = 0.99993750062499996275
    .........MODULE9:  array references......
      e1_j = -1.10309805692560095340
      e1_k = 3.00000000000000000000
      e1_l = -1.10309805692560095340
    .........MODULE10:  integer arithmetic...
      j    = 2
      k    = 3
    .........MODULE11:  standard functions...
      x    = 0.83466551951904967427
    ........................................
    Whetstone last    time (uS) = 142583.00
    Whetstone max     time (uS) = 142583.00
    Whetstone min     time (uS) = 142582.00
    
    
    ----------- DHRYSTONE 2 -------------
    
    
    Dhrystone Benchmark, Version 2.1 (Language: C)
    Program compiled without 'register' attribute
    Execution starts, 20000 runs through Dhrystone
                                                  Execution ends
    Final values of the variables used in the benchmark:
    Int_Glob:            5
            should be:   5
    Bool_Glob:           1
            should be:   1
    Ch_1_Glob:           A
            should be:   A
    Ch_2_Glob:           B
            should be:   B
    Arr_1_Glob[8]:       7
            should be:   7
    Arr_2_Glob[8][7]:    20010
            should be:   Number_Of_Runs + 10
    Ptr_Glob->
      Ptr_Comp:          536867932
            should be:   (implementation-dependent)
      Discr:             0
            should be:   0
      Enum_Comp:         2
            should be:   2
      Int_Comp:          17
            should be:   17
      Str_Comp:          DHRYSTONE PROGRAM, SOME STRING
            should be:   DHRYSTONE PROGRAM, SOME STRING
    Next_Ptr_Glob->
      Ptr_Comp:          536867932
            should be:   (implementation-dependent), same as above
      Discr:             0
            should be:   0
      Enum_Comp:         1
            should be:   1
      Int_Comp:          18
            should be:   18
      Str_Comp:          DHRYSTONE PROGRAM, SOME STRING
            should be:   DHRYSTONE PROGRAM, SOME STRING
    Int_1_Loc:           5
            should be:   5
    Int_2_Loc:           13
            should be:   13
    Int_3_Loc:           7
            should be:   7
    Enum_Loc:            1
            should be:   1
    Str_1_Loc:           DHRYSTONE PROGRAM, 1'ST STRING
            should be:   DHRYSTONE PROGRAM, 1'ST STRING
    Str_2_Loc:           DHRYSTONE PROGRAM, 2'ND STRING
            should be:   DHRYSTONE PROGRAM, 2'ND STRING
    Time = 93000 us
    Microseconds for one run through Dhrystone: 4.65
    Dhrystones per Second:                      215053
    
    
    ----------- COREMARK -------------
    
    2K performance run parameters for coremark.
    CoreMark Size    : 666
    Total ticks      : 29079282
    Total time (secs): 29.079282
    Iterations/Sec   : 343.887445
    Iterations       : 10000
    Compiler version : IAR 7.40.7
    Compiler flags   :  -O3 -Otime
    Memory location  : IRAM
    seedcrc          : 0xe9f5
    [0]crclist       : 0xe714
    [0]crcmatrix     : 0x1fd7
    [0]crcstate      : 0x8e3a
    [0]crcfinal      : 0x988c
    Correct operation validated. See readme.txt for run and reporting rules.
    CoreMark 1.0 : 343.887445 / IAR 7.40.7  -O3 -Otime / IRAM
    
    END.
    


    Вывод в терминал результатов теста скомпилированного в Keil
    ----------- Speed Test -------------
    
    
    Reference time = 100001 us
    
    ----------- umm malloc test -------------
    ...........................................................
    |0x1fff60f8|B     0|NB     1|PB     0|Z     1|NF     1|PF     0|USED
    |0x1fff6100|B     1|NB  4223|PB     0|Z  4222|NF  4223|PF     0|FREE
    |0x1fffe4f0|B  4223|NB     0|PB     1|Z     1|NF     0|PF     1|USED
    ...........................................................
    Total Entries     1    Used Entries      0    Free Entries      1
    Total Blocks   4223    Used Blocks       0    Free Blocks    4223
                           Used space =      0    Free space =  33784
    ...........................................................
    
    umm malloc test   time  = 1507118 uS
    Allocations =  40000, uSec per allocation = 37
    
    ----------- Compressor LZSS test -------------
    Uncompressed size = 2048
    Compressed   size = 1858. Max. alloc.= 14384. Time = 7406 uS
    Decompress                Max. alloc.= 1048. Time = 989 uS
    Decompress Ok!
    
    ----------- Compressor Zlib test -------------
    Uncompressed size = 2048
    Compressed   size = 1740. Max. alloc.= 24288. Time = 11716 uS
    Decompress                Max. alloc.= 15768. Time = 912 uS
    Decompress Ok!
    
    ----------- Compressor S-LZW test -------------
    Uncompressed size = 2048
    Compressed   size = 2035. Max. alloc.= 4320. Time = 2839 uS
    Decompress                Max. alloc.= 4320. Time = 4194 uS
    Decompress Ok!
    
    ----------- Compressor FastLZ test -------------
    Uncompressed size = 2048
    Compressed   size = 1834. Max. alloc.= 32776. Time = 1028 uS
    Decompress                Max. alloc.= 0. Time = 160 uS
    Decompress Ok!
    
    
    ----------- WHETSTONE FLOAT -------------
    
    .........MODULE 1:  simple identifiers...
      xx1  = -0.06679254770278930700
      xx2  = -0.46633863449096680000
      xx3  = -0.73303699493408203000
      xx4  = -1.13254797458648680000
    .........MODULE 2:  array elements.......
      e10  = -0.06834230571985244800
      e11  = -0.46263590455055237000
      e12  = -0.72971796989440918000
      e13  = -1.12397670745849610000
    .........MODULE 3:  array as parameter...
      e1_0 = -0.05533060804009437600
      e1_1 = -0.44743216037750244000
      e1_2 = -0.71096724271774292000
      e1_3 = -1.10309338569641110000
    .........MODULE 4:  conditional jumps....
      val  = 1
    .........MODULE 6:  integer arithmetic...
      e1k  = 6.00000000000000000000
      e1l  = 6.00000000000000000000
    .........MODULE 7:  trig. functions......
      x1   = 0.49040567874908447000
      y1   = 0.49039086699485779000
    .........MODULE 8:  procedure calls......
      z    = 0.99993747472763062000
    .........MODULE9:  array references......
      e1_j = -1.10309338569641110000
      e1_k = 3.00000000000000000000
      e1_l = -1.10309338569641110000
    .........MODULE10:  integer arithmetic...
      j    = 2
      k    = 3
    .........MODULE11:  standard functions...
      x    = 0.83466011285781860000
    ........................................
    Whetstone last    time (uS) = 08925.00
    Whetstone max     time (uS) = 08926.00
    Whetstone min     time (uS) = 08925.00
    
    
    ----------- WHETSTONE DOUBLE -------------
    
    .........MODULE 1:  simple identifiers...
      xx1  = -0.06679268039452399000
      xx2  = -0.46633881454398041000
      xx3  = -0.73303694842681344000
      xx4  = -1.13254799829068810000
    .........MODULE 2:  array elements.......
      e10  = -0.06834219862995163900
      e11  = -0.46263765626356895000
      e12  = -0.72971838784369047000
      e13  = -1.12397907004612830000
    .........MODULE 3:  array as parameter...
      e1_0 = -0.05533645259179446200
      e1_1 = -0.44743656275474680000
      e1_2 = -0.71097338928518250000
      e1_3 = -1.10309805692560080000
    .........MODULE 4:  conditional jumps....
      val  = 1
    .........MODULE 6:  integer arithmetic...
      e1k  = 6.00000000000000000000
      e1l  = 6.00000000000000000000
    .........MODULE 7:  trig. functions......
      x1   = 0.49040731615903904000
      y1   = 0.49039249795609352000
    .........MODULE 8:  procedure calls......
      z    = 0.99993750062499998000
    .........MODULE9:  array references......
      e1_j = -1.10309805692560080000
      e1_k = 3.00000000000000000000
      e1_l = -1.10309805692560080000
    .........MODULE10:  integer arithmetic...
      j    = 2
      k    = 3
    .........MODULE11:  standard functions...
      x    = 0.83466551951905033000
    ........................................
    Whetstone last    time (uS) = 166298.00
    Whetstone max     time (uS) = 166298.00
    Whetstone min     time (uS) = 166298.00
    
    
    ----------- DHRYSTONE 2 -------------
    
    
    Dhrystone Benchmark, Version 2.1 (Language: C)
    Program compiled without 'register' attribute
    Execution starts, 20000 runs through Dhrystone
                                                  Execution ends
    Final values of the variables used in the benchmark:
    Int_Glob:            5
            should be:   5
    Bool_Glob:           1
            should be:   1
    Ch_1_Glob:           A
            should be:   A
    Ch_2_Glob:           B
            should be:   B
    Arr_1_Glob[8]:       7
            should be:   7
    Arr_2_Glob[8][7]:    20010
            should be:   Number_Of_Runs + 10
    Ptr_Glob->
      Ptr_Comp:          536870816
            should be:   (implementation-dependent)
      Discr:             0
            should be:   0
      Enum_Comp:         2
            should be:   2
      Int_Comp:          17
            should be:   17
      Str_Comp:          DHRYSTONE PROGRAM, SOME STRING
            should be:   DHRYSTONE PROGRAM, SOME STRING
    Next_Ptr_Glob->
      Ptr_Comp:          536870816
            should be:   (implementation-dependent), same as above
      Discr:             0
            should be:   0
      Enum_Comp:         1
            should be:   1
      Int_Comp:          18
            should be:   18
      Str_Comp:          DHRYSTONE PROGRAM, SOME STRING
            should be:   DHRYSTONE PROGRAM, SOME STRING
    Int_1_Loc:           5
            should be:   5
    Int_2_Loc:           13
            should be:   13
    Int_3_Loc:           7
            should be:   7
    Enum_Loc:            1
            should be:   1
    Str_1_Loc:           DHRYSTONE PROGRAM, 1'ST STRING
            should be:   DHRYSTONE PROGRAM, 1'ST STRING
    Str_2_Loc:           DHRYSTONE PROGRAM, 2'ND STRING
            should be:   DHRYSTONE PROGRAM, 2'ND STRING
    Time = 91000 us
    Microseconds for one run through Dhrystone: 4.55
    Dhrystones per Second:                      219780
    
    
    ----------- COREMARK -------------
    
    2K performance run parameters for coremark.
    CoreMark Size    : 666
    Total ticks      : 37386523
    Total time (secs): 37.386523
    Iterations/Sec   : 267.476064
    Iterations       : 10000
    Compiler version : armcc V5.06 (build 20)
    Compiler flags   :  -O3 -Otime
    Memory location  : IRAM
    seedcrc          : 0xe9f5
    [0]crclist       : 0xe714
    [0]crcmatrix     : 0x1fd7
    [0]crcstate      : 0x8e3a
    [0]crcfinal      : 0x988c
    Correct operation validated. See readme.txt for run and reporting rules.
    CoreMark 1.0 : 267.476064 / armcc V5.06 (build 20)  -O3 -Otime / IRAM
    
    END.
    


    Вывод в терминал результатов теста скомпилированного в GCC
    ----------- Speed Test -------------
    
    
    Reference time = 100001 us
    
    ----------- umm malloc test -------------
    ...........................................................
    |0x1fff5280|B     0|NB     1|PB     0|Z     1|NF     1|PF     0|USED
    |0x1fff5288|B     1|NB  4223|PB     0|Z  4222|NF  4223|PF     0|FREE
    |0x1fffd678|B  4223|NB     0|PB     1|Z     1|NF     0|PF     1|USED
    ...........................................................
    Total Entries     1    Used Entries      0    Free Entries      1
    Total Blocks   4223    Used Blocks       0    Free Blocks    4223
                           Used space =      0    Free space =  33784
    ...........................................................
    
    umm malloc test   time  = 983944 uS
    Allocations =  40000, uSec per allocation = 24
    
    ----------- Compressor LZSS test -------------
    Uncompressed size = 2048
    Compressed   size = 1858. Max. alloc.= 14384. Time = 8504 uS
    Decompress                Max. alloc.= 1048. Time = 673 uS
    Decompress Ok!
    
    ----------- Compressor Zlib test -------------
    Uncompressed size = 2048
    Compressed   size = 1740. Max. alloc.= 24288. Time = 12384 uS
    Decompress                Max. alloc.= 15768. Time = 1070 uS
    Decompress Ok!
    
    ----------- Compressor S-LZW test -------------
    Uncompressed size = 2048
    Compressed   size = 2035. Max. alloc.= 4320. Time = 2577 uS
    Decompress                Max. alloc.= 4320. Time = 4189 uS
    Decompress Ok!
    
    ----------- Compressor FastLZ test -------------
    Uncompressed size = 2048
    Compressed   size = 1834. Max. alloc.= 32776. Time = 1045 uS
    Decompress                Max. alloc.= 0. Time = 234 uS
    Decompress Ok!
    
    
    ----------- WHETSTONE FLOAT -------------
    
    .........MODULE 1:  simple identifiers...
      xx1  = -0.06679254770278930664
      xx2  = -0.46633863449096679688
      xx3  = -0.73303699493408203125
      xx4  = -1.13254797458648681641
    .........MODULE 2:  array elements.......
      e10  = -0.06834230571985244751
      e11  = -0.46263590455055236816
      e12  = -0.72971796989440917969
      e13  = -1.12397670745849609375
    .........MODULE 3:  array as parameter...
      e1_0 = -0.05533138290047645569
      e1_1 = -0.44743290543556213379
      e1_2 = -0.71096915006637573242
      e1_3 = -1.10309529304504394531
    .........MODULE 4:  conditional jumps....
      val  = 1
    .........MODULE 6:  integer arithmetic...
      e1k  = 6.00000000000000000000
      e1l  = 6.00000000000000000000
    .........MODULE 7:  trig. functions......
      x1   = 0.49040564894676208496
      y1   = 0.49039086699485778809
    .........MODULE 8:  procedure calls......
      z    = 0.99993747472763061523
    .........MODULE9:  array references......
      e1_j = -1.10309529304504394531
      e1_k = 3.00000000000000000000
      e1_l = -1.10309529304504394531
    .........MODULE10:  integer arithmetic...
      j    = 2
      k    = 3
    .........MODULE11:  standard functions...
      x    = 0.83466064929962158203
    ........................................
    Whetstone last    time (uS) = 13629.00
    Whetstone max     time (uS) = 13630.00
    Whetstone min     time (uS) = 13629.00
    
    
    ----------- WHETSTONE DOUBLE -------------
    
    .........MODULE 1:  simple identifiers...
      xx1  = -0.06679268039452398997
      xx2  = -0.46633881454398040667
      xx3  = -0.73303694842681343946
      xx4  = -1.13254799829068808492
    .........MODULE 2:  array elements.......
      e10  = -0.06834219862995163930
      e11  = -0.46263765626356895266
      e12  = -0.72971838784369047470
      e13  = -1.12397907004612829240
    .........MODULE 3:  array as parameter...
      e1_0 = -0.05533645259179446191
      e1_1 = -0.44743656275474680273
      e1_2 = -0.71097338928518249990
      e1_3 = -1.10309805692560081170
    .........MODULE 4:  conditional jumps....
      val  = 1
    .........MODULE 6:  integer arithmetic...
      e1k  = 6.00000000000000000000
      e1l  = 6.00000000000000000000
    .........MODULE 7:  trig. functions......
      x1   = 0.49040731615904653573
      y1   = 0.49039249795610123650
    .........MODULE 8:  procedure calls......
      z    = 0.99993750062499997533
    .........MODULE9:  array references......
      e1_j = -1.10309805692560081170
      e1_k = 3.00000000000000000000
      e1_l = -1.10309805692560081170
    .........MODULE10:  integer arithmetic...
      j    = 2
      k    = 3
    .........MODULE11:  standard functions...
      x    = 0.83466551951905032514
    ........................................
    Whetstone last    time (uS) = 219895.00
    Whetstone max     time (uS) = 219895.00
    Whetstone min     time (uS) = 219894.00
    
    
    ----------- DHRYSTONE 2 -------------
    
    
    Dhrystone Benchmark, Version 2.1 (Language: C)
    Program compiled without 'register' attribute
    Execution starts, 20000 runs through Dhrystone
                                                  Execution ends
    Final values of the variables used in the benchmark:
    Int_Glob:            5
            should be:   5
    Bool_Glob:           1
            should be:   1
    Ch_1_Glob:           A
            should be:   A
    Ch_2_Glob:           B
            should be:   B
    Arr_1_Glob[8]:       7
            should be:   7
    Arr_2_Glob[8][7]:    20010
            should be:   Number_Of_Runs + 10
    Ptr_Glob->
      Ptr_Comp:          536870792
            should be:   (implementation-dependent)
      Discr:             0
            should be:   0
      Enum_Comp:         2
            should be:   2
      Int_Comp:          17
            should be:   17
      Str_Comp:          DHRYSTONE PROGRAM, SOME STRING
            should be:   DHRYSTONE PROGRAM, SOME STRING
    Next_Ptr_Glob->
      Ptr_Comp:          536870792
            should be:   (implementation-dependent), same as above
      Discr:             0
            should be:   0
      Enum_Comp:         1
            should be:   1
      Int_Comp:          18
            should be:   18
      Str_Comp:          DHRYSTONE PROGRAM, SOME STRING
            should be:   DHRYSTONE PROGRAM, SOME STRING
    Int_1_Loc:           5
            should be:   5
    Int_2_Loc:           13
            should be:   13
    Int_3_Loc:           7
            should be:   7
    Enum_Loc:            1
            should be:   1
    Str_1_Loc:           DHRYSTONE PROGRAM, 1'ST STRING
            should be:   DHRYSTONE PROGRAM, 1'ST STRING
    Str_2_Loc:           DHRYSTONE PROGRAM, 2'ND STRING
            should be:   DHRYSTONE PROGRAM, 2'ND STRING
    Time = 74000 us
    Microseconds for one run through Dhrystone: 3.70
    Dhrystones per Second:                      270270
    
    
    ----------- COREMARK -------------
    
    2K performance run parameters for coremark.
    CoreMark Size    : 666
    Total ticks      : 45291107
    Total time (secs): 45.291107
    Iterations/Sec   : 220.793897
    Iterations       : 10000
    Compiler version : GCC4.8.4 20140725 (release) [ARM/embedded-4_8-branch revision 213147]
    Compiler flags   :  -O3 -Otime
    Memory location  : IRAM
    seedcrc          : 0xe9f5
    [0]crclist       : 0xe714
    [0]crcmatrix     : 0x1fd7
    [0]crcstate      : 0x8e3a
    [0]crcfinal      : 0x988c
    Correct operation validated. See readme.txt for run and reporting rules.
    CoreMark 1.0 : 220.793897 / GCC4.8.4 20140725 (release) [ARM/embedded-4_8-branch revision 213147]  -O3 -Otime / IRAM
    
    END.
    


    Вывод в терминал результатов теста запущенного в Visual Studio 2015
    ----------- Speed Test -------------
    
    
    Reference time = 100000 us
    
    ----------- umm malloc test -------------
    ...........................................................
    |0x00ba5980|B     0|NB     1|PB     0|Z     1|NF     1|PF     0|USED
    |0x00ba5988|B     1|NB  4223|PB     0|Z  4222|NF  4223|PF     0|FREE
    |0x00badd78|B  4223|NB     0|PB     1|Z     1|NF     0|PF     1|USED
    ...........................................................
    Total Entries     1    Used Entries      0    Free Entries      1
    Total Blocks   4223    Used Blocks       0    Free Blocks    4223
                           Used space =      0    Free space =  33784
    ...........................................................
    
    umm malloc test   time  = 13586 uS
    Allocations =  40000, uSec per allocation = 0
    
    ----------- Compressor LZSS test -------------
    Uncompressed size = 2048
    Compressed   size = 1858. Max. alloc.= 14384. Time = 146 uS
    Decompress                Max. alloc.= 1048. Time = 10 uS
    Decompress Ok!
    
    ----------- Compressor Zlib test -------------
    Uncompressed size = 2048
    Compressed   size = 1740. Max. alloc.= 24288. Time = 241 uS
    Decompress                Max. alloc.= 15768. Time = 20 uS
    Decompress Ok!
    
    ----------- Compressor S-LZW test -------------
    Uncompressed size = 2048
    Compressed   size = 2035. Max. alloc.= 4320. Time = 47 uS
    Decompress                Max. alloc.= 4320. Time = 31 uS
    Decompress Ok!
    
    ----------- Compressor FastLZ test -------------
    Uncompressed size = 2048
    Compressed   size = 1834. Max. alloc.= 32776. Time = 13 uS
    Decompress                Max. alloc.= 0. Time = 4 uS
    Decompress Ok!
    
    
    ----------- WHETSTONE FLOAT -------------
    
    .........MODULE 1:  simple identifiers...
      xx1  = -0.06679254770278930700
      xx2  = -0.46633863449096680000
      xx3  = -0.73303699493408203000
      xx4  = -1.13254797458648680000
    .........MODULE 2:  array elements.......
      e10  = -0.06834230571985244800
      e11  = -0.46263590455055237000
      e12  = -0.72971796989440918000
      e13  = -1.12397670745849610000
    .........MODULE 3:  array as parameter...
      e1_0 = -0.05533060804009437600
      e1_1 = -0.44743216037750244000
      e1_2 = -0.71096724271774292000
      e1_3 = -1.10309338569641110000
    .........MODULE 4:  conditional jumps....
      val  = 1
    .........MODULE 6:  integer arithmetic...
      e1k  = 6.00000000000000000000
      e1l  = 6.00000000000000000000
    .........MODULE 7:  trig. functions......
      x1   = 0.49040612578392029000
      y1   = 0.49039128422737122000
    .........MODULE 8:  procedure calls......
      z    = 0.99993747472763062000
    .........MODULE9:  array references......
      e1_j = -1.10309338569641110000
      e1_k = 3.00000000000000000000
      e1_l = -1.10309338569641110000
    .........MODULE10:  integer arithmetic...
      j    = 2
      k    = 3
    .........MODULE11:  standard functions...
      x    = 0.83466225862503052000
    ........................................
    Whetstone last    time (uS) = 00131.00
    Whetstone max     time (uS) = 00168.00
    Whetstone min     time (uS) = 00123.00
    
    
    ----------- WHETSTONE DOUBLE -------------
    
    .........MODULE 1:  simple identifiers...
      xx1  = -0.06679268039452399000
      xx2  = -0.46633881454398041000
      xx3  = -0.73303694842681344000
      xx4  = -1.13254799829068810000
    .........MODULE 2:  array elements.......
      e10  = -0.06834219862995163900
      e11  = -0.46263765626356895000
      e12  = -0.72971838784369047000
      e13  = -1.12397907004612830000
    .........MODULE 3:  array as parameter...
      e1_0 = -0.05533645259179446200
      e1_1 = -0.44743656275474680000
      e1_2 = -0.71097338928518250000
      e1_3 = -1.10309805692560080000
    .........MODULE 4:  conditional jumps....
      val  = 1
    .........MODULE 6:  integer arithmetic...
      e1k  = 6.00000000000000000000
      e1l  = 6.00000000000000000000
    .........MODULE 7:  trig. functions......
      x1   = 0.49040731615904543000
      y1   = 0.49039249795610007000
    .........MODULE 8:  procedure calls......
      z    = 0.99993750062499998000
    .........MODULE9:  array references......
      e1_j = -1.10309805692560080000
      e1_k = 3.00000000000000000000
      e1_l = -1.10309805692560080000
    .........MODULE10:  integer arithmetic...
      j    = 2
      k    = 3
    .........MODULE11:  standard functions...
      x    = 0.83466551951905787000
    ........................................
    Whetstone last    time (uS) = 00152.00
    Whetstone max     time (uS) = 00186.00
    Whetstone min     time (uS) = 00142.00
    
    
    ----------- DHRYSTONE 2 -------------
    
    
    Dhrystone Benchmark, Version 2.1 (Language: C)
    Program compiled without 'register' attribute
    Execution starts, 20000 runs through Dhrystone
    Execution ends
    Final values of the variables used in the benchmark:
    Int_Glob:            5
            should be:   5
    Bool_Glob:           1
            should be:   1
    Ch_1_Glob:           A
            should be:   A
    Ch_2_Glob:           B
            should be:   B
    Arr_1_Glob[8]:       7
            should be:   7
    Arr_2_Glob[8][7]:    20010
            should be:   Number_Of_Runs + 10
    Ptr_Glob->
      Ptr_Comp:          3602560
            should be:   (implementation-dependent)
      Discr:             0
            should be:   0
      Enum_Comp:         2
            should be:   2
      Int_Comp:          17
            should be:   17
      Str_Comp:          DHRYSTONE PROGRAM, SOME STRING
            should be:   DHRYSTONE PROGRAM, SOME STRING
    Next_Ptr_Glob->
      Ptr_Comp:          3602560
            should be:   (implementation-dependent), same as above
      Discr:             0
            should be:   0
      Enum_Comp:         1
            should be:   1
      Int_Comp:          18
            should be:   18
      Str_Comp:          DHRYSTONE PROGRAM, SOME STRING
            should be:   DHRYSTONE PROGRAM, SOME STRING
    Int_1_Loc:           5
            should be:   5
    Int_2_Loc:           13
            should be:   13
    Int_3_Loc:           7
            should be:   7
    Enum_Loc:            1
            should be:   1
    Str_1_Loc:           DHRYSTONE PROGRAM, 1'ST STRING
            should be:   DHRYSTONE PROGRAM, 1'ST STRING
    Str_2_Loc:           DHRYSTONE PROGRAM, 2'ND STRING
            should be:   DHRYSTONE PROGRAM, 2'ND STRING
    Time = 551 us
    Microseconds for one run through Dhrystone: 0.03
    Dhrystones per Second:                      36297640
    
    
    ----------- COREMARK -------------
    
    2K performance run parameters for coremark.
    CoreMark Size    : 666
    Total ticks      : 11012043
    Total time (secs): 11.012043
    Iterations/Sec   : 9080.967083
    Iterations       : 100000
    Compiler version : VS 2013
    Compiler flags   :  -O3 -Otime
    Memory location  : IRAM
    seedcrc          : 0xe9f5
    [0]crclist       : 0xe714
    [0]crcmatrix     : 0x1fd7
    [0]crcstate      : 0x8e3a
    [0]crcfinal      : 0xd340
    Correct operation validated. See readme.txt for run and reporting rules.
    CoreMark 1.0 : 9080.967083 / VS 2015  -O3 -Otime / IRAM
    
    END.
    



    Как тут оказался Intel Core i7


    Дело в том, что все алгоритмы сжатия и менеджер памяти отлаживались в среде Visual Studio и это процессор моего компьютера. В архиве есть директория SpeedTest_VS, где содержится проект для Visual Studio 2015 и в котором можно при желании продолжить совершенствование данных алгоритмов.

    Вывод


    IAR оказался безусловным лидером рейтинга. Самое удивительно что, сохраняя эффективность кода IAR также лидер и по скорости компиляции. Неучтенная здесь ложка дёгтя в том, что IAR поставляется с довольно мало функциональным редактором исходных текстов. Можно конечно запускать компиляцию инструментами IAR прямо из среды KDS, поскольку KDS это тот же слегка модифицированный Eclipse версии Mylyn. Но время перекомпиляции тогда увеличивается до 2 мин! У Eclipse тоже есть недостаток, он медленно открывается, с некоторого размера исходников у него начинает тормозиться контекстный парсинг. В проекте данного теста есть директория SpeedTest_SE. Там содержится файл SpeedTest.vpw рабочего пространства проекта данного теста для редактора SlickEdit. SlickEdit прекрасный, очень быстрый редактор, а IAR IDE умеет автоматически отслеживать изменения файлов, поэтому не возникает проблем в их совместном использовании.

    Полный архив проекта (97.7 MB) доступен по ссылке https://drive.google.com/file/d/0B5dbvc_yPqJHYWI0OE9YZklKRjQ/view?usp=sharing
    Метки:
    • +7
    • 11,1k
    • 8
    Поделиться публикацией
    Комментарии 8
    • 0
      Еще хотелось бы clang увидеть рядом, конечно.
      • 0
        Что и требовалось доказать…
        • +1
          www.ghs.com/products/compiler.html

          Вот этот компилятор еще бы попробовать.
          • 0
            судя по тестам, у меня складывается ощущение, что gcc не подключил (или не использовал) сопроцессор.
            по времени компиляции для случая gcc можно попробовать указать системе сборки использовать параллельную компиляцию (make -j8 например), если это возможно.

            табличку тяжело изучать, так как в 1/3 случаев для случаев второго места — нет процентажа.
            • 0
              GCC сопроцессор подключил это можно увидеть в листинге ассемблера. В проекте все вложено.
              Сборка была из KDS, ничего другого не тестировалось.
              Таблица такая уж получилась. Не хотелось еще загромождать цифрами.
            • 0
              Во-первых, в каждой из сред Keil, IAR, GCC будет своя библиотека кучи и не хотелось тратить время на исследование особенностей каждой из них
              Какая-то полумера. Нет, обоснование понятное: поставить в равные условия. Но ведь тогда нужно не использовать и libc, всякие libgcc, startfiles (серия опций -nostdlib -nostartfiles у GCC), предоставив единую реализацию. А то правильно, рантайм Kail, IAR заточен на embedded, а GCC всё же копилятор с более широким спектром поддерживаемых платформ. В нашем проекте пришлось выкидывать стандартный рантайм, т.к. весил очень много и писать свою функциональность, минимально-необходимую (по принципу: «что вылезет на линковке»). Сэкономили почти 100кБ (из 300 доступных, C++11). Хотя это и аффектит только последние два пункта. Но всё же. В остальном интересно размышление Elvish в geektimes.ru/post/264558/#comment_8934830. Ровно как и сборка вне IDE.

              ЗЫ традиционный риторический вопрос: это же про программирование, это же тематика хабра, не?
              • 0
                Нужна была библиотека работы с heap со способностью регистрировать утечки и расход памяти.
                К штатным пришлось бы к каждой писать свою обертку.

                • 0
                  Не-не-не, я это как раз понимаю и поддерживаю. Вопрос — почему остальной рантайм не унифицирован?

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.