Hi Andrew,
I believe the gX objects (obfuscated name) are our internal TreeNode class instances that track the relationship of items within the tree. There is a dictionary that maps your "item" objects to our TreeNode class. TreeNode objects are created whenever an item is examined, even if data virtualization is active.
While we don't currently have a sample for data virtualization, it will still create the same number of TreeNode objects behind the scenes. It's just that it won't load the actual items until they are needed. But it still will be creating TreeNodes objects with ITreeItemVirtualPlaceholder objects.
If you have an enormous number of items like that, perhaps changing the children query mode would be better. As explained in this topic, by default when a node is going to be made visible, all of its child nodes are queried to see if there are any. This allows us to hide the expander box if there are no children. The downside of that is that there is one level deeper of children queries happening, which could be a performance bottleneck in enormous trees. You can change the TreeListBoxItemAdapter.GetChildrenQueryMode method result (or simply set the adapter's ChildrenQueryModeDefault) to TreeItemChildrenQueryMode.OnExpansion instead of OnDisplay. That will always show an expander box until a node is expanded. At that point, it will scan the children for display and will hide the expander box if there are no children. This prevents that extra level of children scanning until necessary for display, and thus creates fewer TreeNodes behind the scenes.