Fast collections

Db4o's solution for the best collection performance and lowest memory consumption is to implement them directly on top of BTrees without an intermediate "stored-object-db4o" layer (P1Object, P1Collection, P2LinkedList).

This task is still under development, but already it makes sense to be ready to switch to the new fast collections seamlessly.

Current recommendation for collection usage with db4o is:

Please, avoid the following realizations, which will make the switching more difficult:

Let's look at application design, which will allow you to upgrade your application to fast collections with the least effort.

In our example we will save a list of pilots as members of one team. To make it simple let's use the following factory class to get the proper list implementation:

CollectionFactory.cs
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02using System; 03using System.Collections; 04 05namespace Db4objects.Db4odoc.Lists 06{ 07 public class CollectionFactory 08 { 09 public static IList newList() 10 { 11 return new VerboseList(); 12 } 13 } 14}

CollectionFactory.vb
01' Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com 02 03Imports System 04Imports System.Collections 05 06Namespace Db4objects.Db4odoc.Lists 07 Public Class CollectionFactory 08 Public Shared Function NewList() As IList 09 Return New VerboseList() 10 End Function 11 End Class 12End Namespace

The concrete class returned by the CollectionFactory can be changed to any other collection implementation (fast collection) with the minimum coding effort.

We will use the following class as a team of pilots:

Team.cs
01/* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com */ 02using System; 03using System.Collections; 04 05namespace Db4objects.Db4odoc.Lists 06{ 07 public class Team 08 { 09 private IList _pilots; 10 private string _name; 11 12 public Team() 13 { 14 _pilots = CollectionFactory.newList(); 15 } 16 17 public string Name 18 { 19 get 20 { 21 return _name; 22 } 23 24 set 25 { 26 _name = value; 27 } 28 } 29 30 public void AddPilot(Pilot pilot) 31 { 32 _pilots.Add(pilot); 33 } 34 35 public Pilot GetPilot(int index) 36 { 37 return (Pilot)_pilots[index]; 38 } 39 40 public void RemovePilot(int index) 41 { 42 _pilots.Remove(index); 43 } 44 45 public void UpdatePilot(int index, Pilot newPilot) 46 { 47 _pilots[index] = newPilot; 48 } 49 } 50}

Team.vb
01' Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com 02Imports System.Collections 03 04Namespace Db4objects.Db4odoc.Lists 05 Public Class Team 06 Private _pilots As IList 07 Private _name As String 08 09 Public Sub New() 10 _pilots = CollectionFactory.NewList() 11 End Sub 12 13 Public Property Name() As String 14 Get 15 Return _name 16 End Get 17 Set(ByVal Value As String) 18 _name = Value 19 End Set 20 End Property 21 22 Public Sub AddPilot(ByVal pilot As Pilot) 23 _pilots.Add(pilot) 24 End Sub 25 26 Public Function GetPilot(ByVal index As Integer) As evaluations.Pilot 27 Return CType(_pilots(index), evaluations.Pilot) 28 End Function 29 30 Public Sub RemovePilot(ByVal index As Integer) 31 _pilots.Remove(index) 32 End Sub 33 34 Public Sub UpdatePilot(ByVal index As Integer, ByVal NewPilot As evaluations.Pilot) 35 _pilots(index) = NewPilot 36 End Sub 37 End Class 38End Namespace

Let's try to store our team:

CollectionExample.cs: SetTeam
01private static void SetTeam() 02 { 03 File.Delete(Db4oFileName); 04 IObjectContainer db = Db4oFactory.OpenFile(Db4oFileName); 05 try 06 { 07 Team ferrariTeam = new Team(); 08 ferrariTeam.Name = "Ferrari"; 09 10 Pilot pilot1 = new Pilot("Michael Schumacher", 100); 11 ferrariTeam.AddPilot(pilot1); 12 Pilot pilot2 = new Pilot("David Schumacher", 98); 13 ferrariTeam.AddPilot(pilot2); 14 15 db.Set(ferrariTeam); 16 IList protoList = CollectionFactory.newList(); 17 IObjectSet result = db.Get(protoList); 18 ListResult(result); 19 } 20 finally 21 { 22 db.Close(); 23 } 24 }

CollectionExample.vb: SetTeam
01Public Shared Sub SetTeam() 02 File.Delete(Db4oFileName) 03 Dim db As IObjectContainer = Db4oFactory.OpenFile(Db4oFileName) 04 Try 05 Dim ferrariTeam As Team = New Team() 06 ferrariTeam.Name = "Ferrari" 07 08 Dim pilot1 As Pilot = New Pilot("Michael Schumacher", 100) 09 ferrariTeam.AddPilot(pilot1) 10 Dim pilot2 As Pilot = New Pilot("David Schumacher", 98) 11 ferrariTeam.AddPilot(pilot2) 12 13 db.Set(ferrariTeam) 14 Dim protoList As IList = CollectionFactory.NewList() 15 Dim result As IObjectSet = db.Get(protoList) 16 ListResult(result) 17 Finally 18 db.Close() 19 End Try 20 End Sub

If we want to update one of the pilots, we will have to retrieve the whole collection:

CollectionExample.cs: UpdateTeam
01private static void UpdateTeam() 02 { 03 IObjectContainer db = Db4oFactory.OpenFile(Db4oFileName); 04 try 05 { 06 IQuery query =db.Query(); 07 query.Constrain(typeof(Team)); 08 query.Descend("_name").Constrain("Ferrari"); 09 IObjectSet result = query.Execute(); 10 if (result.HasNext()) 11 { 12 Team ferrariTeam = (Team)result.Next(); 13 14 Pilot pilot = new Pilot("David Schumacher", 100); 15 ferrariTeam.UpdatePilot(1,pilot); 16 17 db.Set(ferrariTeam); 18 } 19 IList protoList = CollectionFactory.newList(); 20 result = db.Get(protoList); 21 ListResult(result); 22 } 23 finally 24 { 25 db.Close(); 26 } 27 }

CollectionExample.vb: UpdateTeam
01Public Shared Sub UpdateTeam() 02 Dim db As IObjectContainer = Db4oFactory.OpenFile(Db4oFileName) 03 Try 04 Dim query As IQuery = db.Query() 05 query.Constrain(GetType(Team)) 06 query.Descend("_name").Constrain("Ferrari") 07 Dim result As IObjectSet = query.Execute() 08 If result.HasNext() Then 09 Dim ferrariTeam As Team = CType(result.Next(), Team) 10 11 Dim pilot As Evaluations.Pilot = New Evaluations.Pilot("David Schumacher", 100) 12 ferrariTeam.UpdatePilot(1, pilot) 13 14 db.Set(ferrariTeam) 15 End If 16 Dim protoList As IList = CollectionFactory.NewList() 17 result = db.Get(protoList) 18 ListResult(result) 19 Finally 20 db.Close() 21 End Try 22 End Sub

The idea of the new fast collection implementation is to allow select/update of collection elements without an intermediate "stored-object-db4o" layer. This will allow random activation and fast querying, thus providing a considerable performance improvement especially on big collections holding deep object graphs.