プログラムの処理時間を計測するための関数の利用例として、\ref{sec:osi-basic-benchmark}で紹介した素数を求めるプログラムをC言語で記述したものを「エラトステネスのふるい:sieve.c」に示します。

sieve.cではプログラムの実行時間を計測するために以下のライブラリ関数が使用されています。

  • initexectime()は計時機能の時間を0に初期化します。
  • getexectime()は経過時間を秒単位で返します。
#include <xcore.h>
#define MAXSQRT 100
#define MAX MAXSQRT*MAXSQRT
void main()
{
    char  prime[MAX] ;
    int   i, j ;
	
    initexectime() ; // 計時時間の初期化
    cputs("INIT TABLE\n") ;
    for (i = 2; i < MAX; i++)
        prime[i] = 1 ;
    cprintf("DONE: %d sec\n", getexectime()) ; // 経過時間の表示
    cputs("SIEVE\n") ;
    for (i = 2; i < MAXSQRT; i++) {
        if (prime[i]) {
            cprintf("%d,", i) ;
            for (j = i; i * j < MAX; j++)
                prime[i * j] = 0 ;
        }
    }
    t = getexectime() ; // 経過時間の取得
    cprintf("\nDONE: %d sec\n", t) ;
    cputs("\nPRIME NUMBERS\n") ;
    for (i = 2; i < MAX ; i++) { 
        if (prime[i])
            cprintf("%d,", i) ;
    }
    cprintf("\nEXEC TIME: %d sec\n", t) ;
    wexit() ;
}

エラトステネスのふるい:sieve.c

プログラムをコンパイルして6502-CORE で実行した例を「sieve.cの実行結果」に示します。

計算結果の表示を除く計算時間は8秒(2MHz)でした。

sieve.cの実行結果

\ref{sec:apple1-basic-exec}節に、BASICで書かれたSIEVEの実行例を示しています。

同じアルゴリズムのプログラムですが、実行時間はやはりというか当然というか、こちらのCで書かれた方が9倍程度高速です。

sieve.cのmapファイルのSegment listを「生成コードのメモリマップ:sieve.c」に示します。

Segment list:
-------------
Name                   Start     End    Size  Align
----------------------------------------------------
ZEROPAGE              000080  000099  00001A  00001
STARTUP               001000  001016  000017  00001
ONCE                  001017  001022  00000C  00001
CODE                  001023  0018CF  0008AD  00001
RODATA                0018D0  00199E  0000CF  00001
DATA                  00199F  0019D5  000037  00001
BSS                   0019D6  001A01  00002C  00001

生成コードのメモリマップ:sieve.c

sieve.cの行数(処理内容)は、これまでのプログラムの中で最大ですが、コードサイズは同じようにcprintf()を使用しているevalpr.cより200バイト程度多いだけで、sieve.cで使用していないcscanf関数を使用しているevalprsc.cに比べれば、2KB以上小さなサイズとなっています。

Cの小さなプログラムでは、プログラムの行数以上に使用するライブラリ関数がコードサイズの大小に影響を与えることが確認できます。