Skip to content

feat(parallel random reads): Changes to enable parallel random read handling in gcs reader #3619

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

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

abhishek10004
Copy link
Collaborator

@abhishek10004 abhishek10004 commented Jul 31, 2025

Description

This pull request introduces changes to enable parallel random reads in the GCS reader. This is achieved by refactoring the read logic in gcs_reader.go, introducing a mutex to manage concurrent access for range reader while allowing reads to go in parallel for MRD. The changes also include updates to the test suite to cover the new logic and parallel read scenarios.

Link to the issue in case of a bug fix.

b/427137532

Testing details

  1. Manual - Done
  2. Unit tests - Done
  3. Integration tests - NA

Any backward incompatible change? If so, please explain.

@abhishek10004 abhishek10004 added execute-perf-test Execute performance test in PR execute-integration-tests Run only integration tests labels Jul 31, 2025
Copy link

Hi @abhishek10004, it looks like you've invoked /gemini without a specific command. If you'd like me to perform a code review, please use /gemini review. If you'd like a summary of the pull request, please use /gemini summary. You can also type /gemini help to see a list of all available commands.

@abhishek10004
Copy link
Collaborator Author

/gemini review
/gemini summary

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces changes to enable parallel random reads in the GCS reader. This is achieved by refactoring the read logic in gcs_reader.go, introducing a mutex to manage concurrent access, and adding logic to dynamically switch between sequential (RangeReader) and random (MultiRangeReader) read strategies. The changes also include significant updates to the test suite to cover the new logic and parallel read scenarios.

While the changes to gcs_reader.go seem well-thought-out for concurrency, a critical issue has been introduced in internal/fs/fs.go by removing a file handle lock, which leads to a data race. Additionally, some of the test modifications appear fragile due to hardcoded mock expectations.

Comment on lines 2806 to -2808
fh.Inode().Lock()
defer fh.Unlock()

Choose a reason for hiding this comment

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

critical

Removing the lock on the file handle fh here introduces a data race. Multiple goroutines calling ReadFile on the same file handle will concurrently access and potentially modify fh.reader and fh.readManager within fh.Read and fh.ReadWithReadManager. This can lead to unpredictable behavior and crashes.

While the goal is to enable parallel reads, the file handle's internal state (like the reader instance) must be protected during initialization and updates. A lock is still required for this. Consider moving the lock inside fh.Read and fh.ReadWithReadManager to protect just the reader management logic, which would allow the actual read I/O operations to run in parallel if the underlying reader supports it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is okay since we are now synchronizing at the reader level (for range readers)

Copy link

codecov bot commented Aug 1, 2025

Codecov Report

❌ Patch coverage is 95.23810% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.36%. Comparing base (c2a7d57) to head (aa1f2ad).
⚠️ Report is 7 commits behind head on master.

Files with missing lines Patch % Lines
internal/gcsx/client_readers/gcs_reader.go 93.50% 4 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3619      +/-   ##
==========================================
+ Coverage   82.34%   82.36%   +0.02%     
==========================================
  Files         146      146              
  Lines       22524    22663     +139     
==========================================
+ Hits        18548    18667     +119     
- Misses       3428     3445      +17     
- Partials      548      551       +3     
Flag Coverage Δ
unittests 82.36% <95.23%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@abhishek10004 abhishek10004 marked this pull request as ready for review August 1, 2025 12:31
@abhishek10004 abhishek10004 requested a review from a team as a code owner August 1, 2025 12:31
@abhishek10004 abhishek10004 requested a review from charith87 August 1, 2025 12:31
Copy link

github-actions bot commented Aug 1, 2025

/gemini review

Copy link

github-actions bot commented Aug 1, 2025

/gemini summary

@github-actions github-actions bot added the remind-reviewers Auto remind reviewers in attention set for review post 24hrs of inactivity on PR. label Aug 1, 2025
@kislaykishore kislaykishore requested review from a team and Tulsishah and removed request for raj-prince, Tulsishah, vadlakondaswetha and a team August 1, 2025 12:32
func (rr *RangeReader) readFromExistingReader(ctx context.Context, req *gcsx.GCSReaderRequest) (gcsx.ReaderResponse, error) {
func (rr *RangeReader) readFromExistingReader(ctx context.Context, req *gcsx.GCSReaderRequest) (int, error) {
rr.skipBytes(req.Offset)
rr.invalidateReaderIfMisalignedOrTooSmall(req.Offset, req.Offset+int64(len(req.Buffer)))
Copy link
Collaborator

Choose a reason for hiding this comment

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

please compute and put the value in a variable so it can be reused. req.Offset+int64(len(req.Buffer))

Copy link
Collaborator

Choose a reason for hiding this comment

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

also what is the difference between endOffset in GCSReaderRequest vs this one?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

GCSReaderRequest has the computed endOffset which would be used while creating the reader. Here, we're reading from the existing reader, so I'm reading only what the user has requested.

@@ -407,129 +410,341 @@ func (t *gcsReaderTest) Test_ReadAt_PropagatesCancellation() {
}
}

func (t *gcsReaderTest) Test_ReadInfo_WithInvalidInput() {
t.object.Size = 10 * MiB
func (t *gcsReaderTest) Test_IsSeekNeeded() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

not reviewing the tests assuming you have written the same tests as random_reader

@abhishek10004
Copy link
Collaborator Author

/gemini review

Copy link

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@@ -52,6 +52,12 @@ const (
MultiRangeReaderType
)

type readInfo struct {
Copy link
Collaborator

@raj-prince raj-prince Aug 4, 2025

Choose a reason for hiding this comment

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

Should we rename it to more specific and clear? Something like - RequestState?

Also, I feel good to document the purpose of this struct, as not very straightforward to understand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
execute-integration-tests Run only integration tests execute-perf-test Execute performance test in PR remind-reviewers Auto remind reviewers in attention set for review post 24hrs of inactivity on PR.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants