Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'm trying to optimize my code to make it faster. I have a loop that reads some string input and creates points with the help of IFeatureBuffer and IFeatureCursor.

If I create the buffer inside tho loop, it slows the code down.

For i = 0 To Counter
  pFBuffer = pFClass.CreateFeatureBuffer
  ...
  pFBuffer.Value(iField) = ...
  pFCursor.InsertFeature(pFBuffer)
Next

If I move pFBuffer = pFClass.CreateFeatureBuffer above the loop (i.e. create the buffer once only) it works significantly faster. However, I have to "clear" the buffer at the end of each iteration, as in some cases it stores values from previous iterations.

So the question is: how can I clear the buffer, so that I won't need to create it at each iteration? Are there any other drawbacks or things to consider?

share|improve this question
    
How are you handlong garbage collection? –  Hairy Jan 26 '12 at 10:21
add comment

3 Answers 3

up vote 3 down vote accepted

how can I clear the buffer, so that I won't need to create it at each iteration?

You could loop through each field of the featurebuffer and if IField.Editable is true set the value of the featurebuffer to IField.DefaultValue. Take special care if you have subtypes.

share|improve this answer
    
agreed! this is the best option so far –  Ragi Yaser Burhum Jan 26 '12 at 16:42
    
Thanks, Kirk. This works, although I can't see a significant performace improvement. –  jan_b Feb 3 '12 at 8:32
    
When you create your cursor, did you try passing true to IFeatureClass.Insert? Also, before releasing the cursor call IFeatureCursor.Flush. –  Kirk Kuykendall Feb 3 '12 at 14:19
    
Yes, I use true when creating the cursor and call IFeatureCursor.Flush at the end. It seems that recreating the buffer at each iteration is much faster then looping through fields in the buffer and setting editable fields to default values. It takes 9 sec to import 30k points if I place pFBuffer = pFClass.CreateFeatureBuffer inside the loop, and 24 sec to import the same file if I create the buffer once and set default values at the end of each iteration. –  jan_b Feb 6 '12 at 8:35
    
@jan_b Thanks for posting - this is good to know. How many fields were on your test dataset? –  Kirk Kuykendall Feb 6 '12 at 14:28
show 3 more comments

The main reason to use the feature/row buffer is so that the DBMS is able to use larger, more efficient transactions instead of one transaction per row, and it should definitely be initialized outside of the loop. Also be sure to call Flush on your cursor at the end. See the example in the SDK help for Creating features:

Public Shared Sub InsertFeaturesUsingCursor(ByVal featureClass As IFeatureClass, _
                                            ByVal geometryList As List(Of IGeometry))
Using comReleaser As ComReleaser = New ComReleaser()
' Create a feature buffer.
Dim featureBuffer As IFeatureBuffer = featureClass.CreateFeatureBuffer()
comReleaser.ManageLifetime(featureBuffer)

' Create an insert cursor.
Dim insertCursor As IFeatureCursor = featureClass.Insert(True)
comReleaser.ManageLifetime(insertCursor)

' All of the features to be created are classified as Primary Highways.
Dim typeFieldIndex As Integer = featureClass.FindField("TYPE")
featureBuffer.Value(typeFieldIndex) = "Primary Highway"
For Each geometry As IGeometry In geometryList
    ' Set the feature buffer's shape and insert it.
    featureBuffer.Shape = geometry
    insertCursor.InsertFeature(featureBuffer)
Next

' Flush the buffer to the geodatabase.
insertCursor.Flush()
End Using
End Sub
share|improve this answer
    
if you are inserting several features, you do not want to call flush after every insert, otherwise you loose optimizations for inserts to be done in batch. –  Ragi Yaser Burhum Jan 26 '12 at 16:41
    
Right, but you still want to flush the cursor at the end, correct? –  blah238 Jan 26 '12 at 18:16
    
Ideally, yes, you want to flush once you are done with all the inserts so you can catch insertion table violations at that specific point - nevertheless, the cursor destructor calls flush for you internally. With .NET non-deterministic garbage collection that could be at any point it kicks in. –  Ragi Yaser Burhum Jan 26 '12 at 21:36
    
I do flush the cursor at the end. But in case of large loops, is it recommended to flush the cursor e.g. every 10k iterations? –  jan_b Feb 3 '12 at 8:38
add comment

You dont' need to keep recreating the buffer.

You just create the buffer once and populate it with the attributes you need (and the geometry). After that, a call to insertCursor.InsertFeature(buffer) will make ArcObjects understand that this is a new feature that needs to be created.

You can even populate an attribute once and use that for all features.

The drawbacks of feature buffers is that they do not trigger class extension events (OnCreate, OnChange, OnDelete). So if you are not using class extensions, I don't see any drawbacks.

share|improve this answer
    
I believe they do not bypass any custom behavior. Rather, row/feature buffers revert to internally calling Store() in that case. –  Petr Krebs Jan 26 '12 at 14:30
    
True Petr. I'll edit the answer. –  George Jan 26 '12 at 15:10
    
That's true, but my concern was how to make sure, that after 'pFCursor.InsertFeature(pFBuffer)' the 'pFBuffer' will be cleared. The reason is that in the next iteration some input values may be invalid (I read them from text file) and will not be parsed into 'pFBuffer.Value(iField)'. Thus, if I don't clear the 'pFBuffer', some values may retain from the previous iteration. –  jan_b Feb 3 '12 at 8:46
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.