Skip to content

Commit b628119

Browse files
modified read benchmark test and codebase related to len method
1 parent 7e48910 commit b628119

7 files changed

+109
-35
lines changed

test/benchmarks_test.go

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func BenchmarkV1BulkInsert100KDocs(b *testing.B) {
8787
}
8888

8989
func bulkRead(b *testing.B, docSize int) {
90-
db, col := setup(b)
90+
_, col := setup(b)
9191

9292
// -----------------------------
9393
// Prepare and insert documents
@@ -110,31 +110,24 @@ func bulkRead(b *testing.B, docSize int) {
110110
require.NoError(b, err)
111111

112112
// -----------------------------------------
113-
// Sub-benchmark 1: Read entire collection
113+
// Sub-benchmark 1: Read entire collection using ReadDocuments
114114
// -----------------------------------------
115115
b.Run("ReadAllDocsOnce", func(b *testing.B) {
116-
query := fmt.Sprintf("FOR d IN %s RETURN d", col.Name())
116+
// Prepare keys for reading
117+
keys := make([]string, docSize)
118+
for j := 0; j < docSize; j++ {
119+
keys[j] = fmt.Sprintf("doc_%d", j)
120+
}
117121

118122
b.ResetTimer()
119123
for i := 0; i < b.N; i++ {
120-
cursor, err := db.Query(ctx, query, nil)
124+
readDocs := make([]TestDoc, docSize)
125+
_, _, err := col.ReadDocuments(ctx, keys, readDocs)
121126
require.NoError(b, err)
122127

123-
count := 0
124-
for {
125-
var doc TestDoc
126-
_, err := cursor.ReadDocument(ctx, &doc)
127-
if driver.IsNoMoreDocuments(err) {
128-
break
129-
}
130-
require.NoError(b, err)
131-
count++
132-
}
133-
// require.Equal(b, docSize, count, "expected to read all documents")
134-
_ = cursor.Close()
135128
// sanity check
136-
if count != docSize {
137-
b.Fatalf("expected to read %d docs, got %d", docSize, count)
129+
if len(readDocs) != docSize {
130+
b.Fatalf("expected to read %d docs, got %d", docSize, len(readDocs))
138131
}
139132
}
140133
})

v2/arangodb/collection_documents_create_impl.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,26 @@ type collectionDocumentCreateResponseReader struct {
150150
}
151151
shared.ReadAllReader[CollectionDocumentCreateResponse, *collectionDocumentCreateResponseReader]
152152

153-
// Cache for len() method
153+
// Cache for len() method - allows Read() to work after Len() is called
154154
cachedResults []CollectionDocumentCreateResponse
155155
cachedErrors []error
156156
cached bool
157+
readIndex int // Track position in cache for Read() after Len()
157158
}
158159

159160
func (c *collectionDocumentCreateResponseReader) Read() (CollectionDocumentCreateResponse, error) {
161+
// If Len() was called, serve from cache
162+
if c.cached {
163+
if c.readIndex >= len(c.cachedResults) {
164+
return CollectionDocumentCreateResponse{}, shared.NoMoreDocumentsError{}
165+
}
166+
result := c.cachedResults[c.readIndex]
167+
err := c.cachedErrors[c.readIndex]
168+
c.readIndex++
169+
return result, err
170+
}
171+
172+
// Normal streaming read
160173
if !c.array.More() {
161174
return CollectionDocumentCreateResponse{}, shared.NoMoreDocumentsError{}
162175
}
@@ -191,11 +204,13 @@ func (c *collectionDocumentCreateResponseReader) Read() (CollectionDocumentCreat
191204
return meta, nil
192205
}
193206

194-
// Len returns the number of items in the response
207+
// Len returns the number of items in the response.
208+
// After calling Len(), you can still use Read() to iterate through items.
195209
func (c *collectionDocumentCreateResponseReader) Len() int {
196210
if !c.cached {
197211
c.cachedResults, c.cachedErrors = c.ReadAll()
198212
c.cached = true
213+
c.readIndex = 0 // Reset read position to allow Read() after Len()
199214
}
200215
return len(c.cachedResults)
201216
}

v2/arangodb/collection_documents_delete_impl.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,27 @@ type collectionDocumentDeleteResponseReader struct {
115115
array *connection.Array
116116
options *CollectionDocumentDeleteOptions
117117
shared.ReadAllIntoReader[CollectionDocumentDeleteResponse, *collectionDocumentDeleteResponseReader]
118-
// Cache for len() method
118+
// Cache for len() method - allows Read() to work after Len() is called
119119
cachedResults []CollectionDocumentDeleteResponse
120120
cachedErrors []error
121121
cached bool
122+
readIndex int // Track position in cache for Read() after Len()
122123
}
123124

124125
func (c *collectionDocumentDeleteResponseReader) Read(i interface{}) (CollectionDocumentDeleteResponse, error) {
126+
// If Len() was called, serve from cache
127+
// Note: When serving from cache, the 'i' parameter is not populated with document data
128+
if c.cached {
129+
if c.readIndex >= len(c.cachedResults) {
130+
return CollectionDocumentDeleteResponse{}, shared.NoMoreDocumentsError{}
131+
}
132+
result := c.cachedResults[c.readIndex]
133+
err := c.cachedErrors[c.readIndex]
134+
c.readIndex++
135+
return result, err
136+
}
137+
138+
// Normal streaming read
125139
if !c.array.More() {
126140
return CollectionDocumentDeleteResponse{}, shared.NoMoreDocumentsError{}
127141
}
@@ -172,12 +186,15 @@ func (c *collectionDocumentDeleteResponseReader) Read(i interface{}) (Collection
172186
return meta, nil
173187
}
174188

175-
// Len returns the number of items in the response
189+
// Len returns the number of items in the response.
190+
// After calling Len(), you can still use Read() to iterate through items.
191+
// Note: When Read() serves from cache, the document data parameter is not populated.
176192
func (c *collectionDocumentDeleteResponseReader) Len() int {
177193
if !c.cached {
178194
var dummySlice []interface{}
179195
c.cachedResults, c.cachedErrors = c.ReadAll(&dummySlice)
180196
c.cached = true
197+
c.readIndex = 0 // Reset read position to allow Read() after Len()
181198
}
182199
return len(c.cachedResults)
183200
}

v2/arangodb/collection_documents_read_impl.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,27 @@ type collectionDocumentReadResponseReader struct {
107107
array *connection.Array
108108
options *CollectionDocumentReadOptions
109109
shared.ReadAllIntoReader[CollectionDocumentReadResponse, *collectionDocumentReadResponseReader]
110-
// Cache for len() method
110+
// Cache for len() method - allows Read() to work after Len() is called
111111
cachedResults []CollectionDocumentReadResponse
112112
cachedErrors []error
113113
cached bool
114+
readIndex int // Track position in cache for Read() after Len()
114115
}
115116

116117
func (c *collectionDocumentReadResponseReader) Read(i interface{}) (CollectionDocumentReadResponse, error) {
118+
// If Len() was called, serve from cache
119+
// Note: When serving from cache, the 'i' parameter is not populated with document data
120+
if c.cached {
121+
if c.readIndex >= len(c.cachedResults) {
122+
return CollectionDocumentReadResponse{}, shared.NoMoreDocumentsError{}
123+
}
124+
result := c.cachedResults[c.readIndex]
125+
err := c.cachedErrors[c.readIndex]
126+
c.readIndex++
127+
return result, err
128+
}
129+
130+
// Normal streaming read
117131
if !c.array.More() {
118132
return CollectionDocumentReadResponse{}, shared.NoMoreDocumentsError{}
119133
}
@@ -148,12 +162,15 @@ func (c *collectionDocumentReadResponseReader) Read(i interface{}) (CollectionDo
148162
return meta, nil
149163
}
150164

151-
// Len returns the number of items in the response
165+
// Len returns the number of items in the response.
166+
// After calling Len(), you can still use Read() to iterate through items.
167+
// Note: When Read() serves from cache, the document data parameter is not populated.
152168
func (c *collectionDocumentReadResponseReader) Len() int {
153169
if !c.cached {
154170
var dummySlice []interface{}
155171
c.cachedResults, c.cachedErrors = c.ReadAll(&dummySlice)
156172
c.cached = true
173+
c.readIndex = 0 // Reset read position to allow Read() after Len()
157174
}
158175
return len(c.cachedResults)
159176
}

v2/arangodb/collection_documents_replace_impl.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,26 @@ type collectionDocumentReplaceResponseReader struct {
150150
}
151151
shared.ReadAllReader[CollectionDocumentReplaceResponse, *collectionDocumentReplaceResponseReader]
152152

153-
// Cache for len() method
153+
// Cache for len() method - allows Read() to work after Len() is called
154154
cachedResults []CollectionDocumentReplaceResponse
155155
cachedErrors []error
156156
cached bool
157+
readIndex int // Track position in cache for Read() after Len()
157158
}
158159

159160
func (c *collectionDocumentReplaceResponseReader) Read() (CollectionDocumentReplaceResponse, error) {
161+
// If Len() was called, serve from cache
162+
if c.cached {
163+
if c.readIndex >= len(c.cachedResults) {
164+
return CollectionDocumentReplaceResponse{}, shared.NoMoreDocumentsError{}
165+
}
166+
result := c.cachedResults[c.readIndex]
167+
err := c.cachedErrors[c.readIndex]
168+
c.readIndex++
169+
return result, err
170+
}
171+
172+
// Normal streaming read
160173
if !c.array.More() {
161174
return CollectionDocumentReplaceResponse{}, shared.NoMoreDocumentsError{}
162175
}
@@ -198,11 +211,13 @@ func (c *collectionDocumentReplaceResponseReader) Read() (CollectionDocumentRepl
198211
return meta, nil
199212
}
200213

201-
// Len returns the number of items in the response
214+
// Len returns the number of items in the response.
215+
// After calling Len(), you can still use Read() to iterate through items.
202216
func (c *collectionDocumentReplaceResponseReader) Len() int {
203217
if !c.cached {
204218
c.cachedResults, c.cachedErrors = c.ReadAll()
205219
c.cached = true
220+
c.readIndex = 0 // Reset read position to allow Read() after Len()
206221
}
207222
return len(c.cachedResults)
208223
}

v2/arangodb/collection_documents_update_impl.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,26 @@ type collectionDocumentUpdateResponseReader struct {
150150
}
151151
shared.ReadAllReader[CollectionDocumentUpdateResponse, *collectionDocumentUpdateResponseReader]
152152

153-
// Cache for len() method
153+
// Cache for len() method - allows Read() to work after Len() is called
154154
cachedResults []CollectionDocumentUpdateResponse
155155
cachedErrors []error
156156
cached bool
157+
readIndex int // Track position in cache for Read() after Len()
157158
}
158159

159160
func (c *collectionDocumentUpdateResponseReader) Read() (CollectionDocumentUpdateResponse, error) {
161+
// If Len() was called, serve from cache
162+
if c.cached {
163+
if c.readIndex >= len(c.cachedResults) {
164+
return CollectionDocumentUpdateResponse{}, shared.NoMoreDocumentsError{}
165+
}
166+
result := c.cachedResults[c.readIndex]
167+
err := c.cachedErrors[c.readIndex]
168+
c.readIndex++
169+
return result, err
170+
}
171+
172+
// Normal streaming read
160173
if !c.array.More() {
161174
return CollectionDocumentUpdateResponse{}, shared.NoMoreDocumentsError{}
162175
}
@@ -198,11 +211,13 @@ func (c *collectionDocumentUpdateResponseReader) Read() (CollectionDocumentUpdat
198211
return meta, nil
199212
}
200213

201-
// Len returns the number of items in the response
214+
// Len returns the number of items in the response.
215+
// After calling Len(), you can still use Read() to iterate through items.
202216
func (c *collectionDocumentUpdateResponseReader) Len() int {
203217
if !c.cached {
204218
c.cachedResults, c.cachedErrors = c.ReadAll()
205219
c.cached = true
220+
c.readIndex = 0 // Reset read position to allow Read() after Len()
206221
}
207222
return len(c.cachedResults)
208223
}

v2/tests/benchmarks_test.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func BenchmarkV2BulkInsert100KDocs(b *testing.B) {
209209
}
210210

211211
func bulkRead(b *testing.B, docSize int) {
212-
db, col := setup(b)
212+
_, col := setup(b)
213213

214214
// -----------------------------
215215
// Prepare and insert documents
@@ -237,28 +237,30 @@ func bulkRead(b *testing.B, docSize int) {
237237
require.NoError(b, err)
238238

239239
// -----------------------------------------
240-
// Sub-benchmark 1: Read entire collection
240+
// Sub-benchmark 1: Read entire collection using ReadDocuments
241241
// -----------------------------------------
242242
b.Run("ReadAllDocsOnce", func(b *testing.B) {
243-
query := fmt.Sprintf("FOR d IN %s RETURN d", col.Name())
243+
// Prepare keys for reading
244+
keys := make([]string, docSize)
245+
for j := 0; j < docSize; j++ {
246+
keys[j] = fmt.Sprintf("doc_%d", j)
247+
}
244248

245249
b.ResetTimer()
246250
for i := 0; i < b.N; i++ {
247-
cursor, err := db.Query(ctx, query, nil)
251+
resp, err := col.ReadDocuments(ctx, keys)
248252
require.NoError(b, err)
249253

250254
count := 0
251255
for {
252256
var doc TestDoc
253-
_, err := cursor.ReadDocument(ctx, &doc)
257+
_, err := resp.Read(&doc)
254258
if shared.IsNoMoreDocuments(err) {
255259
break
256260
}
257261
require.NoError(b, err)
258262
count++
259263
}
260-
// require.Equal(b, docSize, count, "expected to read all documents")
261-
_ = cursor.Close()
262264
// sanity check
263265
if count != docSize {
264266
b.Fatalf("expected to read %d docs, got %d", docSize, count)

0 commit comments

Comments
 (0)