Flickrnet - Hard Drive usage goes to 100% and stays there.

Topics: Developer Forum
Jul 21, 2014 at 1:40 PM
Edited Jul 21, 2014 at 1:44 PM
We've implemented FlickrNet on about 10 sites so we're fairly familiar with how it works. We recently updated the DLL to the latest version and everything was working fine.

However, last Friday we noticed two of our server hard drives we're running at 100% constantly. We tracked the issue down to any site using FlickrNet but despite debugging we can't see where the problem is.

The only issue encountered while debugging is that we occasionally got a 502 error, the content of which appeared to come from Flickr telling us that they apologised for the outage and that their engineers were working on a fix. This happened irregularly but was the only problem we found.

We're unsure what the problem might be but perhaps it's a caching issue, maybe a corrupt cache, although I can't see how that would give us a 502.

In any case, has anyone else encountered this or something similar? We've searched but haven't found anything so far.
Coordinator
Jul 21, 2014 at 1:56 PM
I see irregular 502 errors on quite a frequent basis. Unfortunately there isn't a lot I can do about the error as it comes directly from Flickr (or from one of their front end cache servers I suspect).

I'm not sure how this would affect hard drive usage though.

Sam
Jul 21, 2014 at 2:05 PM
Thanks for the quick reply Sam, it's appreciated. Yes we're in the dark as to how this could affect HDD usage either, but the proof appears to be in the fact that once it's turned off (commented out the Flickrnet calls) the HDD usage drops again and the server calms down.

I'd have considered it coding issue but we'd upgraded to the new DLL at least a week previously and all sites were running fine, which makes me think its something related to the cache. Perhaps something building up over time, some cache call or reference that all our sites would have after X number of days that's now causing the server to go crazy seeking the cached files.

Can we easily clear the cache (i.e. ideally without having to make code changes, is there a web.config edit we can make to flush the cache and restart?)

Thanks.
Coordinator
Jul 21, 2014 at 2:21 PM
You can use a config file:

https://flickrnet.codeplex.com/wikipage?title=ExampleConfigFile&referringTitle=Examples

However this only works if you use the parameterless constructor.

You can manually clear the cache if you can work out where it is, usually C:\Users\<username>\AppData\Local\FlickrNet\ or something similar, depending on who the site is running as etc.

Sam
Jul 21, 2014 at 4:56 PM
Edited Jul 22, 2014 at 11:55 AM
Hi

A little bit of further info, when I disable the cache the HDD usage drops to normal levels. Turn it back on and it spikes again to max and stays there. If I then delete the cache files and turn caching on it no longer spikes as often but I believe that as the cache file gets larger the spikes will get longer. I'll know more tomorrow once it's had time to run for a while.


UPDATE:

Here's a screen grab of Perfmon running locally, showing avg disk queue length (green line) when we access a flickrnet page on one of our sites. On the server the equivalent perfmon shows 100% and stays there, locally it's a little less constant.

http://i.imgur.com/NehXYMC.jpg
Coordinator
Jul 22, 2014 at 2:30 PM
Average Disk Queue Length isn't a percentage, and you have the "scale" set to 100, so you actually have an average disk queue length which fluctuates between 0 and 3. A quick Google reveals that an average of greater than 0.7 means there is likely excessive disk queuing, however your average is 0.2 (with a 'last' value of 0.015) in the image. I wouldn't assume therefore that there was actually a disk issue.

As an aside, have you considered just turning Flickr cache off, and implementing caching in your web site?

Sam
Jul 22, 2014 at 2:50 PM
Hi

Sorry should probably have sent you the live one, we just didn't want to grind the servers down again. However, we did and here's the result:

http://i.imgur.com/gD4wOxD.jpg%5b/IMG

As you can see it's far higher than locally, and this is acutally a mild version of what happens, we didn't leave long enough to totally hammer the server. We have turned off caching but the result is just too slow to work with, caching makes it a viable solution, or it used to until this started happening.
Coordinator
Jul 22, 2014 at 2:57 PM
OK, yeah, that looks worse, unfortunately.

I'm not sure what the cause could be - apart from the fact that the caching in FlickrNet isn't very good - but it's never been very good - I haven't updated the cache code in ages.

I have considered ripping it out and providing an interface for people to configure their own caching, is that something that would help you do you think?

