From fa8c795867b284239eb88970889a145cfa026f78 Mon Sep 17 00:00:00 2001 From: Sharvil Nanavati Date: Sat, 13 Jun 2015 02:12:08 -0700 Subject: [PATCH] Reduce CPU utilization from ~60% to ~10% on busy HCI reads. This patch improves RFCOMM throughput and reduces CPU utilization. Instead of using a counting semaphore to measure bytes and reading one at a time from the eager reader's buffer, read in bulk based on the incoming read request size. Change-Id: I17046bfbc3ca49576a9c82b38911aeb84234881a --- osi/src/eager_reader.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/osi/src/eager_reader.c b/osi/src/eager_reader.c index 6f0a88fec..63b190ea6 100644 --- a/osi/src/eager_reader.c +++ b/osi/src/eager_reader.c @@ -85,7 +85,7 @@ eager_reader_t *eager_reader_new( ret->allocator = allocator; ret->inbound_fd = fd_to_read; - ret->bytes_available_fd = eventfd(0, EFD_SEMAPHORE); + ret->bytes_available_fd = eventfd(0, 0); if (ret->bytes_available_fd == INVALID_FD) { LOG_ERROR("%s unable to create output reading semaphore.", __func__); goto error; @@ -170,31 +170,46 @@ size_t eager_reader_read(eager_reader_t *reader, uint8_t *buffer, size_t max_siz assert(reader != NULL); assert(buffer != NULL); - size_t bytes_read = 0; + // If the caller wants nonblocking behavior, poll to see if we have + // any bytes available before reading. + if (!block && !has_byte(reader)) + return 0; - while (bytes_read < max_size) { - if (!block && !has_byte(reader)) - return bytes_read; + // Find out how many bytes we have available in our various buffers. + eventfd_t bytes_available; + if (eventfd_read(reader->bytes_available_fd, &bytes_available) == -1) { + LOG_ERROR("%s unable to read semaphore for output data.", __func__); + return 0; + } - eventfd_t value; - if (eventfd_read(reader->bytes_available_fd, &value) == -1) - LOG_ERROR("%s unable to read semaphore for output data.", __func__); + if (max_size > bytes_available) + max_size = bytes_available; + size_t bytes_consumed = 0; + while (bytes_consumed < max_size) { if (!reader->current_buffer) reader->current_buffer = fixed_queue_dequeue(reader->buffers); - buffer[bytes_read] = reader->current_buffer->data[reader->current_buffer->offset]; - reader->current_buffer->offset++; - bytes_read++; + size_t bytes_to_copy = reader->current_buffer->length - reader->current_buffer->offset; + if (bytes_to_copy > (max_size - bytes_consumed)) + bytes_to_copy = max_size - bytes_consumed; + + memcpy(&buffer[bytes_consumed], &reader->current_buffer->data[reader->current_buffer->offset], bytes_to_copy); + bytes_consumed += bytes_to_copy; + reader->current_buffer->offset += bytes_to_copy; - // Prep for next byte if (reader->current_buffer->offset >= reader->current_buffer->length) { reader->allocator->free(reader->current_buffer); reader->current_buffer = NULL; } } - return bytes_read; + bytes_available -= bytes_consumed; + if (eventfd_write(reader->bytes_available_fd, bytes_available) == -1) { + LOG_ERROR("%s unable to write back bytes available for output data.", __func__); + } + + return bytes_consumed; } static bool has_byte(const eager_reader_t *reader) { -- 2.11.0