Quantcast
Channel: User Lundin - Code Review Stack Exchange
Viewing all articles
Browse latest Browse all 42

Answer by Lundin for Optimizing C System Design for Sensor Data Handling

$
0
0

Regarding performance:

  • From lower-level embedded systems we may pick up the good practice "never use memcpy unless you actually have to". If the socket lib is already doing such through the API then that's already bad enough without the application adding further copying on top of that.

    Most often we can instead keep 2 or more buffers allocated (similar to uint8_t Buf[MAX_TCP_FRAME];) and just swap the pointers between them. Often there is no need to "zero out" old data either, but just to overwrite it.

    And regarding threading, it is good to minimize the time spent inside a mutex lock, since if we have lots of code there we are stalling other parts of the program. I would wildly guess that this part is the main bottleneck.

    Though if you are to forward this data on someone else outside this module, there might seem to be no other way around it than hard copying. A different approach then could be to skip the local variable and instead pre-allocate a chunk using malloc so that the data will persist. Let the socket write directly into the malloc buffer and then have the circular buffer work on pointers to allocated data instead of doing hard copies. malloc does come with overhead, but if you malloc the next chunk just after receiving data, you may be able to time it so that you are doing malloc while the socket is still receiving the next incoming data packet.

  • The standard nit-pick code review remark for structs is that circular_buffer is poorly optimized with regards to alignment. You shouldn't have a small type like bool in the middle of a struct, put small types at the end to minimize the need for padding.

Regarding coding style:

The rule of thumb is to never use goto because if you do, you have to suffer the old "goto considered harmful" debate yet again. Or as various industry coding standards usually put it: it's ok to use goto for error handling, but only if you jump downwards.

In this specific case, goto just makes readability worse. As does the while loop even. The first loop could be replaced with an idiomatic, readable for loop (and maybe less verbose names to get shorter lines, but that's a minor thing):

ssize_t total_read;ssize_t bytes_read = 0;for(total_read = 0; total_read < HEADER_SIZE; total_read += bytes_read){  bytes_read = recv(socket_fd, buffer + total_read, HEADER_SIZE - total_read, 0);  // error handling code is never fun to read so best write it as clear as possible  if(bytes_read == -1)  {    if(errno == EINTR)     {       bytes_read=0; /* ignore and continue */     }    else    {      return -1;    }  }  else if (bytes_read == 0)  {    return 0;  }}...// next loop may have to skip the total_read initialization

Viewing all articles
Browse latest Browse all 42

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>