Sam
Jul 22, 2014 at 3:21 PM
Well anything that can get us back up and running would be great as at the moment we've had to turn off the Flickr areas of quite a few of our sites. I'll keep trying solutions in the interim and hopefully either a caching interface as you mention or some other suggestion or idea that we find might sort this issue. Thanks again for the quick replies, it's rare to get such good support from a free product.
Coordinator
Jul 22, 2014 at 4:03 PM
Is there anyway you could send me some details of the method you are calling or some example code?

Perhaps we can look at the calls you are making and see if there are any alternatives?

Sam
Jul 23, 2014 at 11:19 AM
Edited Jul 23, 2014 at 11:19 AM
Hi Sam,

Eoin has asked me to provide a code sample to you. Here is a sample of the C# from an Image Detail page. Please bare with us.

This page has a user control which displays the large image. It also displays the other images in the set in a repeater. And finally it displays cover photos & links to all other sets from that user in a repeater.
   protected void SetFlickrPhotoFromId(string strPhotoId)
    {
        //oFlickr.PhotosGetInfo can throw an error
        //so catch the error and return a 404 
        try
        {
            //Instantiate a new flickr object
            Flickr oFlickr = new Flickr(this.FlickrApiKey);

            //instantiate a new PhotoInfo object
            PhotoInfo oPhotoInfo = oFlickr.PhotosGetInfo(strPhotoId);

            //do stuff to set the page title etc based on oPhotoInfo 
        }
     }

        public static Photo GetNextPhoto(string strPhotoId, string strFlickrUserID, string strFlickrApiKey)
        {

            try
            {
                //Instantiate a new flickr object
                Flickr oFlickr = new Flickr(strFlickrApiKey);

                //get all the photosets for that user
                Photosets oPhotosets = oFlickr.PhotosetsGetList(strFlickrUserID);

                //loop through all the photo sets
                foreach (Photoset oPhotoset in oPhotosets.PhotosetCollection)
                {
                    //get a collection of the photos in the current set
                    PhotoCollection photoCollection = oFlickr.PhotosetsGetPhotos(oPhotoset.PhotosetId);

                    //create a flag to say if the current id matches
                    bool bIsCurrent = false;

                    //loop through each photo the collection
                    foreach (Photo oPhoto in photoCollection)
                    {
                        //If bcurrent has been set to true
                        //We know to return the next number
                        if (bIsCurrent)
                        {
                            return oPhoto;
                        }

                        //check if the photoid is equal to the one we passed in
                        if (oPhoto.PhotoId == strPhotoId)
                        {
                            //it is - so set the flag to true
                            bIsCurrent = true;

                        }
                    }
                }

                return null;

            }
            catch
            {
                return null;
            }
        }
       
        public static Photo GetPreviousPhoto(string strPhotoId, string strFlickrUserID, string strFlickrApiKey)
        {

            try
            {
                //Instantiate a new flickr object
                Flickr oFlickr = new Flickr(strFlickrApiKey);

                //get all the photosets for that user
                Photosets oPhotosets = oFlickr.PhotosetsGetList(strFlickrUserID);

                Photo oPreviousPhoto = new Photo();

                //loop through all the photo sets
                foreach (Photoset oPhotoset in oPhotosets.PhotosetCollection)
                {
                    //get a collection of the photos in the current set
                    PhotoCollection photoCollection = oFlickr.PhotosetsGetPhotos(oPhotoset.PhotosetId);

                    //create a flag to say if the current id matches
                    bool bIsCurrent = false;

                    //loop through each photo the collection
                    foreach (Photo oPhoto in photoCollection)
                    {
                        //check if the photoid is equal to the one we passed in
                        if (oPhoto.PhotoId == strPhotoId)
                        {
                            //it is - so set the flag to true
                            bIsCurrent = true;

                            //and return the previous id
                            return oPreviousPhoto;
                        }

                        //If bcurrent has not been set to true.
                        //probably no need for this IF but just to be safe
                        if (!bIsCurrent)
                        {
                            //then assign the id
                            oPreviousPhoto = oPhoto;
                        }
                    }
                }

                return null;

            }
            catch
            {
                return null;
            }
        }
       
        public static Photoset GetSetDetailsFromPhotoId(string strPhotoId, string strFlickrUserID, string strFlickrApiKey)
        {

            try
            {
                //Instantiate a new flickr object
                Flickr oFlickr = new Flickr(strFlickrApiKey);

                //get all the photosets for that user
                Photosets oPhotosets = oFlickr.PhotosetsGetList(strFlickrUserID);

                //loop through all the photo sets
                foreach (Photoset oPhotoset in oPhotosets.PhotosetCollection)
                {
                    //get a collection of the photos in the current set
                    PhotoCollection photoCollection = oFlickr.PhotosetsGetPhotos(oPhotoset.PhotosetId);

                    //loop through each photo the colelction
                    foreach (Photo oPhoto in photoCollection)
                    {
                        //check if the photoid is equal to the one we passed in
                        if (oPhoto.PhotoId == strPhotoId)
                        {
                            //it is - so return the ID
                            return oPhotoset;
                        }
                    }
                }

                return null;

            }
            catch
            {
                return null;
            }
        }
        
       public static PhotoCollection GetSetPhotosFromPhotoId(string strPhotoId, string strFlickrUserID, string strFlickrApiKey)
        {

            try
            {
                //Instantiate a new flickr object
                Flickr oFlickr = new Flickr(strFlickrApiKey);

                //get all the photosets for that user
                Photosets oPhotosets = oFlickr.PhotosetsGetList(strFlickrUserID);

                //loop through all the photo sets
                foreach (Photoset oPhotoset in oPhotosets.PhotosetCollection)
                {
                    //get a collection of the photos in the current set
                    PhotoCollection photoCollection = oFlickr.PhotosetsGetPhotos(oPhotoset.PhotosetId);

                    //loop through each photo the colelction
                    foreach (Photo oPhoto in photoCollection)
                    {
                        //check if the photoid is equal to the one we passed in
                        if (oPhoto.PhotoId == strPhotoId)
                        {
                            //it is - so return the set
                            return photoCollection;
                        }
                    }
                }

                return null;

            }
            catch
            {
                return null;
            }
        }

       public static Photosets GetAllPhotoSets(string strFlickrUserID, string strFlickrApiKey)
        {

            try
            {
                //Instantiate a new flickr object
                Flickr oFlickr = new Flickr(strFlickrApiKey);

                //get all the photosets for that user
                Photosets oPhotosets = oFlickr.PhotosetsGetList(strFlickrUserID);

                return oPhotosets;

            }
            catch
            {
                return null;
            }
        }

        public static bool IsFlickrOnline()
        {
            bool bIsOnline = true;

            string URL = "http://www.flickr.com";

            try
            {
                //Create a request for the URL. 
                WebRequest request = WebRequest.Create(URL);

                request.Proxy = null;

                //Get the response.
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                //check the status
                if (response.StatusDescription != "OK")
                {
                    //status not ok - return false
                    bIsOnline = false;
                }
            }
            catch
            {
                return false;
            }

            return bIsOnline;
        }

    protected void rptrMoreGalleries_OnItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            //DISPLAYING ALL THE OTHER SETS.........
            Photoset oPhotoset = (Photoset)e.Item.DataItem; 

            //Find the image and set it
            Image PhotoThumb = (Image)e.Item.FindControl("PhotoThumb");

            //instantiate a flickr object
            Flickr oFlickr = new Flickr(this.FlickrApiKey);

            //get the photoinfo for the primar photo
            PhotoInfo oPhotoInfo = oFlickr.PhotosGetInfo(oPhotoset.PrimaryPhotoId);

            //do stuff to display the sets info
          }
     }
