This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.
Jacob Erlbeck jerlbeck at sysmocom.deOn 30.01.2014 16:43, Peter Stuge wrote: > Jacob Erlbeck wrote: >>> +/* add sec,usec to tv */ >>> +static void tv_add(struct timeval *tv, int sec, int usec) >>> +{ >>> + >>> + while (usec < 0) { >>> + usec += USEC_1S; >>> + sec--; >>> + } >>> + tv->tv_sec += sec; >>> + tv->tv_usec += usec; >>> + while (tv->tv_usec >= USEC_1S) { >>> + tv->tv_sec++; >>> + tv->tv_usec -= USEC_1S; >>> + } >>> +} >> >> I'm not sure whether it is a good idea to use while loops in this case >> since CPU usage is O(N) of the usec value. > > Remember that N>1 only with very small or very large usec values, > which I guess will be a corner case since it wasn't handled before? I think the question here is, do I want have a generic function that could be used in other places, too? If yes, I strongly advice to take into account that bad things could happen here (e.g. due to bugs delivering broken values for usec), eventually causing very-hard-to-diagnose latency problems. If you first check for out-of-range usecs, hint it with something like UNLIKELY() and do the div/mod in that case only. That's probably slightly faster than the while approach if most of the usecs are within 0..999999 and has still an upper bound. Or are we looking at the few applications already part of the patch, which would not have any advantage of allowing out of range usecs. > > Is there a machine where div/mod is actually more efficient than a > small number of iterations around a loop? :) That depends on 'small'. But sheer performance (throughput) is not always the most important, sometimes it's predictability, latency, and maintainability. And throughput at the cost of the others should be considered very carefully! >> Wouldn't it be more convenient to have a function tv_add_us(tv, usec) >> instead that does the div/mod stuff to a temporary timeval and then >> just calls timeradd()? Let's assume I had an implementation like (no it's not C) void tv_add_us(tv, usec) { struct timeval foo; foo.tv_sec = usec / 1000000; foo.tv_usec = usec % 1000000; timeradd(tv, &foo, tv); } Looking at the applications of the function: tv_add(&rs->transmit.last_tv, 0, USEC_20MS); tv_add(&rs->transmit.last_tv, sample_diff_excess / SAMPLES_1S, (sample_diff_excess % SAMPLES_1S) * USEC_SAMPLE); Which I then would write as tv_add_us(&rs->transmit.last_tv, USEC_20MS); tv_add_us(&rs->transmit.last_tv, sample_diff_excess * USEC_SAMPLE); And thanks to inlining the div/mod would vanish completely in the first case and would be without extra cost in the second. So no performance penalty but much better readability. > Is this a hot path? Then I think it makes sense to optimize harder > for performance rather than for readability. But compilers are good > at that too.. I'd rather go for readability by default until profiling tells me otherwise. Some well-intentioned hand optimizations lead sometimes to worse performance if the prevent the compiler from doing better optimizations. So on some platforms a branch taken can be more expensive than a div/mod. And did you understand the second application of tv_add() at first sight? It is correct but that is not obvious IMO. Jacob