function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Justin RuckJustin Ruck 

VF Home tab - size and loading time

I created a VF Home tab that has a few charts at the top (with tooltips), and below is a section with the Chatter newsfeed on the left and the Activities object on the right (with only 2 filter options, "My Open Tasks" and "My Open Meetings", which doesn't contain tons of data).  The loading time is too long.  First load takes a couple minutes and after that, takes about 7 seconds.  But other than that, everything works excellently.  

The charts are pulling data from a few different objects - Users, Opportunities, and Accounts.  Would it be better to have the charts in a separate VF page and then just pull that VF page into this new VF Home tab?  Any help is appreciated.  

VF:
 
<apex:page controller="HomePageController" title="Metrie Home Page" readonly="true">
<script type="text/javascript">
function renderSalesBudgetChartTip(klass, item)
{
    console.log (klass);
    console.log (item);
    console.log (this);
    var yField = item.yField; // dataSales or dataBudget
    var name = item.storeItem.get('name'); // doors, mouldings, sheets, other
    var label;
    if (yField == 'dataSales')
        label = 'Sales';
    else if (yField == 'dataBudget')
        label = 'Budget';
    else
        label = '';
    
    var amount = item.storeItem.get(yField);
    this.height = 50; // Fixed height, how to force a recalc of the size?
    this.setTitle(name + ' ' + label + ': $' + amount.formatMoney(0));
}
function renderCollectionsChartTip(klass, item)
{
    //console.log (item);
    var yField = item.yField; // sales or budget
    var monthName = item.storeItem.get('month'); // Jan - Dec
    var label;
    if (yField == 'sales')
        label = 'Sales';
    else if (yField == 'budget')
        label = 'Budget'
    else if (yField == 'custsales')
        label = 'Customer Sales'
    else
        label = '';
    
    var amount = item.storeItem.get(yField);
    this.height = 40;
    this.setTitle(monthName + ' ' + label + ': $' + amount.formatMoney(0));
}
Number.prototype.formatMoney = function(c, d, t){
var n = this, 
    c = isNaN(c = Math.abs(c)) ? 2 : c, 
    d = d == undefined ? "." : d, 
    t = t == undefined ? "," : t, 
    s = n < 0 ? "-" : "", 
    i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", 
    j = (j = i.length) > 3 ? j % 3 : 0;
   return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
 };
</script>
<style>
.chartTitle { font-size:16px;font-weight:bold }
.chartSubTitleText { text-align:right; width:60%; font-size:12px;font-weight:bold;}
.chartSubTitleValue { text-align:right; font-size:12px;font-weight:bold;}
.chartColumn { text-align: center;}
</style>
    <apex:sectionHeader title="Metrie Home Page" subtitle="">
        <apex:outputText rendered="{!HasSalesCharts}" value="Charts for {0}" style="font-size:22px;font-weight:bold;">
            <apex:param value="{!chartScope}"/>
        </apex:outputText>
        
        <apex:panelGrid rendered="{!HasSalesCharts}" columns="3" columnClasses="chartColumn">
            <apex:panelGroup >
                <apex:outputText value="MTD" styleClass="chartTitle"/>
                <apex:panelGrid columns="2" width="85%" columnClasses="chartSubTitleText,chartSubTitleValue">
                <apex:outputText value="Sales:"/>
                <apex:outputText value="${0, number, ###,###,##0}">
                    <apex:param value="{!MTDTotalSales}"/>
                </apex:outputText>
                <apex:outputText value="Budget:"/>
                <apex:outputText value="${0, number, ###,###,##0}">
                    <apex:param value="{!MTDTotalBudget}"/>
                </apex:outputText>
                </apex:panelGrid>
    
                <apex:chart height="250" width="350" data="{!MTDChartData}">
                <apex:legend position="bottom" font="10px Helvetica"/>
                <apex:axis type="Numeric" position="left" fields="dataSales,dataBudget" minimum="0" title="Sales vs Budget"/>
                <apex:axis type="Category" position="bottom" fields="name" title="Product"/>
                <apex:barSeries orientation="vertical" axis="left" xField="name" yField="dataSales,dataBudget" title="Sales,Budget" colorSet="#FFCC00,#969696" colorsProgressWithinSeries="true">
                    <apex:chartTips rendererFn="renderSalesBudgetChartTip"/>
                </apex:barSeries>
                </apex:chart>
            </apex:panelGroup>
    
            <apex:panelGroup >
                <apex:outputText value="YTD" styleClass="chartTitle"/>
                <apex:panelGrid columns="2" width="85%" columnClasses="chartSubTitleText,chartSubTitleValue">
                <apex:outputText value="Sales:"/>
                <apex:outputText value="${0, number, ###,###,##0}">
                    <apex:param value="{!YTDTotalSales}"/>
                </apex:outputText>
                <apex:outputText value="Budget:"/>
                <apex:outputText value="${0, number, ###,###,##0}">
                    <apex:param value="{!YTDTotalBudget}"/>
                </apex:outputText>
                </apex:panelGrid>
     
                <apex:chart height="250" width="350" data="{!YTDChartData}">
                <apex:legend position="bottom" font="10px Helvetica"/>
                <apex:axis type="Numeric" position="left" fields="dataSales,dataBudget" minimum="0" title="Sales vs Budget"/>
                <apex:axis type="Category" position="bottom" fields="name" title="Product"/>
                <apex:barSeries orientation="vertical" axis="left" xField="name" yField="dataSales,dataBudget" title="Sales,Budget" colorSet="#FFCC00,#969696" colorsProgressWithinSeries="true">
                    <apex:chartTips rendererFn="renderSalesBudgetChartTip"/>
                </apex:barSeries>
                </apex:chart>
            </apex:panelGroup>
    
            <apex:panelGroup >
                <apex:outputText value="Collections YTD" styleClass="chartTitle" />
                <apex:panelGrid columns="2" width="85%" columnClasses="chartSubTitleText,chartSubTitleValue">
                
                <apex:outputText value="Sales:"/>
                <apex:outputText value="${0, number, ###,###,##0}">
                    <apex:param value="{!YTDCollectionCustSales}"/>
                </apex:outputText>    
                <apex:outputText value="Open Oppty:"/>
                <apex:outputText value="${0, number, ###,###,##0}">
                    <apex:param value="{!YTDCollectionSales}"/>
                </apex:outputText>
                <apex:outputText value="Budget:"/>
                <apex:outputText value="${0, number, ###,###,##0}">
                    <apex:param value="{!YTDCollectionBudget}"/>
                </apex:outputText>
                </apex:panelGrid>
     
                <apex:chart height="250" width="350" data="{!CollectionChart}">
                <apex:legend position="bottom" font="10px Helvetica"/>
                <apex:axis type="Numeric" position="left" fields="sales,custsales,budget" minimum="0" title="Collections $"/>
                <apex:axis type="Category" position="bottom" fields="month" title="Close Date"/>
                <apex:barSeries orientation="vertical" axis="left" xField="month" yField="sales" title="Open Oppty" colorSet="#FF9900">
                    <apex:chartTips rendererFn="renderCollectionsChartTip"/>
                </apex:barSeries>
                <apex:lineSeries axis="left" xField="month" yField="custsales" title="Sales" fill="true" markerType="cross" markerSize="4" fillColor="#FFFF99" markerFill="#FFCC00"/>
                <apex:lineSeries axis="left" xField="month" yField="budget" title="Budget" fill="true" markerType="circle" markerSize="4" fillcolor="#C0C0C0" markerFill="#C0C0C0"/>
                
                </apex:chart>

            </apex:panelGroup>
    
        </apex:panelGrid>
    </apex:sectionHeader>
    
    <apex:panelGrid columns="2" width="100%">
    <chatter:newsfeed id="newsFeed"/>
        
    <apex:enhancedList type="Activity" height="300" customizable="false" rowsPerPage="10"/>

</apex:panelGrid>
</apex:page>

Controller:
 
public class HomePageController
{
	public HomePageController()
	{
		//PromotionText = '<p align="center"><font face="Arial,Sans-Serif"><font size="4">Remember, Ontario has a special on Doors this month, 50% off certain SKUs</font></font></p><p><br></p><p><br></p><p><br></p><p>mimi and mark made presentation to senior leadershup team<br>call with traction on friday<br>we want their ideas not business $<br>meeting was eye opener<br>everybody believes in it but hwere is the value<br>insure by years end one consistent way that we were <br>goto reportign tool<br>inform branch visit weekly sales meetings<br>June 25th &amp; 26th vancouver sales directors &amp; above</p>';
		// What branch and report level for the current user
		this.currentUser = Database.query ('select Branch__c, BranchShort__c, RegionSGI__c, Country, ReportLevel__c, X2015_Collections_Budget__c from User where Id = \'' + UserInfo.getUserId() + '\' limit 1');
		
		if (currentUser.ReportLevel__c == 'Territory Manager')
		{
			ChartScope = 'My Accounts';
			CalculateMTDSales();
			CalculateYTDSales();
			CalculateCollectionSales();
		}
		else if (currentUser.ReportLevel__c == 'Market Manager')
		{
			ChartScope = this.currentUser.BranchShort__c;
			CalculateMTDSales();
			CalculateYTDSales();
			CalculateCollectionSales();
		}
		else if (currentUser.ReportLevel__c == 'Sales Director')
		{
			ChartScope = this.currentUser.RegionSGI__c;
			CalculateMTDSales();
			CalculateYTDSales();
			CalculateCollectionSales();
		}
		else if (currentUser.ReportLevel__c == 'VP of Sales')
		{
			ChartScope = this.currentUser.Country;
			CalculateMTDSales();
			CalculateYTDSales();
			CalculateCollectionSales();
		}
		else if (currentUser.ReportLevel__c == 'Corporate')
		{
			ChartScope = 'Metrie';
			CalculateMTDSales();
			CalculateYTDSales();
			CalculateCollectionSales();
		}
		
	}
	public String ChartScope { get; private set; }
	public Boolean HasSalesCharts { get { return MTDChartData == null ? false : true; } }
	public List<ChartData> MTDChartData { get; private set; }
	public Decimal MTDTotalSales { get; private set; }
	public Decimal MTDTotalBudget { get; private set; }
	public Decimal YTDTotalSales { get; private set; }
	public Decimal YTDTotalBudget { get; private set; }
	public List<ChartData> YTDChartData { get; private set; }
	public List<CollectionChartData> CollectionChart { get; private set; }
	public Decimal YTDCollectionSales { get; private set; }
	public Decimal YTDCollectionBudget { get; private set; }
    public Decimal YTDCollectionCustSales { get; private set; }
	
	private User currentUser { get; set; }
	private ChartData doorChartData;
	private ChartData mouldingChartData;
	private ChartData sheetChartData;
	private ChartData otherChartData;
	private Decimal totalSales;
	private Decimal totalBudget;
	
	private void CalculateMTDSales()
	{
		List<AggregateResult> shList = null;
		if (currentUser.ReportLevel__c == 'Territory Manager')
		{
			shList = [select sum(s.Sales__c), sum(s.Budget__c), ProductGroupCode__c
										from SalesHistory__c s 
										where s.Account__r.OwnerId = :UserInfo.getUserId() and
											s.CurrentPeriod__c = 'Yes'
										group by s.ProductGroupCode__c];
		}
		else if (currentUser.ReportLevel__c == 'Market Manager')
		{
			shList = [select sum(s.Sales__c), sum(s.Budget__c), ProductGroupCode__c
										from SalesHistory__c s 
										where s.Account__r.OwnerBranch__c = :this.currentUser.Branch__c and
											s.CurrentPeriod__c = 'Yes'
										group by s.ProductGroupCode__c];
		}
		else if (currentUser.ReportLevel__c == 'Sales Director')
		{
			shList = [select sum(s.Sales__c), sum(s.Budget__c), ProductGroupCode__c
										from SalesHistory__c s 
										where s.Account__r.Owner.RegionSGI__c = :this.currentUser.RegionSGI__c and
											s.CurrentPeriod__c = 'Yes'
										group by s.ProductGroupCode__c];
		}
		else if (currentUser.ReportLevel__c == 'VP of Sales')
		{
			shList = [select sum(s.Sales__c), sum(s.Budget__c), ProductGroupCode__c
										from SalesHistory__c s 
										where s.Account__r.Owner.Country = :this.currentUser.Country and
											s.CurrentPeriod__c = 'Yes'
										group by s.ProductGroupCode__c];
		}
		else if (currentUser.ReportLevel__c == 'Corporate')
		{
			shList = [select sum(s.Sales__c), sum(s.Budget__c), ProductGroupCode__c
										from SalesHistory__c s 
										where s.CurrentPeriod__c = 'Yes'
										group by s.ProductGroupCode__c];
		}
		else
			return;
		doorChartData = mouldingChartData = sheetChartData = otherChartData = null;
		TallyResults (shList);
		MTDTotalSales = totalSales;
		MTDTotalBudget = totalBudget;
		MTDChartData = new List<ChartData>();
		MTDChartData.add (doorChartData);
		MTDChartData.add (mouldingChartData);
		MTDChartData.add (sheetChartData);
		MTDChartData.add (otherChartData);
	}
	private void CalculateYTDSales()
	{
		List<AggregateResult> shList = null;
		if (currentUser.ReportLevel__c == 'Territory Manager')
		{
			shList = [select sum(s.Sales__c), sum(s.Budget__c), ProductGroupCode__c
										from SalesHistory__c s 
										where s.Account__r.OwnerId = :UserInfo.getUserId() and
											s.CurrentYear__c = 'Yes'
										group by s.ProductGroupCode__c];
		}
		else if (currentUser.ReportLevel__c == 'Market Manager')
		{
			shList = [select sum(s.Sales__c), sum(s.Budget__c), ProductGroupCode__c
										from SalesHistory__c s 
										where s.Account__r.OwnerBranch__c = :this.currentUser.Branch__c and
											s.CurrentYear__c = 'Yes'
										group by s.ProductGroupCode__c];
		}
		else if (currentUser.ReportLevel__c == 'Sales Director')
		{
			shList = [select sum(s.Sales__c), sum(s.Budget__c), ProductGroupCode__c
										from SalesHistory__c s 
										where s.Account__r.Owner.RegionSGI__c = :this.currentUser.RegionSGI__c and
											s.CurrentYear__c = 'Yes'
										group by s.ProductGroupCode__c];
		}
		else if (currentUser.ReportLevel__c == 'VP of Sales')
		{
			shList = [select sum(s.Sales__c), sum(s.Budget__c), ProductGroupCode__c
										from SalesHistory__c s 
										where s.Account__r.Owner.Country = :this.currentUser.Country and
											s.CurrentYear__c = 'Yes'
										group by s.ProductGroupCode__c];
		}
		else if (currentUser.ReportLevel__c == 'Corporate')
		{
			shList = [select sum(s.Sales__c), sum(s.Budget__c), ProductGroupCode__c
										from SalesHistory__c s 
										where s.CurrentYear__c = 'Yes'
										group by s.ProductGroupCode__c];
		}
		else
			return;
		doorChartData = mouldingChartData = sheetChartData = otherChartData = null;
		TallyResults (shList);			
		YTDTotalSales = totalSales;
		YTDTotalBudget = totalBudget;
		YTDChartData = new List<ChartData>();
		YTDChartData.add (doorChartData);
		YTDChartData.add (mouldingChartData);
		YTDChartData.add (sheetChartData);
		YTDChartData.add (otherChartData);
	}
	private void CalculateCollectionSales()
	{
		List<Opportunity> opps = null;
		YTDCollectionSales = 0;
		YTDCollectionBudget = 0;
        List<Account> acct = null;
        YTDCollectionCustSales = 0;
        
        
		if (currentUser.ReportLevel__c == 'Territory Manager')
		{
			opps = [select Id, CloseDate, CollectionsOpportunityValue__c
					from Opportunity
					where IsCollectionsOpportunity__c = True and IsClosed = False and Calendar_Year(CloseDate) = 2015
					and OwnerId = :UserInfo.getUserId()];
            acct = [select Id, X2015_Collections_Sales__c 
                    from Account
                    where OwnerId = :UserInfo.getUserId()];
			YTDCollectionBudget = this.currentUser.X2015_Collections_Budget__c;
		
            for (AggregateResult ar : [select sum(X2015_Collections_Sales__c) from Account where OwnerID = :UserInfo.getUserId() and X2015_Collections_Sales__c <> null])
			{
				YTDCollectionCustSales = (Decimal) ar.get('expr0');
        }
        }
		else if (currentUser.ReportLevel__c == 'Market Manager')
		{
			opps = [select Id, CloseDate, CollectionsOpportunityValue__c
					from Opportunity
					where IsCollectionsOpportunity__c = True and IsWon = False and Calendar_Year(CloseDate) = 2015
					and Owner.Branch__c = :currentUser.Branch__c];
            acct = [select Id, X2015_Collections_Sales__c 
                    from Account
                    where Owner.Branch__c = :currentUser.Branch__c];
        
			for (AggregateResult ar : [select sum(X2015_Collections_Budget__c) from User where Branch__c = :currentUser.Branch__c and IsActive = True and X2015_Collections_Budget__c <> null])
			{
				YTDCollectionBudget = (Decimal) ar.get('expr0');
             }
             for (AggregateResult ar : [select sum(X2015_Collections_Sales__c) from Account where Owner_Branch__c = :currentUser.BranchShort__c and X2015_Collections_Sales__c <> null])
			{
				YTDCollectionCustSales = (Decimal) ar.get('expr0');
		}
        }
		else if (currentUser.ReportLevel__c == 'Sales Director')
		{
			opps = [select Id, CloseDate, CollectionsOpportunityValue__c
					from Opportunity
					where IsCollectionsOpportunity__c = True and IsWon = False and Calendar_Year(CloseDate) = 2015
					and Owner.RegionSGI__c = :currentUser.RegionSGI__c];
            acct = [select Id, X2015_Collections_Sales__c 
                    from Account
                    where Owner.RegionSGI__c = :currentUser.RegionSGI__c];
            for (AggregateResult ar : [select sum(X2015_Collections_Budget__c) from User where RegionSGI__c = :currentUser.RegionSGI__c and IsActive = True and X2015_Collections_Budget__c <> null])
			{
				YTDCollectionBudget = (Decimal) ar.get('expr0');
            }
             for (AggregateResult ar : [select sum(X2015_Collections_Sales__c) from Account where Owner_Region_SGI__c = :currentUser.RegionSGI__c and X2015_Collections_Sales__c <> null])
			{
				YTDCollectionCustSales = (Decimal) ar.get('expr0');
			}
		}
		else if (currentUser.ReportLevel__c == 'VP of Sales')
		{
			opps = [select Id, CloseDate, CollectionsOpportunityValue__c
					from Opportunity
					where IsCollectionsOpportunity__c = True and IsWon = False and Calendar_Year(CloseDate) = 2015
					and Owner.Country = :currentUser.Country];
            acct = [select Id, X2015_Collections_Sales__c 
                    from Account
                    where Owner.Country = :currentUser.Country];
            for (AggregateResult ar : [select Sum(X2015_Collections_Budget__c) from User where Country = :currentUser.Country and IsActive = True and X2015_Collections_Budget__c <> null])
			{
				YTDCollectionBudget = (Decimal) ar.get('expr0');

			}
            for (AggregateResult ar : [select sum(X2015_Collections_Sales__c) from Account where Owner_Country__c = :currentUser.Country and X2015_Collections_Sales__c <> null])
			{
				YTDCollectionCustSales = (Decimal) ar.get('expr0');
			}
		}
		else if (currentUser.ReportLevel__c == 'Corporate')
		{
			opps = [select Id, CloseDate, CollectionsOpportunityValue__c
					from Opportunity
					where IsCollectionsOpportunity__c = True and IsWon = False  and Calendar_Year(CloseDate) = 2015];
            acct = [select Id, X2015_Collections_Sales__c
                    from Account];			
            for (AggregateResult ar : [select sum(X2015_Collections_Budget__c) from User where IsActive = True and X2015_Collections_Budget__c <> null])
			{
				YTDCollectionBudget = (Decimal) ar.get('expr0');
			}
            for (AggregateResult ar : [select sum(X2015_Collections_Sales__c) from Account where X2015_Collections_Sales__c <> null])
			{
				YTDCollectionCustSales = (Decimal) ar.get('expr0');
			}
		}
		else
			return;
		
        Decimal monthlyBudget;
		if (YTDCollectionBudget > 0)
			monthlyBudget = YTDCollectionBudget / 1;
        else
					monthlyBudget = 0;
        System.Debug ('==monthlyBudget:' + monthlyBudget);
        Decimal custsales;
		if (YTDCollectionCustSales > 0)
			custsales = YTDCollectionCustSales / 1;
		else
					custsales = 0;
        System.Debug ('==custsales:' + custsales);
		CollectionChart = new List<CollectionChartData>();
		CollectionChart.add (new CollectionChartData('J', 0, monthlyBudget, custsales));
		CollectionChart.add (new CollectionChartData('F', 0, monthlyBudget, custsales));
		CollectionChart.add (new CollectionChartData('M', 0, monthlyBudget, custsales));
		CollectionChart.add (new CollectionChartData('A', 0, monthlyBudget, custsales));
		CollectionChart.add (new CollectionChartData('M', 0, monthlyBudget, custsales));
		CollectionChart.add (new CollectionChartData('Jn', 0, monthlyBudget, custsales));
		CollectionChart.add (new CollectionChartData('Jl', 0, monthlyBudget, custsales));
		CollectionChart.add (new CollectionChartData('A', 0, monthlyBudget, custsales));
		CollectionChart.add (new CollectionChartData('S', 0, monthlyBudget, custsales));
		CollectionChart.add (new CollectionChartData('O', 0, monthlyBudget, custsales));
		CollectionChart.add (new CollectionChartData('N', 0, monthlyBudget, custsales));
		CollectionChart.add (new CollectionChartData('D', 0, monthlyBudget, custsales));

               
        for (Opportunity o : opps)
		{
			Integer idx = o.CloseDate.month()-1;
			System.assert(idx >= 0 && idx <= 12);
			CollectionChart[idx].sales += o.CollectionsOpportunityValue__c;
			YTDCollectionSales += o.CollectionsOpportunityValue__c;
			System.debug('==Collection:' + CollectionChart[idx].month + ' $' + CollectionChart[idx].sales);
		}
        
       

		// Remove any months up to the current month with zero value.  Stop at first month
		// found with a zero value.
		Integer currentMonth = Date.today().month()-1;
		System.assert(currentMonth >= 0 && currentMonth < 12);
		for (Integer idx = 11; idx > currentMonth && CollectionChart[idx].sales == 0; idx--)
		{
			CollectionChart.Remove(idx);
		}
	}
	private void TallyResults (List<AggregateResult> results)
	{
		totalSales = totalBudget = 0;
		for (AggregateResult ar : results)		
		{
			String productGroupCode = (String) ar.get('ProductGroupCode__c');
			System.Debug ('==productGroupCode__c:' + productGroupCode + ' Sales:' + ar.get('expr0') + ' Budget:' + ar.get('expr1'));
			if (productGroupCode == 'D')
				doorChartData = new ChartData ('Doors', (Decimal) ar.get('expr0'), (Decimal) ar.get('expr1'));
			else if (productGroupCode == 'M')
				mouldingChartData = new ChartData ('Mouldings', (Decimal) ar.get('expr0'), (Decimal) ar.get('expr1'));
			else if (productGroupCode == 'S')
				sheetChartData = new ChartData ('Sheets', (Decimal) ar.get('expr0'), (Decimal) ar.get('expr1'));
			else if (productGroupCode == 'O')
				otherChartData = new ChartData ('Other', (Decimal) ar.get('expr0'), (Decimal) ar.get('expr1'));
			totalSales += (Decimal) ar.get('expr0');
			totalBudget += (Decimal) ar.get('expr1');
		}
		if (doorChartData == null)
			doorChartData = new ChartData ('Doors', 0, 0);
		if (mouldingChartData == null)
			mouldingChartData = new ChartData ('Mouldings', 0, 0);
		if (sheetChartData == null)
			sheetChartData = new ChartData ('Sheets', 0, 0);
		if (otherChartData == null)
			otherChartData = new ChartData ('Other', 0, 0);
	}
	
	// Container for the chart data
	public class ChartData
	{
        public String name { get; set; }
        public Decimal dataSales { get; set; }
        public Decimal dataBudget { get; set; }


        public ChartData(String name, Decimal sales, Decimal budget)
        {
            this.name = name;
            this.dataSales = sales;
            this.dataBudget = budget;
        }
	}
	public class CollectionChartData
	{
		public String month { get; set; }
		public String year { get; set; }
		public Decimal sales { get; set; }
		public Decimal budget { get; set; }
        public Decimal custsales { get; set; }

		public CollectionChartData(string month, Decimal sales, Decimal budget, Decimal custsales)
		{
			this.month = month;
			this.sales = sales;
			this.budget = budget;
            this.custsales = custsales;
		}
	}
}

 
Best Answer chosen by Justin Ruck
Justin RuckJustin Ruck
I moved the parts of the VF page to componets, and now it's better. 

All Answers

David ZhuDavid Zhu
Just my 2c. You may use system.debug() to trace the running time for each step. It might help you find the issue.
Justin RuckJustin Ruck
I moved the parts of the VF page to componets, and now it's better. 
This was selected as the best answer