Craft model and populateModels() performance issue? I'm getting a big performance hit on front end requests (+15 seconds) when using a model to store / use data from one of my custom fieldtypes, cp requests for the same data appear unaffected.

The prepValue function:

public function prepValue($value)
{
    if( is_array($value) )
    {
        return FruitGrid_BlockModel::populateModels($value);
    }

    return $value;
}


And the model which is getting populated:

class FruitGrid_BlockModel extends BaseModel
{
    protected function defineAttributes()
    {
        return array(
            'row' =&gt; array(AttributeType::Number),
            'col' =&gt; array(AttributeType::Number),
            'sizex' =&gt; array(AttributeType::Number),
            'sizey' =&gt; array(AttributeType::Number),
            'entryid' =&gt; array(AttributeType::Number),
            'rules' =&gt; array(AttributeType::Mixed),
        );
    }

    public function getRuleClasses()
    {
        $string = '';
        if(is_array($this-&gt;rules))
        {
            foreach ($this-&gt;rules as $rule =&gt; $value)
            {
                switch ($rule)
                {
                    case 'fixedHeight':
                        $string .= ' height-'.$value;
                        break;
                    case 'desktopRuleOne':
                        $string .= ' desktop-'.$value;
                        break;
                    case 'tabletRuleOne':
                        $string .= ' tablet-'.$value;
                        break;
                    case 'mobileRuleOne':
                        $string .= ' mobile-'.$value;
                        break;
                }
            }
        }
        return trim($string);
    }

    public function getEntry()
    {
        $criteria = craft()-&gt;elements-&gt;getCriteria(ElementType::Entry);
        $criteria-&gt;id = $this-&gt;entryid;
        return $criteria-&gt;first();
    }
}


And pretty standard usage on the front end:

{% if entry.customFieldHandle|length %}

    {% for block in entry.customFieldHandle %}

        &lt;h1&gt;{{ block.entry.title }}&lt;/h2&gt;
        &lt;p&gt;{{ block.entry.text }}&lt;/p&gt;

        ...

    {% endfor %}

{% endif %}
Avoid calling block.entry multiple time per block since you only need to do that database query once. Alternatively you can use function memoization to cache the entry like this:

class FruitGrid_BlockModel extends BaseModel
{
    private $_entry;

    protected function defineAttributes()
    {
        return array(
            'row' =&gt; array(AttributeType::Number),
            'col' =&gt; array(AttributeType::Number),
            'sizex' =&gt; array(AttributeType::Number),
            'sizey' =&gt; array(AttributeType::Number),
            'entryid' =&gt; array(AttributeType::Number),
            'rules' =&gt; array(AttributeType::Mixed),
        );
    }

    public function getRuleClasses()
    {
        //...
    }

    public function getEntry()
    {
        if(!$this-&gt;_entry){
            $criteria = craft()-&gt;elements-&gt;getCriteria(ElementType::Entry);
            $criteria-&gt;id = $this-&gt;entryid;
            $this-&gt;_entry = $criteria-&gt;first();
        }

        return $this-&gt;_entry;

    }
}


This will only get the entry from the database once.

Also recommend renaming the rules attribute on the model to something like blockRules.

When you loop over the rules to create the ruleClasses string you may be looping over every rule created by the AttributeType declarations in your defineAttributes method.