File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -10,7 +10,7 @@ cmake_minimum_required(VERSION 3.20)
1010
1111project (canard)
1212enable_testing ()
13-
13+ set (CMAKE_CTEST_ARGUMENTS "-V" ) # Enable test outputs when running `make test`
1414set (CMAKE_EXPORT_COMPILE_COMMANDS ON )
1515
1616# Shared Clang-Format target for all subprojects.
Original file line number Diff line number Diff line change @@ -133,6 +133,30 @@ static byte_t popcount(const uint64_t x)
133133#endif
134134}
135135
136+ /// See ctz().
137+ static byte_t ctz_emulated (uint32_t x )
138+ {
139+ CANARD_ASSERT (x != 0U );
140+ byte_t v = 0 ;
141+ while ((x & 1U ) == 0U ) {
142+ x >>= 1U ;
143+ ++ v ;
144+ }
145+ return v ;
146+ }
147+
148+ /// Count trailing zeros (ctz), aka find first set (ffs), aka the index of the least-significant set bit.
149+ /// Undefined for zero argument.
150+ static byte_t ctz (const uint32_t x )
151+ {
152+ #if defined(__GNUC__ ) || defined(__clang__ ) || defined(__CC_ARM )
153+ CANARD_ASSERT (x != 0U );
154+ return (byte_t )__builtin_ctzl (x );
155+ #else
156+ return ctz_emulated (x );
157+ #endif
158+ }
159+
136160static void * mem_alloc (const canard_mem_t memory , const size_t size ) { return memory .vtable -> alloc (memory , size ); }
137161static void * mem_alloc_zero (const canard_mem_t memory , const size_t size )
138162{
Original file line number Diff line number Diff line change @@ -389,7 +389,15 @@ struct canard_t
389389 /// due to the limited bus capacity; at the same time, CAN is likely to be used with small memory-limited
390390 /// devices. Hence we introduce a design tradeoff favoring smaller memory footprint over insertion efficiency,
391391 /// which is reasonable on the assumption that the number of simultaneously enqueued transfers (sic! not frames)
392- /// is typically small, on the order of a couple dozen at most.
392+ /// is typically small, on the order of a couple dozen at most. At small N, linked lists are even expected to
393+ /// outperform BST lookup; given r=2 is the approximate complexity premium of BST lookup over list scan,
394+ /// assuming that an average list lookup ends halfway, then the complexity crossover point is about:
395+ ///
396+ /// N/2 > r log2(N)
397+ ///
398+ /// So for r=2, we expect linked lists to outperform BSTs for less than about 15 pending transfers per shard
399+ /// (per default, RPC-service and message transfers use different shards, also each priority level is separate).
400+ /// The number of frames per transfer is irrelevant here as it doesn't affect the asymptotic complexity.
393401 ///
394402 /// The structures are optimized to minimize the poll complexity, since it is on the hot path, at the expense
395403 /// of insertion and cancellation paths. Each pending queue is a simple FIFO; the priority ordering is done
You can’t perform that action at this time.
0 commit comments