Answers.Body: <p>Avoid calling <code>block.entry</code> 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:</p>
  
  <pre><code>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;
  
      }
  }
  </code></pre>
  
  <p>This will only get the entry from the database once.</p>
  
  <p>Also recommend renaming the <code>rules</code> attribute on the model to something like <code>blockRules</code>.</p>
  
  <p>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 <code>defineAttributes</code> method.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-09-09T10:14:10.047Z
Answers.Text: Ah I see, removing ```{{ block.ruleClasses }}``` improved things a drop, but I was accessing ```{{ block.entry.customField }}``` loads of times, storing / caching the entry and accessing it via this var helped loads. So does it get the entry each time i hit block.entry??
Answers.UserDisplayName: Sam Hibberd
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-09-09T10:15:43.820Z
Answers.Text: ah yes, you are doing a db call every time you do `block.entry`. You could cache it in the plugin function or just assign it once per block in the template like so: {% set blockEntry = block.entry %}. This would have been causing the huge slowdown more than my answer.
Answers.UserDisplayName: Luke Holder
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-09-09T11:30:40.830Z
Answers.Text: Yes, this was the issue, although your suggestion certainly helped speed things up. What do you mean by cache in the function? Set a var that is checked before grabbing the entry and set only if it has not be retrieved?
Answers.UserDisplayName: Sam Hibberd
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-09-09T11:31:50.617Z
Answers.Text: Sorry Luke, just saw you answer! Exactly as expected, thanks!!!
Answers.UserDisplayName: Sam Hibberd
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-09-09T09:15:20.273Z
Answers.LastActivityDate: 2015-09-09T10:24:50.947Z
Answers.LastEditDate: 2015-09-09T10:24:50.947Z
Answers.UserDisplayName: Luke Holder
Body: <p>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.</p>
  
  <p>The prepValue function:</p>
  
  <pre><code>public function prepValue($value)
  {
      if( is_array($value) )
      {
          return FruitGrid_BlockModel::populateModels($value);
      }
  
      return $value;
  }
  </code></pre>
  
  <p>And the model which is getting populated:</p>
  
  <pre><code>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();
      }
  }
  </code></pre>
  
  <p>And pretty standard usage on the front end:</p>
  
  <pre><code>{% 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 %}
  </code></pre>
  
Tags: <plugin-development><fieldtypes><performance>
Title: Craft model and populateModels() performance issue?
ThreadText: # Craft model and populateModels() performance issue?
  
  (Asked by: username_0 on 2015-09-09)
  
  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' => array(AttributeType::Number),
              'col' => array(AttributeType::Number),
              'sizex' => array(AttributeType::Number),
              'sizey' => array(AttributeType::Number),
              'entryid' => array(AttributeType::Number),
              'rules' => array(AttributeType::Mixed),
          );
      }
  
      public function getRuleClasses()
      {
          $string = '';
          if(is_array($this->rules))
          {
              foreach ($this->rules as $rule => $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()->elements->getCriteria(ElementType::Entry);
          $criteria->id = $this->entryid;
          return $criteria->first();
      }
  }
  
  ```
  
  And pretty standard usage on the front end:
  
  ```
  {% if entry.customFieldHandle|length %}
  
      {% for block in entry.customFieldHandle %}
  
          <h1>{{ block.entry.title }}</h2>
          <p>{{ block.entry.text }}</p>
  
          ...
  
      {% endfor %}
  
  {% endif %}
  
  ```
  
  **Tags:** plugin-development, fieldtypes, performance
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2015-09-09. Score: 2 | Accepted answer
  
  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' => array(AttributeType::Number),
              'col' => array(AttributeType::Number),
              'sizex' => array(AttributeType::Number),
              'sizey' => array(AttributeType::Number),
              'entryid' => array(AttributeType::Number),
              'rules' => array(AttributeType::Mixed),
          );
      }
  
      public function getRuleClasses()
      {
          //...
      }
  
      public function getEntry()
      {
          if(!$this->_entry){
              $criteria = craft()->elements->getCriteria(ElementType::Entry);
              $criteria->id = $this->entryid;
              $this->_entry = $criteria->first();
          }
  
          return $this->_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.
  
  > **Comments:**
  > **username_0**: Ah I see, removing ```{{ block.ruleClasses }}``` improved things a drop, but I was accessing ```{{ block.entry.customField }}``` loads of times, storing / caching the entry and accessing it via this var helped loads. So does it get the entry each time i hit block.entry??  
  > **username_1**: ah yes, you are doing a db call every time you do `block.entry`. You could cache it in the plugin function or just assign it once per block in the template like so: {% set blockEntry = block.entry %}. This would have been causing the huge slowdown more than my answer.  
  > **username_0**: Yes, this was the issue, although your suggestion certainly helped speed things up. What do you mean by cache in the function? Set a var that is checked before grabbing the entry and set only if it has not be retrieved?  
  > **username_0**: Sorry username_1, just saw you answer! Exactly as expected, thanks!!!  
  
  ---
  
  