Trees for data acquisition?

Hi Rooters,
We are looking at ways to create chained data files in (hard) real time on our linux/VME acquisition processor. We will have on the order of 20 integers arriving at 144000/second. Am I right in thinking that full trees are not the fastest structures to store? What other structures should we consider?
Cheers,
Steve Alam

I assume that you mean 144000 events per second, each one having 20 integers, ie a total of about 144000204 = 11.5 MBytes/s
I do not see any problem in doing this with a standard Tree.

Rene

My only concern is the overhead in splitting and “machine independent” formatting since there are other things to do in our acquisition loop. I’ll start with the standard tree.
Thanks,
Steve

Rene,
Filling a branch built as:
MyTree->Branch(“BR1”,&iEv,“iEv[144000][20]/F”,64000);
and writing to a file (previously) constructed as
MyFile = new TFile(“myfile.root”,“recreate”,“myfile.root”,0);
burns considerably more time than a simple
_write(iHandle, iEv, sizeof(iEv));.
The iEv buffer is filled by DMA. We would like to put our raw data into root format as soon as possible. Still, I need to get as close to the _write speed as possible. Filling the branch and closing the file also adds time.
TClonesArray constructors (and the branch constructors that permit setting a split level of zero) seem also to require objects that I would prefer not to take time to construct. All suggestions are welcome!
Cheers,
Steve

Are you opening a file, a Tree and closing it at each event?
If not, opening/closing a file should be completely marginal.
If you open the file with no compression, filling the Tree should be nearly as fast as your direct write operation.
Do you have any numbers?

Rene

Rene,
Out of curiosity I wrote the same file 10 times before closing. There is apparently some disk caching issue. On average writing 128MB is much faster than writing 12MB and better (3.109S vs 4.375S) than the simple write!
Unfortunately I need to update at the 1 second rate to keep from missing data. Perhaps I should write even more often?
Cheers,
Steve

see TTree::AutoSave

Rene

Hi Rooters,
I have tried AutoSave and it appears to make no difference. I hope you can show me what to do differently.

Here is the (edited) setup for my root 12.0 file and tree:

CytFile = new TFile(sData_Path_Name, "RECREATE", "Raw Cyt Data", 0); CytTree = new TTree(); CytTree->SetName("RawTree"); CytTree->SetAutoSave(EVENT_SIZE * 1000);
Where EVENT_SIZE is 84 bytes

I call a method that does the following:

sprintf(cBranchDef,"BinData[%d][%d]/F", ulEventCount, EVENT_SIZE); sprintf(cBranchID,"BR%d",iBID++); CytTree->Branch(cBranchID, pulBuf, cBranchDef, iTreeBufferSize); CytTree->GetBranch(cBranchID)->SetFile(CytFile); CytTree->GetBranch(cBranchID)->Fill();
Where ulEventCount is 144000

And I use the following loop:

for (ii = 0; ii <REPS ...[Some code missing] ...>Start(); CytDat->WriteRaw((unsigned long *)&ulEv, MAXEVENTS); StopWatch1->Stop(); fprintf(fRep,"%3.3f , S ,%6.6f , CPU\n", StopWatch1->RealTime() StopWatch1->CpuTime()); }
With REPS at 50 and a close after all filling is complete.

I have tried buffer sizes from 1K to 256K and AutoSave times from 1000 to 1000000. In 50 repetitions I see a mean time of 300 ms but there are always one or two writes that come in at around one second. This is on Windows - times in linux are actually better on average but the long delays are actually worse. Removing the AutoSave and/or fprintf make no difference. Aside from writing small buffers more frequently is there anything you can suggest?

Cheers,
Steve

I do not understand what you do in this piece of code:

for (ii = 0; ii <REPS>Start(); CytDat->WriteRaw((unsigned long *)&ulEv, MAXEVENTS); StopWatch1->Stop(); fprintf(fRep,"%3.3f , S ,%6.6f , CPU\n", StopWatch1->RealTime() StopWatch1->CpuTime()); }
What is CytDat?
Where to you write your Tree?

Also note that you can replace

CytTree->Branch(cBranchID, pulBuf, cBranchDef, iTreeBufferSize); CytTree->GetBranch(cBranchID)->SetFile(CytFile); CytTree->GetBranch(cBranchID)->Fill(); by

TBranch *BranchID = CytTree->Branch(cBranchID, pulBuf, cBranchDef, iTreeBufferSize); BranchID)->Fill();

Rene

Rene,
What is CytDat?
CytDat is the class in which I buld and fill new branches. Thank you for the efficient way to build the branch.

Where to you write your Tree?
I only want to write to the the file as buffers fill (or every n bytes if autosave would work). Do I need to write the tree before I close the file? How long will this take?

Regards,
Steve

I do not understand your description.
Could you send the shortest possible RUNNING script reproducing/explaing your problem?

Rene

Rene,
I am working on several projects at once and it may take me a couple of days to condense my application. I will get back to you as soon as I can.
Regards,
Steve

Take your time. I wuill be away in the coming days.

Rene

Rene,
It appears that we have solved our immediate problem with long delays in writing data - Running without X-Windows at level 3 seems to help. In the process of trying to pair down our loop I seem to have lost track of writing the tree. In a loop I am calling and timing the following lines
CytTree->Branch(cBranchID, pulBuf, cBranchDef, iTreeBufferSize);
CytTree->GetBranch(cBranchID)->SetFile(CytFile);
CytTree->GetBranch(cBranchID)->Fill();
I get an appropriately sized, but hard to read file. Must I write the tree each time?
Regards,
Steve