DateTick

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
PollerJava
Posts: 81
Joined: Wed Jul 25, 2007 10:40 am

DateTick

Post by PollerJava » Tue Jan 20, 2009 5:07 pm

Hello,

I have a problem with the java heap memory and the class DateTick, respectively.
First all TracePanelTimeSeries series are cleared (first code) and than new data is set into the series (second code).

My problem now is that if I do this for example the 3. or 4. time, the profiler show me, that a lot of DateTick- objects are created and I than get a java heap space- OutOfMemoryException.
I do not use the DateTick- class in my code.

What can I do, Is it not recommended to clear series and set data again into this series ?

Thanks a lot for your help,
All the best,


Code: Select all

@Override public void clearAllSeries() {
        chart.removeChangeListener(trendZoomListener);
        setLegendVisible(false);
        for (Iterator<TracePanelTimeSeries> iterator = seriesList.iterator(); iterator.hasNext();) {
           TracePanelTimeSeries seriesInList = iterator.next();
           seriesInList.clear();
           }
        chart.addChangeListener(trendZoomListener);
        }    

Code: Select all

private void createDatasetWithExistingSerie(final TracePanelTimeSeries series, final String name, final RegularTimePeriod start, final List<DBWertReadBean> data, final int lineCnt, final TracePanelXYItemRenderer renderer, final String unit, final int lineIndex) {
         for(DBWertReadBean element : data) {
            int millis = element.getZeitstempel().getNanos()/(int)Math.pow(10, 6);
            Millisecond ms = new Millisecond(millis, new Second(element.getZeitstempel()));
            series.addOrUpdate(ms, element.getWert());            
            ms = null;
            }
        }

PollerJava
Posts: 81
Joined: Wed Jul 25, 2007 10:40 am

Post by PollerJava » Wed Jan 21, 2009 7:38 am

Has anyone an idea how I can solve this problem, I have no idea what I can do,
Thanks a lot,

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Wed Jan 21, 2009 9:08 am

My guess is that you've called setTickUnit() for the DateAxis somewhere in your code, using a tick size that is very small (bearing in mind that the DateAxis measures in milliseconds). That would cause the DateAxis (if the range is longish - say months or years) to create a very large number of ticks, as requested.

But I'm only guessing.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

PollerJava
Posts: 81
Joined: Wed Jul 25, 2007 10:40 am

Post by PollerJava » Wed Jan 21, 2009 4:42 pm

david.gilbert wrote:My guess is that you've called setTickUnit() for the DateAxis somewhere in your code, using a tick size that is very small (bearing in mind that the DateAxis measures in milliseconds). That would cause the DateAxis (if the range is longish - say months or years) to create a very large number of ticks, as requested.

But I'm only guessing.

Hello david.gilbert,

I do not invoke or use the methode setTickUnit() but I guess that the Millisecond- Objects aren't cleared when I invoke seriesInList.clear();
What do you think, is it necessary to iterate through the series and set the Millisecond- objects to null?

Thanks a lot for your help,
All the best,
Poller

Code: Select all

Millisecond ms = new Millisecond(millis, new Second(element.getZeitstempel()));
            series.addOrUpdate(ms, element.getWert());

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Wed Jan 21, 2009 5:07 pm

I don't know. TracePanelTimeSeries is not a JFreeChart class, so I don't know what it does.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

PollerJava
Posts: 81
Joined: Wed Jul 25, 2007 10:40 am

Post by PollerJava » Thu Jan 22, 2009 7:44 am

david.gilbert wrote:I don't know. TracePanelTimeSeries is not a JFreeChart class, so I don't know what it does.
Morning,

thats my TracePanelTimeSeries, but I don't think that class is the problem,

Code: Select all

public final class TracePanelTimeSeries extends TimeSeries {

    private String name;
    private int lineCnt;
    private XYItemRenderer renderer;
    private String unit;
    private int lineIndex;