Any Ideas on our code?

Could it be that your caching is writing the image data to many far corners of the HD causing much spinning? Would there be any fix you could apply here?

Thanks in advance.
Coordinator
Jul 23, 2014 at 12:49 PM
Edited Jul 23, 2014 at 1:16 PM
Wow, yeah, a few comments. You are pulling back a huge amount of data there for no reason.

Couple of quick points.

GetSetPhotosFromPhotoId - try calling PhotosGetAllContexts to return a list of all the sets a photo is in, rather than asking for every set the user owns and then asking for every photo in every set...

Once you have the photo ID and the set ID you can call PhotosetsGetContext to return the next and previous photo in the photoset.

Here's some alternative (modified) versions of some of those functions, hopefully to give you some idea.
public static string GetSetIdFromPhotoId(string strPhotoId, string strFlickrApiKey)
{
    try
    {
        //Instantiate a new flickr object
        Flickr oFlickr = new Flickr(strFlickrApiKey);

        //get all the photosets for that user
        AllContexts context = oFlickr.PhotosGetAllContexts(strPhotoId);

        if (context.Sets == null || context.Sets.Count == 0) return null;

        return context.Sets[0].PhotosetId;
    }
    catch
    {
        return null;
    }
}

public static PhotosetPhotoCollection GetSetPhotosFromPhotoId(string strPhotoId, string strFlickrApiKey)
{
    try
    {
        //Instantiate a new flickr object
        Flickr oFlickr = new Flickr(strFlickrApiKey);

        var setId = GetSetIdFromPhotoId(strPhotoId, strFlickrApiKey);

        return oFlickr.PhotosetsGetPhotos(setId);
    }
    catch
    {
        return null;
    }
}

