[Assignments] Assignments and Modules are Slow to Load If There Is a Lot of Content

I am a Canvas Admin in a K-12 Environment. Although we have used Canvas for about 6 years, this is the first school year we are seeing very heavy use of the platform in all subject areas. One issue that we are starting to run into is that accumulated assignments and modules are causing the pages to lock up and not load all the way for anywhere from 1 minute to even longer to load the page. Sometimes the Assignments page will not load at all unless I use the API to delete several assignments first! So the crux of my idea is making the assignments page and modules page load more efficiently. 

I would love to see a sort of lazy-loading implemented on Assignments and Modules where perhaps the browser only renders assignments as the user scrolls rather than attempting to load the entire course assignments. 

We are only at the halfway point of the school year and this issue is happening in many courses. The assignments page in particular seems to give trouble when there are over 100 assignments. I know 100 assignments may sound like a lot, but that's really just one assignment per school day. We can mitigate it by sorting by grading period but sometimes the page locks up before we can hit that dropdown. That's great for the assignments page but there is no such grading period filter for the Modules page.

I am currently working around it by having teachers offload their assignments into a sandbox course (so they can keep a copy of it) and then mass deleting them with a python script I wrote. 

18 Comments
James
Community Champion

@MattHanes 

I did some more checking and removing the descriptions won't help the assignments page. Sorry about that. The query has exclude_response_fields[]=description in it so the descriptions aren't sent. The images wouldn't have mattered anyway unless they used the data url, but if they were included in an image element, it wouldn't have fetched them since it doesn't display the page. Close that rabbit hole. 

When you look at what is sent, there is still a lot of information sent that isn't used. That's where the GraphQL could come in, but that's something that Canvas will have to implement on their end.

 

I don't use grading periods, so it's hard for me to test things out, but the List assignment groups endpoint does support a grading_period_id query parameter.

Since I can't see how grading periods work, let's see if you can help me out. The How do I use grading periods in a course lesson from the Instructor's Guide says that you can filter them on the Assignments Index Page. That page shows a grading period drop down that starts with "All Grading Periods."

That leaves me with some questions.

  1. Does it remember the grading period filter setting or does it always reset to all grading periods?
  2. If you change the filter while it's taking 30+ seconds to load the page, does it abort the current fetch and return just those from the current grading period or does it force you to do the full load before you can change the filter?

If Canvas remembers the setting, then we potentially have a huge improvement. Depending on where it saves that information, we could go through with custom JavaScript and set it to the default grading period if it is currently unset.

If the request can be interrupted, then we could use custom JavaScript to change the filter as soon as the page loads. It would abort the 30 second download and replace it with a 8 second download (assuming you have four grading periods of equal size). That's still pretty long so other avenues might need pursued as well.

The request comes from the assignments index page itself using window.prefetched_xhrs using the fetch() function. Because it's a script on the page, that means that there's little way to modify it before it gets sent. The custom JavaScript is loaded after the page is ready. You could with Tampermonkey and telling it when to run before the page loads, but you don't want to do that for all of your users.

fetch() uses promises and that makes it more challenging to cancel. I remember when Canvas updated the Admin page, the list of courses was very slow because they were trying to fetch all of them and then filter. Now they filter on the server and only deliver 15 at a time. The assignment groups API still fetches all of the data, though.

GraphQL can get the necessary information a lot faster, but that is something that would need to be implemented on Canvas side. You could fetch it and redisplay the page yourself, but Canvas wouldn't know what to do with it. In the meantime, it may continue to download the other information.

At some point, I did some work with intercepting the built-in fetch command and replacing it with my own. I was bypassing the command to not look in the browser's cache first so that I didn't have to redownload everything that Canvas had just sent, but was able to use their fetch results. I don't remember the exact particulars and don't see how it would help here. If I could intercept the call before it's made, then I could rewrite the request to include the grading period. But we run into the issue of the call is made as soon as the page is loaded. Just throwing this out in case it sparks something somewhere else.