    public TracePanelTimeSeries(final String name, final Class c, final int lineCnt, final XYItemRenderer renderer, final String unit, final int lineIndex) {
        super(name, c);
        this.setName(name);
        this.lineCnt = lineCnt;
        this.renderer = renderer;
        this.unit = unit;
        this.lineIndex = lineIndex;
        }

    public String getName() {
        return name;
        }

    public void setName(final String name) {
        this.name = name;
        }

    public int getLineCnt() {
        return lineCnt;
        }

    public void setLineCnt(final int lineCnt) {
        this.lineCnt = lineCnt;
        }

    public XYItemRenderer getRenderer() {
        return renderer;
        }

    public void setRenderer(final XYItemRenderer renderer) {
        this.renderer = renderer;
        }

    public void setUnit(String unit) {
        this.unit = unit;
        }

    public String getUnit() {
        return unit;
        }
    public void setLineIndex(int lineIndex) {
        this.lineIndex = lineIndex;
        }

    public int getLineIndex() {
        return lineIndex;
        }

    @Override
    public String toString() {
        String s = "Klasse TraceTimeSeries -> Name: " + name + ", LineCnt: " + lineCnt + ", Unit: " + unit + ", LineIndex: " + lineIndex;
        return s;
        }
}

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Post by paradoxoff » Thu Jan 22, 2009 8:54 am

PollerJava wrote: I do not invoke or use the methode setTickUnit() but I guess that the Millisecond- Objects aren't cleared when I invoke seriesInList.clear();
What do you think, is it necessary to iterate through the series and set the Millisecond- objects to null?
A TimeSeries manages an ArrayList of TimeSeriesDataItems. TimeSeries.clear() simply clears this underlying ArrayList, regardless of whether you are using Milliseconds or Years. After clearing, everything should be gone. You can check that with TimeSeries.getItemCount().
Using a DateTick with a small unit on an axis with a large range would have been my first guess as well. If that is not the case, maybe something else is wrong with the time scales you are dealing with.
PollerJava wrote:

Code: Select all

private void createDatasetWithExistingSerie(final TracePanelTimeSeries series, final String name, final RegularTimePeriod start, final List<DBWertReadBean> data, final int lineCnt, final TracePanelXYItemRenderer renderer, final String unit, final int lineIndex) {
         for(DBWertReadBean element : data) {
            int millis = element.getZeitstempel().getNanos()/(int)Math.pow(10, 6);
            Millisecond ms = new Millisecond(millis, new Second(element.getZeitstempel()));
            series.addOrUpdate(ms, element.getWert());           
            ms = null;
            }
        }
Is it ensured that element.getZeitstempel() indeed returns seconds and that element.getZeitstempel().getNanos() indeed returns a value corresponding to only the nanosecond part? If something is wrong with that, maybe you are plotting values from now to year 2010000?


I agree that your TracePanelTimeSeries does not look suspicious. Can you provide an example of a use case?
BTW, what version of JFreeChart are you using?

PollerJava
Posts: 81
Joined: Wed Jul 25, 2007 10:40 am

Post by PollerJava » Thu Jan 22, 2009 1:47 pm

It's really crasy for me, I expand the x-axis in one direction and if I do this three- or four times than the DateTick need so much memory than the application goes down,

I don't know, what I should do,
The problem is in the code at the bottom , but I really don't know what to do.


Code: Select all

private void createDatasetWithExistingSerie(final TracePanelTimeSeries series, final String name, final RegularTimePeriod start, final List<DBWertReadBean> lineData, final int lineCnt, final TracePanelXYItemRenderer renderer, final String unit, final int lineIndex) {        
        xAxis = (DateAxis) ((XYPlot)chartPanel.getChart().getPlot()).getDomainAxis();
        xAxis.setAutoRange(true);
        int x = 0;
        for(DBWertReadBean element : lineData) {
            int millis = element.getZeitstempel().getNanos()/(int)Math.pow(10, 6);
            Millisecond ms = new Millisecond(millis, new Second(element.getZeitstempel()));                     
            series.add(ms, element.getWert());
            ms = null;
            }        
        System.out.println("Das ist das TickUnit: " + xAxis.getTickUnit());
        }