public static PhotoInfo GetNextPhoto(string strPhotoId, string strFlickrApiKey)
{

    try
    {
        //Instantiate a new flickr object
        Flickr oFlickr = new Flickr(strFlickrApiKey);

        string setId = GetSetIdFromPhotoId(strPhotoId, strFlickrApiKey);

        Context context = oFlickr.PhotosetsGetContext(strPhotoId, setId);

        if (context.NextPhoto == null) return null;

        return oFlickr.PhotosGetInfo(context.NextPhoto.PhotoId);

    }
    catch
    {
        return null;
    }
}

public static PhotoInfo GetPrevPhoto(string strPhotoId, string strFlickrApiKey)
{

    try
    {
        //Instantiate a new flickr object
        Flickr oFlickr = new Flickr(strFlickrApiKey);

        string setId = GetSetIdFromPhotoId(strPhotoId, strFlickrApiKey);

        Context context = oFlickr.PhotosetsGetContext(strPhotoId, setId);

        if (context.PreviousPhoto == null) return null;

        return oFlickr.PhotosGetInfo(context.PreviousPhoto.PhotoId);

    }
    catch
    {
        return null;
    }
}
The final thing is there may be no need to call PhotosGetInfo if all of the information you need is already on the Photo or Photoset instance. e.g. Photoset.PhotosetSquareThumbnailUrl is one of the thumbnail urls for the primary photo for the photoset.

I suspect that 99% of the time you are calling PhotosGetInfo you don't need to, but I'd need to see the bits you've commented out above to be sure (update to clarify - this is most often seen when getting a photo collection from Flickr, and then calling GetInfo on each photo - almost never needed).
Jul 23, 2014 at 1:31 PM
Thanks for the reply. I will look into your advice. Much appreciated.

It might not explain though, why this was working OK for 3+ years. then when we upgraded to FlickrNet.dll File version 2.0.2.4.1583 these issues started arising.

Granted we had to change some of the Types in our logic based on your new class names & method names. But the logic remains the exact same on the same websites.

Let me know what you think?

Here are some pieces from my original code that were missing:
protected void SetFlickrPhotoFromId(string strPhotoId)
    {
        //oFlickr.PhotosGetInfo can throw an error
        //so catch the error and return a 404 
        try
        {
            //Instantiate a new flickr object
            Flickr oFlickr = new Flickr(this.FlickrApiKey);

            //instantiate a new PhotoInfo object
            PhotoInfo oPhotoInfo = oFlickr.PhotosGetInfo(strPhotoId);


            if (oPhotoInfo != null)
            {
                //show the image
                pnlPhoto.Visible = true;
                imgDetail.ImageUrl = oPhotoInfo.MediumUrl;
            }

            //set the next & previous buttons
            if (this.ShowNextPrev)
            {
                pnlNextPrev.Visible = this.ShowNextPrev;

                //set the previous link
                Photo oPreviousPhoto = FlickrUtility.GetPreviousPhoto(strPhotoId, this.flickrUserID, this.FlickrApiKey);

                if (oPreviousPhoto != null && !string.IsNullOrEmpty(oPreviousPhoto.PhotoId))
                {
                    hlkPrevious.NavigateUrl = "~/" + UrlUtility.GetUrlFriendlyString(oPreviousPhoto.Title) + "." + this.Item.ItemId + "." + this.Item.LanguageId + ".1." + oPreviousPhoto.PhotoId + ".aspx";
                    hlkPrevious.Visible = true;
                }


                //set the next link
                Photo oNextPhoto = FlickrUtility.GetNextPhoto(strPhotoId, this.flickrUserID, this.FlickrApiKey);

                if (oNextPhoto != null && !string.IsNullOrEmpty(oNextPhoto.PhotoId))
                {
                    hlkNext.NavigateUrl = "~/" + UrlUtility.GetUrlFriendlyString(oNextPhoto.Title) + "." + this.Item.ItemId + "." + this.Item.LanguageId + ".1." + oNextPhoto.PhotoId + ".aspx";
                    hlkNext.Visible = true;
                }


            }

            //set the caption
            if (this.ShowCaption)
            {
                pnlCaption.Visible = true;
                ltlCaption.Text = oPhotoInfo.Title;
            }

            //do the meta stuff - because we are in a photo detail page

            if (this.OverWriteTitleMeta)
            {

                //intitialize the title and desc to the photo / title and desc
                string strTitle = oPhotoInfo.Title;
                string strDescription = oPhotoInfo.Description;

                if (this.PageTitleIsSetName)
                {
                    //we want to use the parent SET's name as the title and desc

                    //get the parent SET
                    Photoset oPhotoset = FlickrUtility.GetSetDetailsFromPhotoId(strPhotoId, this.flickrUserID, this.FlickrApiKey);

                    //use the title desc
                    strTitle = oPhotoset.Title;
                    strDescription = oPhotoset.Description;

                }


                //overwrite the page title
                this.Page.Title = StringUtility.RemoveHtml(strTitle);

                //include the name of the website in the title
                this.Page.Title = this.Page.Title + " | " + this.Client.Name;

                //overwrite the keywords
                string strKeywords = oPhotoInfo.Title;

                if (oPhotoInfo.Tags.TagCollection != null)
                {
                    //loop through the tags
                    foreach (PhotoInfoTag oPhotoInfoTag in oPhotoInfo.Tags.TagCollection)
                    {
                        strKeywords += oPhotoInfoTag.TagText + ", ";
                    }
                }

                StringUtility.ReplaceLast(strKeywords, ",", "");

                HtmlGenericControl metaKeywords = (HtmlGenericControl)ControlUtility.FindAnyControl(this.Page, "metaKeywords");
                metaKeywords.Attributes.Add("content", strKeywords);

                //overwrite the description
                if (string.IsNullOrEmpty(strDescription))
                {
                    strDescription = strTitle;
                }

                HtmlGenericControl metaDescription = (HtmlGenericControl)ControlUtility.FindAnyControl(this.Page, "metaDescription");
                metaDescription.Attributes.Add("content", strDescription);

                //overwrite the h1 heading
                Literal ltlHeading = (Literal)ControlUtility.FindAnyControl(this.Page, "ltlHeading");
                ltlHeading.Text = strTitle;

            }
        }
        catch
        {
            //display the friendly error
            lblError.Text = "Image Service Currently Unavailable";
            lblError.Visible = true;
            pnlPhoto.Visible = false;

            //generate a 404 Not Found header status-code
            Response.Status = "404 Not Found";
            
        }
    }