MattHanes
Community Champion
Author

@James, it really does seem like the GraphQL option is what will really speed up the load times. At 200+ assignments, it takes at least 4 trips to return everything because the per_page is set to 50. 

It does remember the grading period, unfortunately it still uses the same fetch parameters regardless. So it still hangs up waiting to return every assignment before it renders the filtered page. Maybe that would be a good intermediary step (before graphQL implementation) to use the grading_period_id parameter to limit the return size. It would be really fast for grading periods 1, 2, and 3 but the 4th grading period is where Canvas dumps everything without a due date so that one is usually much bigger. 

Changing the filter does not appear to abort the request because it's not limiting the request using the filter anyway, I guess. 

James
Community Champion

@MattHanes 

Did you verify (look at the network traffic) that it takes 4 trips to deliver the 200 assignments? My experience is that the per_page applies to the number of groups and not the number of assignments within each group. You get every assignment within the assignment groups that are delivered. If you're seeing 4 requests, it might actually be using grading periods as part of the query.

In other areas, like the people page, filtering re-sends just the filtered information. I had to modify my Roster Sorter script a couple of weeks ago to accommodate for that. If there are not many assignments, then downloading them all and filtering in the browser may be faster than re-downloading a filtered response every time the filter changes.

On one hand, I can see why they want to deliver all the results at once. It allows you to change things without having to wait 30 seconds just to change the sort from type or date in the student view.

However, for grading periods, it definitely could be handled better. Changing grading periods could force a reload.

For students, they have the ability to limit the assignments to just that student and for the current grading period, but that doesn't apply to teachers, so we're stuck waiting.

How realistic is it to not use the Assignments page? It's definitely part of my workflow, but I could create assignments from the modules page. Most of the things that I need to grade could be accessed from the To Do list -- my current workflow is to go to the assignments page and open it there so I don't go to SpeedGrader, but I could go from SpeedGrader to the assignment. I have the assignments linked from my modules page or from my weekly resources page. I go to Assignments because it's easier for me, but if I was waiting 30+ seconds every time I went, I might re-evaluate my notion of easier.

I know that large courses struggled for a long time to be manageable. When I went to Project Khaki in 2017, I was part of a group working on how to make the gradebook more usable for large classes. They now have filtering that doesn't download the information that is filtered out to speed it up. It really looks like they need something here.

The current "Search for Assignment" box is the only filtering I have and it still requires that all of  the information be fetched first so the filter can be applied to it.

Sadly, your answers didn't give me any ideas that can be implemented by the institution to speed things up. This really needs to be something that is taken up by the people that write the software. GraphQL definitely has potential here, but I'm not sure how much it would save over the downloading of unnecessary information. There is already a single API call that returns all of the information that is needed, it just takes a long time to pull all that information together. Unless the slowness comes from getting unneeded information, it would only save in the amount of information downloaded but not the time it takes to gather the information.

 

MattHanes
Community Champion
Author

@James, I think not using the Assignments list is more reasonable than it was now that our Elementary teachers have received more targeted training about course organization. I think the issue was the intuitiveness of how things are created in Canvas. It was more intuitive (particularly before the new Elementary theme) for teachers to click on the course navigation link that corresponded to the thing they were trying to make. 

Now they are more likely to create a module (or copy a module template) and add new content directly in the module. If they have to add existing assignments, that list is really long and it can be tedious to find it if you don't remember which Assignment Group it was in. A filter-by-name in the content selector for modules would be useful for that case. 

I looked through some of the other courses that were experiencing the issue last year and I'm no longer having the problem where the assignment page completely locks up the browser and never renders. 

KristinL
Community Team
Community Team
Status changed to: New
 
KristinL
Community Team
Community Team
Status changed to: Added to Theme
 
nathanatkinson
Community Team
Community Team
Status changed to: New
 
nathanatkinson
Community Team
Community Team
Status changed to: Open