source: doc/theses/mike_brooks_MMath/benchmarks/list/_classic.c @ bf0c723

ADTast-experimental
Last change on this file since bf0c723 was 0b66ef9, checked in by Michael Brooks <mlbrooks@…>, 15 months ago

Add linked list performance experiment

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/*
2
3$cfa is the result of building this configuration:
4../cfa-cc/configure --with-target-hosts=host:nodebug
5
6
7Make it fixed duration and report mean time/op.
8
9I want the field of competitors to include
10        STL-reference
11        STL-value
12        u++ intrusive
13        LQ intrusive
14        Something from Boost?
15
16Insert-remove tests
17-------------------
18
19These are the fundamental list operations.
20
21The basic end-managed shapes:
22        First-First stack
23        Last-Last stack
24        First-to-last queue
25        Last-to-first queue
26        Rando Deque
27
28Do the basic shapes, using the head for both operations.
29Repeat the basic shapes, using the head for one operation and an element accessor for the other.
30
31Fix a baseline basic shape
32  - probably first-first stack
33  - intent: the best and simplest
34Varying the fun operation across insert, remove
35Do the fun operation as item-oriented random middle.
36Do the boring operation (probably) using head-provided accessors
37
38All the above on a subsequent list direction
39
40Probably want to vary
41 - am linking nodes in memory order
42 - random access
43
44
45
46Traversal tests
47---------------
48
49Set up a large bunch of inter-linked nodes.  Walk the list.
50
51Cases
52 - am walking in memory order
53 - am walking doing random access
54
55
56
57Measures of overhead
58--------------------
59
60Example motivations
61- some scenarios need running an RNG each iteration
62  - don't assume I'm getting the same RNG on each platform
63  - don't report time in RNG as a slowdown of the scenario that needs it
64- slowdowns due to random accesses (inevitable cache misses) are the user's fault
65- slowdowns due to memory allocation are the SUT's fault
66- slowdowns due to cache churn because SUT uses more memory than necessary are SUT's fault
67  - these are also unlikely
68  - I haven't designed experiments to catch it
69
70Actual RNG uses
71- for the rando-deque scenario: coin toss to work at head or tail
72- for the insert/remove-at-middle operations: index of item (in master array) to work on next
73    - can be a precomputed master array
74> It almost all generalizes into a precomputed master array
75  - Except: choice of head-oriented at-front/at-back implies different control flow (branch prediction, FP indirection)
76    - While an element-oriented operation is always the same control flow
77    - [control flow within the harness; point is to reveal penalties due to control-flow in SUT]
78
79=====================
80
81Attic of early attempts to give the taxonomy above
82
83
84I want times for the basic operations, as applicable, in their various cases.
85  - head-end-provided insert/remove
86      exercising one end    (stack)
87      exercising both ends  (queue; rando-deque)
88  - item-relative insert/remove
89      in middle/random
90      at a head-managed end
91      at a head-unmanaged end
92  - mashup head-provided insert with item-relative remove, and vice-versa
93  - iterating through
94
95
96Insert          Remove
97Head:First      Head:Same
98Head:First      Head:Opposite
99
100[Insert]
101Head:First
102Head:Last
103Head:Randomly-Either
104Item:First
105Item:Last
106Item:Randomly-Middle
107
108[Remove]
109Head:Same / Head:First
110  ^^ If Insertion does Head:x then Removal does Head:x; else Removal does Head:First
111Head:Opposite / Head:Last
112  ^^ Ditto; not applicable for Randomly-Either
113
114
115*/
116
117
118#include <time.h>
119#include <stdio.h>
120
121#if defined IMPL_LQ
122
123        #include <sys/queue.h>
124        struct S {
125                volatile int f[64];
126                TAILQ_ENTRY(S) x;
127        };
128        TAILQ_HEAD(SL, S);
129
130
131#elif defined IMPL_STL
132
133        #include <list>
134        struct S {
135                volatile int f[64];
136        };
137
138#elif defined IMPL_UPP
139
140        #include <uC++.h>
141        #include <uSequence.h>
142        struct S : public uSeqable {
143                volatile int f[64];
144        };
145
146#elif defined IMPL_CFA
147
148        #include <containers/list.hfa>
149        struct S {
150                int f[64]; // FIXME: make "is volatile" consistent; given bug #TBD
151                inline dlink(S);
152        };
153        P9_EMBEDDED( S, dlink(S) )
154
155#elif defined IMPL_CFA_UPP_PORT
156
157        #include <bits/sequence.hfa>
158        struct S {
159                inline Seqable;
160                int f[64]; // FIXME: make "is volatile" consistent; given bug #TBD
161        };
162        static inline S *& Back( S * n ) {
163                return (S *)Back( (Seqable *)n );
164        }
165        static inline S *& Next( S * n ) {
166                return (S *)Next( (Colable *)n );
167        }
168
169#else
170        #error bad impl
171#endif
172
173
174#define Repeat( op ) for ( volatile unsigned int i = 0; i < NoOfNodes; i += 1 ) { op; }
175
176int main() {
177        enum { NoOfNodes = 1000, Times = 100000 }; // Times supposed to be 100000
178        struct S s[NoOfNodes];
179        clock_t start, end;
180        const char * impl = 0;
181
182    #define STATS
183    #define REPORT do { \
184        double elapsed = ((double) (end - start)) / CLOCKS_PER_SEC; \
185        printf("%s %f sec\n", impl, elapsed); \
186        STATS \
187    } while(0);
188
189    #if defined IMPL_LQ
190    do {
191        struct SL lst;
192        TAILQ_INIT(&lst);
193        start = clock();
194        for ( volatile unsigned int t = 0; t < Times; t += 1 ) {
195                Repeat( TAILQ_INSERT_TAIL( &lst, &s[i], x ) );
196                Repeat( TAILQ_REMOVE( &lst, TAILQ_FIRST( &lst ), x ) );
197        }
198        end = clock();
199        impl = "LQ, TAILQ";
200        REPORT
201    } while (0);
202    #elif defined IMPL_STL
203    do {
204        std::list<S *> lst;
205        start = clock();
206        for ( volatile unsigned int t = 0; t < Times; t += 1 ) {
207                Repeat( lst.push_back( &s[i] ) );
208                Repeat( lst.pop_front() );
209        }
210        end = clock();
211        impl = "STL list, pointer";
212        REPORT
213    } while (0);
214    #elif defined IMPL_UPP
215    do {
216        uSequence<S> lst;
217        start = clock();
218        for ( volatile unsigned int t = 0; t < Times; t += 1 ) {
219                Repeat( lst.addTail( &s[i] ) );
220                Repeat( lst.dropHead() );
221        }
222        end = clock();
223        impl = "u++ intrusive list";
224        REPORT
225    } while (0);
226    #elif defined IMPL_CFA
227    do {
228        dlist(S) lst;
229        start = clock();
230        for ( volatile unsigned int t = 0; t < Times; t += 1 ) {
231                Repeat( insert_last( lst, s[i] ) );
232                Repeat( remove( lst`first ) );
233        }
234        end = clock();
235        impl = "cfa mike-new intrusive list";
236        REPORT
237    } while (0);
238    #elif defined IMPL_CFA_UPP_PORT
239    do {
240        Sequence(S) lst;
241        start = clock();
242        for ( volatile unsigned int t = 0; t < Times; t += 1 ) {
243                Repeat( addHead( lst, s[i] ) );
244                Repeat( dropTail( lst ) );
245        }
246        end = clock();
247        impl = "cfa colby intrusive list";
248        REPORT
249    } while (0);
250
251    #endif
252}
Note: See TracBrowser for help on using the repository browser.