And
 protected void rptrMoreGalleries_OnItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            Photoset oPhotoset = (Photoset)e.Item.DataItem;



            //Find the image and set it
            Image PhotoThumb = (Image)e.Item.FindControl("PhotoThumb");

            //instantiate a flickr object
            Flickr oFlickr = new Flickr(this.FlickrApiKey);

            //get the photoinfo for the primar photo
            PhotoInfo oPhotoInfo = oFlickr.PhotosGetInfo(oPhotoset.PrimaryPhotoId);

            if (oPhotoInfo != null && !string.IsNullOrEmpty(oPhotoInfo.SquareThumbnailUrl))
            {
                PhotoThumb.ImageUrl = oPhotoInfo.SquareThumbnailUrl;
            }

            PhotoThumb.Visible = true;
            PhotoThumb.AlternateText = oPhotoset.Title;
            PhotoThumb.ToolTip = oPhotoset.Title;

            //Find the link and set it
            HyperLink hlkImage = (HyperLink)e.Item.FindControl("hlkImage");

            //create a "re-written" url that contains the photo name
            hlkImage.ToolTip = "Go to Gallery: " + oPhotoset.Title;
            
            if (!this.RedirectToDetailPage)
            {
                //create a "re-written" url that contains the photo set name
                //THIS URL GOES TO THE PHOTO SET LISTING
                hlkImage.NavigateUrl = "~/" + UrlUtility.GetUrlFriendlyString(oPhotoset.Title) + "." + this.FlickrListingPageId + "." + this.Item.LanguageId + ".1." + oPhotoset.PhotosetId + ".aspx";

            }
            else
            {
                //create a "re-written" url that contains the photo  SET name
                //THIS URL GOES TO THE FIRST PHOTO DETAIL IN THE SET
                if (oPhotoInfo != null)
                {
                    hlkImage.NavigateUrl = "~/" + UrlUtility.GetUrlFriendlyString(oPhotoset.Title) + "." + this.FlickrDetailPageId + "." + this.Item.LanguageId + ".1." + oPhotoInfo.PhotoId + ".aspx";
                }

            }
            
            //show the gallery name?
            if (this.ShowGalleryName)
            {
                //Find the link and set it
                HyperLink hlkGalleryName = (HyperLink)e.Item.FindControl("hlkGalleryName");
                hlkGalleryName.ToolTip = "Go to Gallery: " + oPhotoset.Title;
                hlkGalleryName.Text = oPhotoset.Title;
                hlkGalleryName.Visible = true;

                if (!this.RedirectToDetailPage)
                {
                    //create a "re-written" url that contains the photo name
                    hlkGalleryName.NavigateUrl = "~/" + UrlUtility.GetUrlFriendlyString(oPhotoset.Title) + "." + this.FlickrListingPageId + "." + this.Item.LanguageId + ".1." + oPhotoset.PhotosetId + ".aspx";
                }
                else
                {
                    //create a "re-written" url that contains the photo  SET name
                    //THIS URL GOES TO THE FIRST PHOTO DETAIL IN THE SET
                    if (oPhotoInfo != null)
                    {
                        //create a "re-written" url that contains the photo name
                        hlkGalleryName.NavigateUrl = "~/" + UrlUtility.GetUrlFriendlyString(oPhotoset.Title) + "." + this.FlickrDetailPageId + "." + this.Item.LanguageId + ".1." + oPhotoInfo.PhotoId + ".aspx";
                    }

                }
            }

            //check every nth item
            //insert a clear fix to insure no display issues if long title
            if ((this.Index > 0) && (this.ClearLeftAfter > 0) && (this.Index % this.ClearLeftAfter == 0))
            {
                HtmlGenericControl liPhoto = (HtmlGenericControl)e.Item.FindControl("liPhoto");
                liPhoto.Attributes.Add("style", "clear:left;");

            }
            this.Index++;
        }
    }
Again, thank you
Coordinator
Jul 23, 2014 at 1:40 PM
You upgraded from 2.0.2? That was released in about 2006, so yeah, the whole project has been completely re-written since then.

If all you need for the 'next' and 'previous' photo is the Title and PhotoId then just use the NextPhoto and PreviousPhoto properties returned by PhotosetsGetContext. They are of type ContextPhoto but have the Title and PhotoId as properties. No need for another call to Flickr.GetPhotoInfo, and certainly no need to loop through every single photoset and every single photo in each set just to find the relevant photos.

You do also seem to be assuming that each photo is only in one photoset, which obviously doesn't have to be the case, but may be if you are controlling the sets as well.

Sam
Jul 23, 2014 at 1:51 PM
Apologies, I actually upgraded from 2.0.2 to 3.12.0.0. That was a typo in my previous post.

Thanks for the advice. I am going through all your advice and implementing.

I fully accept that the logic we have is heavy and pulling out extra info, but it was working away great for a long time before switching to 3.12.0.0.

Will let you know how implementing your advised changes goes.

Cheers!
Jul 23, 2014 at 3:06 PM
Looks like that, and turning OFF caching has done the trick.

We took your advice and re-factored the code, removing any unnecessary calls to Flickr.GetPhotoInfo.

And we also implemented the method changes above you sent on for GetSetIdFromPhotoId, GetSetPhotosFromPhotoId, GetNextPhoto and GetPrevPhoto.

At that point we began monitoring the Average Disk Queue Length but we only saw a small improvement on Average Disk Queue Length.

So we decided to try turn OFF caching to work along side your changes. Thus hitting flickr for the photos and not our own HD.

There was a dramatic improvement in Average Disk Queue Length at this point.

That was on one site. Hopefully when we deploy the changes to multiple websites on the same server the results will be good.

Thank you. Appreciate it.