Search

I have an install running patched 2.0.7 that is getting a memory error in class.lang.php on line 21.

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 71 bytes) in /xxx/symphony/lib/toolkit/class.lang.php on line 21

Has anyone run into his before? I’m not using localization of any kind, is there a simple way to bypass this function or class?

The odd thing is that it is only occurring on 3 Pages (which have the largest DS and final output on the site). The web admins had apparently gotten this before with memory at 64 & now they’re getting it again with the memory up to 128.

The error says that 71 bytes of memory cannot be allocated. That is such a small amount of memory that, while a workaround is almost certainly possible, there wouldn’t be much of a point to it. It would be more fruitful to look for things to optimize elsewhere. For example, if your main navigation does not change, then you might consider foregoing the use of a navigation data source in favor of hardcoding the navigation into the XSLT. That is just one possibility among many.

This is a bit of a longshot, and might not do anything.

But I recall Alistair and myself noticing a bit of a bottleneck with the _t function when we started on Symphony 3. You might be able to compare Symphony 2 with Symphony 3 and backport the Symphony 3 changes to see if that improves your S2 performance.

From memory, the main difference is using strstr to do the straight character replacement, and only use preg_match for the pattern replacement. The S2 and S3 language files differ slightly to help accomplish this.

Let us know how you go :)

This most likely isn’t an issue with class.lang.php itself - it just means whatever page you’re loading has used up too much memory.

If I where you, I’d boost PHPs memory limit until it runs correctly and then look at optimising your data sources, or anything else that may be using a lot of memory.

Thanks everyone for your tips. It looks like the prevailing opinion is correct: I had a DS that was running a crazy high number of queries. Basically I have a section to hold votes & my votes DS loads all vote entries. The site has gotten up to ~4000 vote entries, and that appears to be choking things up.

So now I need to replace the stock vote DS with a more efficient (I presume custom-written) DS. Anyone have a good reference DS for doing something like this?

Here is the code of a custom DS which I used to do some statistics. It is probably over-complicated for your use-case, but it should be rather easy to simplify the DS.

This one counts only entries from 2009-07 and later an build a monthly statistic:

  • total entries
  • entries with “type1”
  • entries with “type2”

(Type1 and Type2 are selctbox field values.)

The datasource name, the datasource ID and the database query are hardcoded! (But it works with many many entries…)

<?php

    require_once(TOOLKIT . '/class.datasource.php');

    Class datasourcekontakt_magno_statistik extends Datasource
    {
        public $dsParamROOTELEMENT = 'my-datasource';

        public function __construct(&$parent, $env=NULL, $process_params=true)
        {
            parent::__construct($parent, $env, $process_params);
            $this->_dependencies = array();
        }

        public function about()
        {
            return array(
                     'name' => 'My Datasource',
                     'author' => array(
                            'name' => 'Michael Eichelsdörfer',
                            'website' => 'http://www.michael-eichelsdoerfer.de',
                            'email' => 'info@michael-eichelsdoerfer.de'),
                     'version' => '1.0',
                     'release-date' => '2010-06-29');
        }

        public function getSource()
        {
            return '44';
        }

        public function allowEditorToParse()
        {
            return false;
        }

        public function grab(&$param_pool)
        {
            $year = '2009';
            $month = '07';
            $section_id = $this->getSource();

            $result = new XMLElement($this->dsParamROOTELEMENT);

            try
            {
                $entries = Symphony::Database()->fetch("SELECT t1.`id` as 'id', YEAR(t2.`value`) as 'year', MONTH(t2.`value`) as 'month', t3.`value` AS 'type' FROM `sym_entries` AS t1 JOIN `sym_entries_data_247` AS t2 ON (t1.`id` =  t2.`entry_id`) LEFT JOIN  `sym_entries_data_590` AS t3 ON (t1.`id` =  t3.`entry_id`);");

                while($year <= date('Y'))
                {
                    while(($year.sprintf("%02d", $month) <= date('Ym')) && $month <= 12)
                    {
                        $entry_count_total = 0;
                        $entry_count_strom = 0;
                        $entry_count_gas = 0;

                        foreach($entries as $entry){
                            if($entry['year'] == $year && $entry['month'] == $month && ($entry['type'] == 'Type1' || $entry['type'] == 'Type2')) $entry_count_total++;
                            if($entry['year'] == $year && $entry['month'] == $month && $entry['type'] == 'Type2') $entry_count_type1++;
                            if($entry['year'] == $year && $entry['month'] == $month && $entry['type'] == 'Type3') $entry_count_type2++;
                        }

                        $entry = new XMLElement('period');
                        $entry->setAttribute('year', $year);
                        $entry->setAttribute('month', sprintf("%02d", $month));
                        $entry->setAttribute('total', $entry_count_total);
                        $entry->setAttribute('type1', $entry_count_type1);
                        $entry->setAttribute('type2', $entry_count_type2);
                        $result->appendChild($entry);
                        $month++;
                    }
                    $year++;
                    $month = 1;
                }
                return $result;
            }
            catch(Exception $e)
            {
                $result->appendChild(new XMLElement('error', $e->getMessage()));
                return $result;
            }
            if($this->_force_empty_result) $result = $this->emptyXMLSet();
            return $result;
        }
    }

OK I’ve finally got this put to bed I think.

While michael-e’s solution was probably the best way to go, I wussed out and used SymQL to retrieve my vote counts without actually loading every vote. This got the memory from presumably > 128 Mb to ~ 8, so that did the trick.

That SymQL is quite handy; thanks Nick!

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details