The output is:

Code: Select all

Anzahl der Werte: Pegel1-> 1617
Das ist das TickUnit: DateTickUnit[MILLISECOND, 1]
Anzahl der Werte: Pegel2-> 1617
Das ist das TickUnit: DateTickUnit[DAY, 7]
Anzahl der Werte: Pegel2-> 1604
Anzahl der Werte: Pegel1-> 1606
Das ist das TickUnit: DateTickUnit[HOUR, 1]
Das ist das TickUnit: DateTickUnit[MONTH, 1]
Anzahl der Werte: Pegel1-> 1604
Das ist das TickUnit: DateTickUnit[MONTH, 4]
Anzahl der Werte: Pegel2-> 1603
Das ist das TickUnit: DateTickUnit[MONTH, 4]
Anzahl der Werte: Pegel2-> 1604
Das ist das TickUnit: DateTickUnit[MILLISECOND, 1]  // here the application shut down!!!!!!!! if MILLISECOND is used
Anzahl der Werte: Pegel1-> 1601
Das ist das TickUnit: DateTickUnit[MILLISECOND, 1]


mkivinie
Posts: 51
Joined: Wed Jul 06, 2005 8:35 am

Post by mkivinie » Thu Jan 22, 2009 3:42 pm

Is the series already mapped to an existing plot?

Because if it is, then you are possibly triggering a redraw after every series.add() -call.
And as you have setAutoRange(true) it also triggers additional updates to axes. And maybe even more...
And as your constantly triggered updates are causing the re-creation of the DomainAxis range and also the TickUnits --> could it be that the heap is being populated with more trash objects than what the GarbageCollection can clean away?

What you could try is to use

Code: Select all

series.add(ms, element.getWert(), false); // false for not notifying 
and finally calling (after all items are added)

Code: Select all

series.fireSeriesChanged()
I hope it helps. Then again it might not if you have taken care of notifications outside of the method you posted...

PollerJava
Posts: 81
Joined: Wed Jul 25, 2007 10:40 am

Post by PollerJava » Thu Jan 22, 2009 3:46 pm

So, I have found the error,
if I set the unit, than all is ok, So I think that the calculation, whether MILLISECOND, SECOND, MINUTE, HOUR, DAY, MONTH, ... should be used, is wrong,
So my question is, in with class or better in with java- file the desicion is made?

Thanks a lot for your help,
All the best,


Code: Select all

private void createDatasetWithExistingSerie(final TracePanelTimeSeries series, final String name, final RegularTimePeriod start, final List<DBWertReadBean> lineData, final int lineCnt, final TracePanelXYItemRenderer renderer, final String unit, final int lineIndex) {        
        xAxis = (DateAxis) ((XYPlot)chartPanel.getChart().getPlot()).getDomainAxis();
        System.out.println("Das ist das TickUnit vorher: " + xAxis.getTickUnit() + ", " + xAxis.getMinorTickCount() + ", " + xAxis.getRange());
        xAxis.setTickUnit(new DateTickUnit(DateTickUnit.DAY, 1), true, true);   // here I set the Unit but why jFreechart makes the wrong desicion
        int x = 0;
        for(DBWertReadBean element : lineData) {
            int millis = element.getZeitstempel().getNanos()/(int)Math.pow(10, 6);
            Millisecond ms = new Millisecond(millis, new Second(element.getZeitstempel()));                     
            series.add(ms, element.getWert());
            ms = null;
            }        
        }

PollerJava
Posts: 81
Joined: Wed Jul 25, 2007 10:40 am

Post by PollerJava » Thu Jan 22, 2009 3:52 pm

@mkivinie
It works, thanks a lot!!!!

All the best,
Poller

Locked