huge memory overhead with TSeriesMarks

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
FMenges
Newbie
Newbie
Posts: 6
Joined: Thu Dec 12, 2019 12:00 am
Contact:

huge memory overhead with TSeriesMarks

Post by FMenges » Fri Jan 10, 2020 2:25 pm

Hi there,

within my scientific software for optical spectra, I use TFastLineSeries to display the spectrum traces in a Teechart. One option is to create "peak labels", which are realised as TSeriesMarks with Callouts (see attached "peaklabel_sample.png"). Sometimes, spectra are huge with 50,000 or even 100,000 datapoints each. They still can be quickly displayed, and even dozens of them. So far no problem. When adding the "peak labels" at a few positions (the local maxima of the series), I set Series.Marks.Visible:=true and to hide all marks except those used as "peak labels", I set Series.Marks.Item[i].Text.Text:='' for all other data points. On doing this step for a spectrum with 65000 data pints, the memory increases by about 50-60MB, which is way too much in my opinion. This easily leads then to a OutOfMemory error for the application, if done for a set of 30 spectra or so.
On doing the same with leaving out the Series.Marks.Item[i].Text.Text:='' step, the spectra display is totally cluttered with all the marks of course, but memory increase is only a tiny fraction of it (less than 1MB for each spectrum). Could you help me to improve this performance? I've attached a small demo project showing the behaviour. You will see the difference on commenting out line 112. I also tried using setting Marks.Items[i].Visible for each datapoint instead, but this gives the same waste of memory.
Thanks a lot in advance!
Friedrich

P.S.: my system: Win7 Pro SP1, Delphi XE5, Teechart Pro VCL 2019.28
Attachments
peaklabel_sample.png
peaklabel_sample.png (29.26 KiB) Viewed 12759 times
marks.zip
demo project for TSeriesMarks memory problem
(3.79 KiB) Downloaded 741 times

Yeray
Site Admin
Site Admin
Posts: 9514
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: huge memory overhead with TSeriesMarks

Post by Yeray » Fri Jan 17, 2020 3:07 pm

Hello,

Sorry for the delay here.

The problem is that, by setting Item[i].Text.Text you are creating 65.000 TMarksItem objects per series which take memory.
Since you are actually hiding the majority of them, it could make sense to use a custom structure which only creates the MarkItems you need. Ie:
marks.zip
(3.88 KiB) Downloaded 742 times
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

FMenges
Newbie
Newbie
Posts: 6
Joined: Thu Dec 12, 2019 12:00 am
Contact:

Re: huge memory overhead with TSeriesMarks

Post by FMenges » Sun Jan 19, 2020 11:39 pm

So when not setting Text.Text:='' it actually plots all those marks without creating the respective TMarksItem objects? All while setting Text.text as empty text will not show them but greatly increase memory use Oh well, hard to understand. I spent quite some time trying to find other ways of showing only a few selected Marks, but not successful :(

Now I implemented your suggestion and it does great in terms of memory use (only a few kB) and it is also faster. BUT: my application let's the user interact with the "peak labels", users can move, delete, add and edit marks.text within the plot. For this I make use of the DragMarksTool, have to access Marks.Positions and query Marks.Clicked(X,Y). Also, to give them the necessary look, I also need to access the properties Automatic, Callout, Clip, SoftClip and Arrow which are all not available with the current proposal. Finally, I need to implement my own consistent management of the new classes, when adding/ removing series or adding/ removing displayed marks.

All of it not very pleasant, as I previously spent a lot of time to have an optimized user experience and frankly, I feel a bit lost between all those TMarksItem, TMarksItems, TSeriesMarks, and whatever...

Perhaps there is a more simple way of just showing a few marks without inflating memory? Can't imagine I am the first and only with that request...

So, if there is more advise, I would much appreciate.

All the Best,
Friedrich

Yeray
Site Admin
Site Admin
Posts: 9514
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: huge memory overhead with TSeriesMarks

Post by Yeray » Mon Jan 20, 2020 11:33 am

Hello Friedrich,

When you want the same format in all the marks in a series and you are fine with the automatic positioning, TeeChart doesn't save any list of marks or positions, and you can still avoid drawing those you don't want using OnGetMarkText event.
However, if you want to set different formats, or you want to set custom positions, this information needs to be stored somewhere. And there's where we populate the list of "custom" marks (TMarksItems) and/or a list of custom positions (TSeriesMarksPositions).
Actually, the list or Marks is populated just by accessing an item in the list:

Code: Select all

function TMarksItems.Get(Index:Integer):TMarksItem;
begin
  while Index>(Count-1) do Add(nil);
  //...
This is normally fine, but in your case you have a considerable number points and only want to show labels for very few, which means many objects are unnecessarily being created.
That's why I suggested creating only those marks you want to show, and add a ValueIndex property to each mark, instead of reusing the index of points for the custom marks.

The list of positions is a similar case. If you want very few items to be customized compared to the number of points, you'll be creating many unused Positions. However, the TDragMarksTool only works with the integrated list of Positions so I'm afraid you should implement that feature manually.
Here an example to start with:
marks.zip
(4.48 KiB) Downloaded 739 times
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

FMenges
Newbie
Newbie
Posts: 6
Joined: Thu Dec 12, 2019 12:00 am
Contact:

Re: huge memory overhead with TSeriesMarks

Post by FMenges » Mon Jan 27, 2020 1:01 am

OK now, after spending quite some time with implementing the approach starting from your custom code I realized it would take way too much to get to a robust solution again. I then went back to my old code and only switched towards assigning the few shown mark's custom text in the OnGetMarkText event and suppressing all other marks by assigning an empty string. It turned out this gives minimal memory use, is fast enough and still is fully compatible with my current way of creating and editing "manual label". Only for large series and a considerable number of labels, it was noticeably time-consuming to iterate through the respective list of peak labels for each series data point, but I could improved this much by implementing a binary search. So, all set now...

Thanks again for your support! (I will soon come back with one more issue)

Post Reply