the performance FGDB API & Arcobjects

5285
3
08-09-2011 10:56 PM
hexuezhou
New Contributor
Hi, I test insert 50,000 points to a FeatureClass use  FGDB API  & ArcObjects

But the result is ArcObjects fast than FGDB API :
ArcObjects used time:
Testing with 50,000 points.
Total time taken: 20.5 s

FGDB API used time:
Testing with 50,000 points.
Total time taken: 80.4 s


My IDE is Visual studio 2010 C++
FGDB API is Final 1.0 version
ArcObjects 10 version

Is not FGDB API faster than ArcObjects ?  

Below is FGDB API  code :
fgdbError hr;
  wstring   errorText;
  // Open the geodatabase.
  Geodatabase geodatabase;
  if ((hr = OpenGeodatabase(L"F:/testData/Editing.gdb", geodatabase)) != S_OK)
  {
    wcout << "An error occurred while opening the geodatabase." << endl;
    ErrorInfo::GetErrorDescription(hr, errorText);
    wcout << errorText << "(" << hr << ")." << endl;
    return ;
  }
  // Open the Cities table.
  Table table;
  if ((hr = geodatabase.OpenTable(L"\\Cities", table)) != S_OK)
  {
    wcout << "An error occurred while opening the table." << endl;
    ErrorInfo::GetErrorDescription(hr, errorText);
    wcout << errorText << "(" << hr << ")." << endl;
    return ;
  }

  Row cabazonRow;
  PointShapeBuffer cabazonGeom;
  Point* point;
   for (int i = 0; i < 50000; i++)
  {
   // Create a new feature for Cabazon.
   table.CreateRowObject(cabazonRow);

   // Set the row's attributes.
   cabazonRow.SetString(L"AREANAME", L"Cabazon");
   cabazonRow.SetString(L"CLASS", L"town");
   cabazonRow.SetInteger(L"POP2000", 2939); // 2007

   // Create and assign a point geometry.
   hr = cabazonGeom.Setup(shapePoint);
   hr = cabazonGeom.GetPoint(point);

   point->x = -116.78443;
   point->y =   33.919902;

   cabazonRow.SetGeometry(cabazonGeom);

   hr = table.Insert(cabazonRow);

  //// Store the row.
  //if ((hr = table.Insert(cabazonRow)) != S_OK)
  //{
  //  wcout << "An error occurred while inserting a row." << endl;
  //  ErrorInfo::GetErrorDescription(hr, errorText);
  //  wcout << errorText << "(" << hr << ")." << endl;
  //  return ;
  //}
  //else
  //{
  //  wcout << "Inserted two strings, one integer and a point." << endl;
  //}

  }
0 Kudos
3 Replies
LanceShipman
Esri Regular Contributor
You need to add   LoadOnlyMode and SetWriteLock/FreeWriteLock to your code. LoadOnlyMode shuts down index generation and SetWriteLock set a write lock. In ArcObjects a write lock is set when a insert cursor is opened and released when the cursor goes out of scope. Since we do not have a cursor we have to create a write lock on each insert. This slows things down. SetWriteLock opens a write lock until FreeWriteLock is called. When SetWriteLock is called the insert does not create a write lock as it knows that it has already been created. This improves insert (update and modify) performance greatly. I've modified your code.


fgdbError hr;
  wstring   errorText;
  // Open the geodatabase.
  Geodatabase geodatabase;
  if ((hr = OpenGeodatabase(L"F:/testData/Editing.gdb", geodatabase)) != S_OK)
  {
    wcout << "An error occurred while opening the geodatabase." << endl;
    ErrorInfo::GetErrorDescription(hr, errorText);
    wcout << errorText << "(" << hr << ")." << endl;
    return ;
  }
  // Open the Cities table.
  Table table;
  if ((hr = geodatabase.OpenTable(L"\\Cities", table)) != S_OK)
  {
    wcout << "An error occurred while opening the table." << endl;
    ErrorInfo::GetErrorDescription(hr, errorText);
    wcout << errorText << "(" << hr << ")." << endl;
    return ;
  }

  // Begin load only mode. This shuts off the update of all indexes.
  table.LoadOnlyMode(true);
  table.SetWriteLock();

  Row cabazonRow;
  PointShapeBuffer cabazonGeom;
  Point* point;
   for (int i = 0; i < 50000; i++)
  {
   // Create a new feature for Cabazon.
   table.CreateRowObject(cabazonRow);

   // Set the row's attributes.
   cabazonRow.SetString(L"AREANAME", L"Cabazon");
   cabazonRow.SetString(L"CLASS", L"town");
   cabazonRow.SetInteger(L"POP2000", 2939); // 2007

   // Create and assign a point geometry.
   hr = cabazonGeom.Setup(shapePoint);
   hr = cabazonGeom.GetPoint(point);

   point->x = -116.78443;
   point->y =   33.919902;

   cabazonRow.SetGeometry(cabazonGeom);

   hr = table.Insert(cabazonRow);

  //// Store the row.
  //if ((hr = table.Insert(cabazonRow)) != S_OK)
  //{
  //  wcout << "An error occurred while inserting a row." << endl;
  //  ErrorInfo::GetErrorDescription(hr, errorText);
  //  wcout << errorText << "(" << hr << ")." << endl;
  //  return ;
  //}
  //else
  //{
  //  wcout << "Inserted two strings, one integer and a point." << endl;
  //}

  }

  // End load only mode. This updates of all indexes.
  table.LoadOnlyMode(false);
  table.FreeWriteLock();
0 Kudos
hexuezhou
New Contributor
Hi, I used code that you supply to me

The File Geodatabase API use 18 seconds to create points(50000) , faster 2 seconds than Arcobjects

Thanks !
0 Kudos
JacobMaggard
Occasional Contributor II
I have similar issues with writing to FGDB.

I am using FME to process and load various FCs to an ESRI FGDB.

One example:

I have found that if I run a 55-65k record FGDB FC truncate job "cleanly" -- meaning without looking at the FGDB in ArcCatalog or touching the FC at all that morning before running the .FMW, it takes about 3 minutes to run my entire processing job.

Yet, if I simply start my day by looking at the FC in ArcCatalog, or some other user looks at the FC in ArcMap before (or during) the time I kick off my .FMW, it increases the job time from 3 minutes to about 25-35 minutes!

I won't even get into the 36 million record .FMW that took 34 hours to run (it has taken 6-8 hours in the past when truncating SDE FCs).

I am wondering if this is an FGDB bug, relates to opportunistic locking on the NAS, or something else entirely.

Any help?
0 Kudos