Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize buffer access in the RingBuffer class #355

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Shivam7-1
Copy link

Optimize Buffer Access in RingBuffer Class
Issue: #347
Description:

This PR aims to optimize buffer access in the RingBuffer class by utilizing typed array views for more efficient data access. The changes improve performance by avoiding nested array accesses and directly accessing the underlying Float32Array.

Changes:

  • Refactored buffer access methods (push and pull) in the RingBuffer class to utilize typed array views for accessing channel data.
  • Removed nested array accesses and directly accessed the _data property of the RingBuffer class for improved efficiency.
  • Simplified index calculations for accessing channel data.

@Shivam7-1
Copy link
Author

Shivam7-1 commented Mar 30, 2024

Hi @mjwilson-google

I've made some significant changes in PR #355 , where I optimized buffer access in the RingBuffer class. I believe these changes could improve the performance of our project.

Could you please take a moment to review my PR? Your feedback would be greatly appreciated.

Additionally, I'm planning to apply for GSOC'24 and I'm particularly interested in this project. I believe that your insights would not only help improve my PR but also my application for GSOC'24.

Thank you for your time and consideration.

Best,
Shivam

Copy link
Collaborator

@mjwilson-google mjwilson-google left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the pull request!

I have added some comments. I think making the array contiguous should improve performance but it would be best if we had some profiling or other measurement to make sure everything is having the effect we desire.

There are some strange things about these ringbuffer implementations so I appreciate your interest and wish you luck on your application!

Comment on lines +195 to 197
get framesAvailable() {
return this._framesAvailable;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a duplicate of the function below; was this intended?

Comment on lines 219 to +222
const sourceLength = arraySequence[0].length;
const dataArray = this._data;
const channelCount = this._channelCount;
const length = this._length;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these const aliases for performance purposes? If so, did you measure the performance difference versus accessing the object members directly?


// Transfer data from the internal buffer to the |arraySequence| storage.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this comment?

}

// For excessive frames, the buffer will be overwritten.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to keep some form of this comment, and actually looking at this a bit more closely we probably need to update the read index if we overflow the buffer.

Some ringbuffers will stop when they get full; this one just keeps writing. Changing that is probably outside the scope of this PR. But we should probably at least keep the comment.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, keeping some form of the comment is important to acknowledge the discussion about the efficiency of the proposed optimization. Additionally, updating the read index if the buffer overflows is a valid consideration, as it ensures proper behavior when the buffer is full. While changing the behavior of the ring buffer to stop when it gets full might be outside the scope of this PR, updating the comment and considering the overflow scenario are reasonable adjustments. I'll make sure to address both points in the code and update the comment accordingly. Thank you for your input!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi
I had some Approach to updated code:

  • After pushing data into the buffer, the write index and frames available are updated as before.
  • Additionally, if the frames available exceed the buffer length, the read index is updated to the current write index, effectively wrapping around the buffer.
  • The pull method remains unchanged, only updating the read index and frames available.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds fine to me. I think it may be more common in audio to stop writing when full, probably because that would produce one large discontinuity instead of potentially many small discontinuities, but as long as we are clear about what happens when more data is written than there is space in the buffer either way should be OK.

The pull method has a similar issue of the read index overtaking the write index if we read more than _framesAvailable.

for (let channel = 0; channel < this._channelCount; ++channel) {
this._channelData[channel][this._writeIndex] = arraySequence[channel][i];
for (let channel = 0; channel < channelCount; ++channel) {
const index = (this._writeIndex + i) % length;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you measure that this is more efficient than storing back to the object member? There was a recent change that did the opposite of what is being proposed here so it would be good to quantify which version is faster, and maybe add a comment with the results as well.

@hoch hoch added the gsoc24 Google Summer of Code 2024 label May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gsoc24 Google Summer of Code 2024
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants