Answers.Body: <p>I'm not 100% sure if your images causing all the trouble because other pages without any images are really slow (compared to how fast they should be) as well. </p>
  
  <p>Maybe there is an issue with your server performance overall or you have something in your other layout templates that are causing trouble or you use some "not so well designed" plugins.</p>
  
  <p>Remember that you can always see what DB queries are happening in a given request by enabling <a href="http://buildwithcraft.com/docs/config-settings#devMode" rel="nofollow noreferrer">Dev Mode</a> and checking your browser’s Javascript console, where all DB queries for the current request will be logged, ordered by how long they took. If you don't understand what they mean - maybe you could share your results here after you removed the parts you don't want us to see. </p>
  
  <p>So if the issue is DB related you should be able to find it really quickly. However over all you should really avoid all these <code>style</code> tags and use proper css classes. That's usually bad practice and can slow your page down as well since you have to create/render so many tags every single time. </p>
  
  <p>Another good idea might be to lazy load your images. I know you use a front-end based lazy load but I mean a server based lazy load like many other pages. So you load about 10-15 elements during the creation of the DOM and the rest after the client scrolls down with Ajax. Your DOM is really huge, I didn't count the number of elements you fetch but if you halve them and notice a high performance boost you should really give it a try. If you wan't I can create the script/plugin for you.</p>
  
  <p>One last question: how did you structure your backend? Are all those images/texts/videos custom entries that you relate with your page?</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-02-13T16:32:55.783Z
Answers.Text: Thanks for the great reply Robin!
  
  Working through your points. I've toggled the plugins on and off and didn't see any improvements so I don't think it's that. 
  I've looked at the Console, seems to be taking 6-7s but couldn't spot anything which is taking a long time, just a lot going on.
  I've put the staging site into dev mode. If you're able to take a look and see if you can spot anything that would be hugely appreciated > http://p2p.progress-review.co.uk/what-we-do
  
  The back-end of this is build with a Section, then Entries with different Page Types for images/text/video
Answers.UserDisplayName: sarah3585
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-02-13T16:51:14.613Z
Answers.Text: Ok so: your page fires 373 queries which takes 10.23946s, for reference other pages (contact) with 26 queries take ( 1.3s). My sites with around 150 - 200 queries take about 1.3s to load. It could definitely be the server that is too slow or there is something else that slows it down too much. I didn't notice any fatal queries or something like that at the first sight. 373 queries are a lot but it should be a little bit faster, your average query time is about 4 times slower that it should be compared to other servers we use. I couldn't see any critical plugins as well
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-02-13T16:52:46.533Z
Answers.Text: So all in all: chances are high that it's the server itself that is a little bit too slow. Do you use a paid server or a free one? Is there a possibility for you to run the page on your local xampp/lamp/ environment? Or can you contact your hosting company and ask them to improve your values?
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-02-13T16:55:36.550Z
Answers.Text: It's slow on both my staging server and the clients server (shared hosting, but not free). Even my own local version is sluggish.
Answers.UserDisplayName: sarah3585
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-02-13T17:50:12.703Z
Answers.Text: Would using {% cache %} help in this situation?
Answers.UserDisplayName: sarah3585
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-02-14T08:22:21.027Z
Answers.Text: Sry for the late response. Yes using a cache tag could help if the content doesn't change every few minutes/hours. Another possibility is to eager load your elements to reduce your queries. That could eventually halve your queries https://craftcms.com/docs/templating/eager-loading-elements when you load the related assets together with the entries. And like I already said you should think about reloading your entries with ajax when a user scrolls down like facebook, youtube comments, instagram pictures and so on. I could do that for you at the weekend if you like
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-02-14T13:20:40.490Z
Answers.Text: I've implemented easy load and it using cache tags. Queries have been reduced to 195 now from the 373. Any other help to keep reducing this would be hugely appreciated. Thanks Robin.
Answers.UserDisplayName: sarah3585
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-02-14T14:17:26.703Z
Answers.Text: Glad I was able to help you. Yeah the page loads definitely faster right now. It's hard to say because we don't know your other layouts and we don't know you skillset. Please excuse me for this but giving advice to designers who don't know PHP that much an use CMS to create sites is always a little bit dangerous. I had many Wordpress designers that did fatal mistakes without knowing it. There could be obvious issues with your other templates that you don't notice and we don't ask about because we think no one will do these mistakes That should be no offence It's just my general experience with
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-02-14T14:17:32.193Z
Answers.Text: designers - there is a reason why developers learn the background mechanics before we start to code (to learn performance issues). As I said, using ajax will increase your site performance probably very much. Keep in mind that your dev server is nearly twice as fast than your live server. I tested a few entries and they are all significant faster. In the end it could still take up to 6s to load some of your paginate pages.You could limit the number of entries you show to 15. If it's getting better -> use ajax. However compared to where you started you did a good job. I wish you good luck
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-02-12T18:48:12.983Z
Answers.LastActivityDate: 2018-02-12T18:54:13.983Z
Answers.LastEditDate: 2018-02-12T18:54:13.983Z
Answers.UserDisplayName: Robin Schambach
Body: <p>I'm trying to speed up this page: <a href="http://planned2perfection.co.uk/what-we-do" rel="nofollow noreferrer">http://planned2perfection.co.uk/what-we-do</a></p>
  
  <p>Yes it has a lot of images but I think it's TTFB that's the issue here. It's built with Structures which I'm thinking could be the bottle neck.</p>
  
  <p>Is that something which will improve in Craft 3? Any tips of what I can do to help improve it?</p>
  
  <pre><code>    &lt;div class="grid__col-sizer"&gt;&lt;/div&gt;
      &lt;div class="grid__gutter-sizer"&gt;&lt;/div&gt;
      &lt;div class="grid-item"&gt;
      &lt;div class="grid-item__inner {% if entry.type.handle == 'image' %}grid-item--image{% endif %}"&gt;
        {% if entry.type.handle == 'image' %}
        {% for image in entry.image %}
        {# Build the markup for the media queries with the image dimensions. #}
        {% set firstMediaQueryWidth = 320 %}
        {% set firstMediaQueryHeight = ( image.getHeight('galleriesThumb') / ( image.getWidth('galleriesThumb') / firstMediaQueryWidth ) ) %}
        {% set secondMediaQueryWidth = 282 %}
        {% set secondMediaQueryHeight = ( image.getHeight('galleriesThumb') / ( image.getWidth('galleriesThumb') / secondMediaQueryWidth ) ) %}
        {% set thirdMediaQueryWidth = 330 %}
        {% set thirdMediaQueryHeight = ( image.getHeight('galleriesThumb') / ( image.getWidth('galleriesThumb') / thirdMediaQueryWidth ) ) %}
        {% set fourthMediaQueryWidth = 382 %}
        {% set fourthMediaQueryHeight = ( image.getHeight('galleriesThumb') / ( image.getWidth('galleriesThumb') / fourthMediaQueryWidth ) ) %}
        {% set firstMediaQueryData = firstMediaQueryData ~ ".open-pop[href=\"#item-p#{ pageNum }#{ loopIndex }\"] img { width: #{firstMediaQueryWidth}px; height: #{firstMediaQueryHeight|round}px }" %}
        {% set secondMediaQueryData = secondMediaQueryData ~ ".open-pop[href=\"#item-p#{ pageNum }#{ loopIndex }\"] img { width: #{secondMediaQueryWidth}px; height: #{secondMediaQueryHeight|round}px }" %}
        {% set thirdMediaQueryData = thirdMediaQueryData ~ ".open-pop[href=\"#item-p#{ pageNum }#{ loopIndex }\"] img { width: #{thirdMediaQueryWidth}px; height: #{thirdMediaQueryHeight|round}px }" %}
        {% set fourthMediaQueryData = fourthMediaQueryData ~ ".open-pop[href=\"#item-p#{ pageNum }#{ loopIndex }\"] img { width: #{fourthMediaQueryWidth}px; height: #{fourthMediaQueryHeight|round}px }" %}
        &lt;style&gt;
           @media screen and (min-width: 500px) {
           {{firstMediaQueryData|raw}}
           }
           @media screen and (min-width: 990px) {
           {{secondMediaQueryData|raw}}
           }
           @media screen and (min-width: 1200px) {
           {{thirdMediaQueryData|raw}}
           }
           @media screen and (min-width: 1600px) {
           {{fourthMediaQueryData|raw}}
           }
        &lt;/style&gt;
        &lt;a href="#item-p{{ pageNum }}{{ loopIndex }}" class="open-pop"&gt;
           &lt;div class="grid-item__image"&gt;
              &lt;div class="image-block-thumb"&gt;&lt;/div&gt;
              &lt;img class="lazyload" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="{{ image.getUrl('galleriesThumb')}}" alt="{{ image.title}}" /&gt;
              &lt;noscript&gt;
                 &lt;img src="{{ image.getUrl('galleriesThumb')}}" alt="{{ image.title}}" /&gt;
              &lt;/noscript&gt;
              {% endfor %}
           &lt;/div&gt;
        &lt;/a&gt;
        {% if entry.shortDescription is not empty %}
        &lt;div class="block-short-description"&gt;{{ entry.shortDescription }}&lt;/div&gt;
        {% endif %}
        {% endif %}
        {% if entry.type.handle == 'video' %}
        &lt;div class="video-container"&gt;
           &lt;div id="myElement-{{ entry.mediaId }}" class="video"&gt;&lt;/div&gt;
        &lt;/div&gt;
        &lt;script&gt;
           var playerInstance = jwplayer("myElement-{{ entry.mediaId }}");
           playerInstance.setup({
           file: "//content.jwplatform.com/videos/{{ entry.mediaId }}-{{ entry.mediaType }}",
           image:"http://content.jwplatform.com/thumbs/{{ entry.mediaId }}-480.jpg",
                          stretching:"fill",
                          preload: "none",
               mediaid: "{{ entry.mediaId }}",
               logo: {
                  hide: true,
              },
           });
        &lt;/script&gt;
        {% if entry.shortDescription is not empty %}
        &lt;div class="block-short-description"&gt;{{ entry.shortDescription }}
        &lt;/div&gt;
        {% endif %}
        {% endif %}
        {% if entry.type.handle == 'text' %}
        &lt;div class="block-text {% if entry.quote %}block-quote{% endif %}"&gt;{{ entry.textArea }}&lt;/div&gt;
        {% endif %}
     &lt;/div&gt;
     &lt;div id="item-p{{ pageNum }}{{ loopIndex }}" class="white-popup mfp-hide"&gt;
        &lt;div class="white-popup__inner"&gt;
           &lt;div class="img-container"&gt;
              {% if entry.type.handle == 'image' %}
              {% if images.getWidth() &lt; images.getHeight() %}
              &lt;img src="{{ images.url ('galleriesLargePortrait') }}" alt="{{ images.title }}"&gt;
              {% if entry.description is not empty %} 
              &lt;div class="content"&gt;
                 {{ entry.description }}
              &lt;/div&gt;
              {% endif %}
              {% else %}
              {% if entry.category.first.slug == 'venues' %}
              &lt;img src="{{ images.url ('galleriesLargeVenues') }}" alt="{{ images.title }}"&gt;
              {% else %}
              &lt;img src="{{ images.url ('galleriesLarge') }}" alt="{{ images.title }}"&gt;
              {% endif %}
              {% if entry.description is not empty %}   
              &lt;div class="content"&gt;
                 {{ entry.description }}
              &lt;/div&gt;
              {% endif %}
              {% endif %}
              {% endif %}
              &lt;/div&gt;
              &lt;/div&gt;
             &lt;/div&gt;
             &lt;/div&gt;
  </code></pre>
  
Tags: <structure><performance>
Title: Improving page performance issue
ThreadText: # Improving page performance issue
  
  (Asked by: username_0 on 2018-02-12)
  
  I'm trying to speed up this page: <http://planned2perfection.co.uk/what-we-do>
  
  Yes it has a lot of images but I think it's TTFB that's the issue here. It's built with Structures which I'm thinking could be the bottle neck.
  
  Is that something which will improve in Craft 3? Any tips of what I can do to help improve it?
  
  ```
      <div class="grid__col-sizer"></div>
      <div class="grid__gutter-sizer"></div>
      <div class="grid-item">
      <div class="grid-item__inner {% if entry.type.handle == 'image' %}grid-item--image{% endif %}">
        {% if entry.type.handle == 'image' %}
        {% for image in entry.image %}
        {# Build the markup for the media queries with the image dimensions. #}
        {% set firstMediaQueryWidth = 320 %}
        {% set firstMediaQueryHeight = ( image.getHeight('galleriesThumb') / ( image.getWidth('galleriesThumb') / firstMediaQueryWidth ) ) %}
        {% set secondMediaQueryWidth = 282 %}
        {% set secondMediaQueryHeight = ( image.getHeight('galleriesThumb') / ( image.getWidth('galleriesThumb') / secondMediaQueryWidth ) ) %}
        {% set thirdMediaQueryWidth = 330 %}
        {% set thirdMediaQueryHeight = ( image.getHeight('galleriesThumb') / ( image.getWidth('galleriesThumb') / thirdMediaQueryWidth ) ) %}
        {% set fourthMediaQueryWidth = 382 %}
        {% set fourthMediaQueryHeight = ( image.getHeight('galleriesThumb') / ( image.getWidth('galleriesThumb') / fourthMediaQueryWidth ) ) %}
        {% set firstMediaQueryData = firstMediaQueryData ~ ".open-pop[href=\"#item-p#{ pageNum }#{ loopIndex }\"] img { width: #{firstMediaQueryWidth}px; height: #{firstMediaQueryHeight|round}px }" %}
        {% set secondMediaQueryData = secondMediaQueryData ~ ".open-pop[href=\"#item-p#{ pageNum }#{ loopIndex }\"] img { width: #{secondMediaQueryWidth}px; height: #{secondMediaQueryHeight|round}px }" %}
        {% set thirdMediaQueryData = thirdMediaQueryData ~ ".open-pop[href=\"#item-p#{ pageNum }#{ loopIndex }\"] img { width: #{thirdMediaQueryWidth}px; height: #{thirdMediaQueryHeight|round}px }" %}
        {% set fourthMediaQueryData = fourthMediaQueryData ~ ".open-pop[href=\"#item-p#{ pageNum }#{ loopIndex }\"] img { width: #{fourthMediaQueryWidth}px; height: #{fourthMediaQueryHeight|round}px }" %}
        <style>
           @media screen and (min-width: 500px) {
           {{firstMediaQueryData|raw}}
           }
           @media screen and (min-width: 990px) {
           {{secondMediaQueryData|raw}}
           }
           @media screen and (min-width: 1200px) {
           {{thirdMediaQueryData|raw}}
           }
           @media screen and (min-width: 1600px) {
           {{fourthMediaQueryData|raw}}
           }
        </style>
        <a href="#item-p{{ pageNum }}{{ loopIndex }}" class="open-pop">
           <div class="grid-item__image">
              <div class="image-block-thumb"></div>
              <img class="lazyload" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="{{ image.getUrl('galleriesThumb')}}" alt="{{ image.title}}" />
              <noscript>
                 <img src="{{ image.getUrl('galleriesThumb')}}" alt="{{ image.title}}" />
              </noscript>
              {% endfor %}
           </div>
        </a>
        {% if entry.shortDescription is not empty %}
        <div class="block-short-description">{{ entry.shortDescription }}</div>
        {% endif %}
        {% endif %}
        {% if entry.type.handle == 'video' %}
        <div class="video-container">
           <div id="myElement-{{ entry.mediaId }}" class="video"></div>
        </div>
        <script>
           var playerInstance = jwplayer("myElement-{{ entry.mediaId }}");
           playerInstance.setup({
           file: "//content.jwplatform.com/videos/{{ entry.mediaId }}-{{ entry.mediaType }}",
           image:"http://content.jwplatform.com/thumbs/{{ entry.mediaId }}-480.jpg",
                          stretching:"fill",
                          preload: "none",
               mediaid: "{{ entry.mediaId }}",
               logo: {
                  hide: true,
              },
           });
        </script>
        {% if entry.shortDescription is not empty %}
        <div class="block-short-description">{{ entry.shortDescription }}
        </div>
        {% endif %}
        {% endif %}
        {% if entry.type.handle == 'text' %}
        <div class="block-text {% if entry.quote %}block-quote{% endif %}">{{ entry.textArea }}</div>
        {% endif %}
     </div>
     <div id="item-p{{ pageNum }}{{ loopIndex }}" class="white-popup mfp-hide">
        <div class="white-popup__inner">
           <div class="img-container">
              {% if entry.type.handle == 'image' %}
              {% if images.getWidth() < images.getHeight() %}
              <img src="{{ images.url ('galleriesLargePortrait') }}" alt="{{ images.title }}">
              {% if entry.description is not empty %} 
              <div class="content">
                 {{ entry.description }}
              </div>
              {% endif %}
              {% else %}
              {% if entry.category.first.slug == 'venues' %}
              <img src="{{ images.url ('galleriesLargeVenues') }}" alt="{{ images.title }}">
              {% else %}
              <img src="{{ images.url ('galleriesLarge') }}" alt="{{ images.title }}">
              {% endif %}
              {% if entry.description is not empty %}   
              <div class="content">
                 {{ entry.description }}
              </div>
              {% endif %}
              {% endif %}
              {% endif %}
              </div>
              </div>
             </div>
             </div>
  
  ```
  
  **Tags:** structure, performance
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2018-02-12. Score: 2
  
  I'm not 100% sure if your images causing all the trouble because other pages without any images are really slow (compared to how fast they should be) as well.
  
  Maybe there is an issue with your server performance overall or you have something in your other layout templates that are causing trouble or you use some "not so well designed" plugins.
  
  Remember that you can always see what DB queries are happening in a given request by enabling [Dev Mode](http://buildwithcraft.com/docs/config-settings#devMode) and checking your browser’s Javascript console, where all DB queries for the current request will be logged, ordered by how long they took. If you don't understand what they mean - maybe you could share your results here after you removed the parts you don't want us to see.
  
  So if the issue is DB related you should be able to find it really quickly. However over all you should really avoid all these `style` tags and use proper css classes. That's usually bad practice and can slow your page down as well since you have to create/render so many tags every single time.
  
  Another good idea might be to lazy load your images. I know you use a front-end based lazy load but I mean a server based lazy load like many other pages. So you load about 10-15 elements during the creation of the DOM and the rest after the client scrolls down with Ajax. Your DOM is really huge, I didn't count the number of elements you fetch but if you halve them and notice a high performance boost you should really give it a try. If you wan't I can create the script/plugin for you.
  
  One last question: how did you structure your backend? Are all those images/texts/videos custom entries that you relate with your page?
  
  > **Comments:**
  > **username_0**: Thanks for the great reply username_1!  Working through your points. I've toggled the plugins on and off and didn't see any improvements so I don't think it's that.  I've looked at the Console, seems to be taking 6-7s but couldn't spot anything which is taking a long time, just a lot going on. I've put the staging site into dev mode. If you're able to take a look and see if you can spot anything that would be hugely appreciated > http://p2p.progress-review.co.uk/what-we-do  The back-end of this is build with a Section, then Entries with different Page Types for images/text/video  
  > **username_1**: Ok so: your page fires 373 queries which takes 10.23946s, for reference other pages (contact) with 26 queries take ( 1.3s). My sites with around 150 - 200 queries take about 1.3s to load. It could definitely be the server that is too slow or there is something else that slows it down too much. I didn't notice any fatal queries or something like that at the first sight. 373 queries are a lot but it should be a little bit faster, your average query time is about 4 times slower that it should be compared to other servers we use. I couldn't see any critical plugins as well  
  > **username_1**: So all in all: chances are high that it's the server itself that is a little bit too slow. Do you use a paid server or a free one? Is there a possibility for you to run the page on your local xampp/lamp/ environment? Or can you contact your hosting company and ask them to improve your values?  
  > **username_0**: It's slow on both my staging server and the clients server (shared hosting, but not free). Even my own local version is sluggish.  
  > **username_0**: Would using {% cache %} help in this situation?  
  > **username_1**: Sry for the late response. Yes using a cache tag could help if the content doesn't change every few minutes/hours. Another possibility is to eager load your elements to reduce your queries. That could eventually halve your queries https://craftcms.com/docs/templating/eager-loading-elements when you load the related assets together with the entries. And like I already said you should think about reloading your entries with ajax when a user scrolls down like facebook, youtube comments, instagram pictures and so on. I could do that for you at the weekend if you like  
  > **username_0**: I've implemented easy load and it using cache tags. Queries have been reduced to 195 now from the 373. Any other help to keep reducing this would be hugely appreciated. Thanks username_1.  
  > **username_1**: Glad I was able to help you. Yeah the page loads definitely faster right now. It's hard to say because we don't know your other layouts and we don't know you skillset. Please excuse me for this but giving advice to designers who don't know PHP that much an use CMS to create sites is always a little bit dangerous. I had many Wordpress designers that did fatal mistakes without knowing it. There could be obvious issues with your other templates that you don't notice and we don't ask about because we think no one will do these mistakes That should be no offence It's just my general experience with  
  > **username_1**: designers - there is a reason why developers learn the background mechanics before we start to code (to learn performance issues). As I said, using ajax will increase your site performance probably very much. Keep in mind that your dev server is nearly twice as fast than your live server. I tested a few entries and they are all significant faster. In the end it could still take up to 6s to load some of your paginate pages.You could limit the number of entries you show to 15. If it's getting better -> use ajax. However compared to where you started you did a good job. I wish you good luck  
  
  ---
  
  