Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
63ddbd9b
Commit
63ddbd9b
authored
Jul 10, 2015
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cache CustomCourseForEdX object lookup per-request
parent
1e84ad99
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
95 additions
and
36 deletions
+95
-36
lms/djangoapps/ccx/overrides.py
+7
-1
lms/djangoapps/ccx/tests/test_field_override_performance.py
+85
-35
lms/djangoapps/ccx/tests/test_overrides.py
+3
-0
No files found.
lms/djangoapps/ccx/overrides.py
View file @
63ddbd9b
...
...
@@ -7,6 +7,8 @@ import logging
from
django.db
import
transaction
,
IntegrityError
import
request_cache
from
courseware.field_overrides
import
FieldOverrideProvider
# pylint: disable=import-error
from
opaque_keys.edx.keys
import
CourseKey
,
UsageKey
from
ccx_keys.locator
import
CCXLocator
,
CCXBlockUsageLocator
...
...
@@ -69,7 +71,11 @@ def get_current_ccx(course_key):
if
not
isinstance
(
course_key
,
CCXLocator
):
return
None
return
CustomCourseForEdX
.
objects
.
get
(
pk
=
course_key
.
ccx
)
ccx_cache
=
request_cache
.
get_cache
(
'ccx'
)
if
course_key
not
in
ccx_cache
:
ccx_cache
[
course_key
]
=
CustomCourseForEdX
.
objects
.
get
(
pk
=
course_key
.
ccx
)
return
ccx_cache
[
course_key
]
def
get_override_for_ccx
(
ccx
,
block
,
name
,
default
=
None
):
...
...
lms/djangoapps/ccx/tests/test_field_override_performance.py
View file @
63ddbd9b
...
...
@@ -5,6 +5,7 @@ Performance tests for field overrides.
import
ddt
import
itertools
import
mock
from
nose.plugins.skip
import
SkipTest
from
courseware.views
import
progress
# pylint: disable=import-error
from
courseware.field_overrides
import
OverrideFieldData
...
...
@@ -25,6 +26,8 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, \
TEST_DATA_SPLIT_MODULESTORE
,
TEST_DATA_MONGO_MODULESTORE
from
xmodule.modulestore.tests.factories
import
check_mongo_calls
,
CourseFactory
,
check_sum_of_calls
from
xmodule.modulestore.tests.utils
import
ProceduralCourseTestMixin
from
ccx_keys.locator
import
CCXLocator
from
ccx.tests.factories
import
CcxFactory
,
CcxMembershipFactory
@attr
(
'shard_1'
)
...
...
@@ -58,6 +61,7 @@ class FieldOverridePerformanceTestCase(ProceduralCourseTestMixin,
self
.
request
=
self
.
request_factory
.
get
(
"foo"
)
self
.
request
.
user
=
self
.
student
self
.
course
=
None
self
.
ccx
=
None
MakoMiddleware
()
.
process_request
(
self
.
request
)
...
...
@@ -113,17 +117,42 @@ class FieldOverridePerformanceTestCase(ProceduralCourseTestMixin,
self
.
course
.
id
)
def
grade_course
(
self
,
course
):
if
enable_ccx
:
self
.
ccx
=
CcxFactory
.
create
()
CcxMembershipFactory
.
create
(
student
=
self
.
student
,
ccx
=
self
.
ccx
)
def
grade_course
(
self
,
course
,
view_as_ccx
):
"""
Renders the progress page for the given course.
"""
course_key
=
course
.
id
if
view_as_ccx
:
course_key
=
CCXLocator
.
from_course_locator
(
course_key
,
self
.
ccx
.
id
)
return
progress
(
self
.
request
,
course_id
=
course
.
id
.
to_deprecated_string
(
),
course_id
=
unicode
(
course_key
),
student_id
=
self
.
student
.
id
)
def
instrument_course_progress_render
(
self
,
course_width
,
enable_ccx
,
queries
,
reads
,
xblocks
):
def
assertMongoCallCount
(
self
,
calls
):
"""
Assert that mongodb is queried ``calls`` times in the surrounded
context.
"""
return
check_mongo_calls
(
calls
)
def
assertXBlockInstantiations
(
self
,
instantiations
):
"""
Assert that exactly ``instantiations`` XBlocks are instantiated in
the surrounded context.
"""
return
check_sum_of_calls
(
XBlock
,
[
'__init__'
],
instantiations
,
instantiations
,
include_arguments
=
False
)
def
instrument_course_progress_render
(
self
,
course_width
,
enable_ccx
,
view_as_ccx
,
queries
,
reads
,
xblocks
):
"""
Renders the progress page, instrumenting Mongo reads and SQL queries.
"""
...
...
@@ -146,16 +175,16 @@ class FieldOverridePerformanceTestCase(ProceduralCourseTestMixin,
OverrideFieldData
.
provider_classes
=
None
with
self
.
assertNumQueries
(
queries
):
with
check_mongo_calls
(
reads
):
with
check_sum_of_calls
(
XBlock
,
[
'__init__'
],
xblocks
,
xblocks
,
include_arguments
=
False
):
self
.
grade_course
(
self
.
course
)
with
self
.
assertMongoCallCount
(
reads
):
with
self
.
assertXBlockInstantiations
(
xblocks
):
self
.
grade_course
(
self
.
course
,
view_as_ccx
)
@ddt.data
(
*
itertools
.
product
((
'no_overrides'
,
'ccx'
),
range
(
1
,
4
),
(
True
,
False
)))
@ddt.data
(
*
itertools
.
product
((
'no_overrides'
,
'ccx'
),
range
(
1
,
4
),
(
True
,
False
)
,
(
True
,
False
)
))
@ddt.unpack
@override_settings
(
FIELD_OVERRIDE_PROVIDERS
=
(),
)
def
test_field_overrides
(
self
,
overrides
,
course_width
,
enable_ccx
):
def
test_field_overrides
(
self
,
overrides
,
course_width
,
enable_ccx
,
view_as_ccx
):
"""
Test without any field overrides.
"""
...
...
@@ -163,9 +192,18 @@ class FieldOverridePerformanceTestCase(ProceduralCourseTestMixin,
'no_overrides'
:
(),
'ccx'
:
(
'ccx.overrides.CustomCoursesForEdxOverrideProvider'
,)
}
if
overrides
==
'no_overrides'
and
view_as_ccx
:
raise
SkipTest
(
"Can't view a ccx course if field overrides are disabled."
)
if
not
enable_ccx
and
view_as_ccx
:
raise
SkipTest
(
"Can't view a ccx course if ccx is disabled on the course"
)
if
self
.
MODULESTORE
==
TEST_DATA_MONGO_MODULESTORE
and
view_as_ccx
:
raise
SkipTest
(
"Can't use a MongoModulestore test as a CCX course"
)
with
self
.
settings
(
FIELD_OVERRIDE_PROVIDERS
=
providers
[
overrides
]):
queries
,
reads
,
xblocks
=
self
.
TEST_DATA
[(
overrides
,
course_width
,
enable_ccx
)]
self
.
instrument_course_progress_render
(
course_width
,
enable_ccx
,
queries
,
reads
,
xblocks
)
queries
,
reads
,
xblocks
=
self
.
TEST_DATA
[(
overrides
,
course_width
,
enable_ccx
,
view_as_ccx
)]
self
.
instrument_course_progress_render
(
course_width
,
enable_ccx
,
view_as_ccx
,
queries
,
reads
,
xblocks
)
class
TestFieldOverrideMongoPerformance
(
FieldOverridePerformanceTestCase
):
...
...
@@ -176,19 +214,25 @@ class TestFieldOverrideMongoPerformance(FieldOverridePerformanceTestCase):
__test__
=
True
TEST_DATA
=
{
# (providers, course_width, enable_ccx): # of sql queries, # of mongo queries, # of xblocks
(
'no_overrides'
,
1
,
True
):
(
23
,
7
,
14
),
(
'no_overrides'
,
2
,
True
):
(
68
,
7
,
85
),
(
'no_overrides'
,
3
,
True
):
(
263
,
7
,
336
),
(
'ccx'
,
1
,
True
):
(
23
,
7
,
14
),
(
'ccx'
,
2
,
True
):
(
68
,
7
,
85
),
(
'ccx'
,
3
,
True
):
(
263
,
7
,
336
),
(
'no_overrides'
,
1
,
False
):
(
23
,
7
,
14
),
(
'no_overrides'
,
2
,
False
):
(
68
,
7
,
85
),
(
'no_overrides'
,
3
,
False
):
(
263
,
7
,
336
),
(
'ccx'
,
1
,
False
):
(
23
,
7
,
14
),
(
'ccx'
,
2
,
False
):
(
68
,
7
,
85
),
(
'ccx'
,
3
,
False
):
(
263
,
7
,
336
),
# (providers, course_width, enable_ccx, view_as_ccx): # of sql queries, # of mongo queries, # of xblocks
(
'no_overrides'
,
1
,
True
,
False
):
(
23
,
7
,
14
),
(
'no_overrides'
,
2
,
True
,
False
):
(
68
,
7
,
85
),
(
'no_overrides'
,
3
,
True
,
False
):
(
263
,
7
,
336
),
(
'ccx'
,
1
,
True
,
False
):
(
23
,
7
,
14
),
(
'ccx'
,
2
,
True
,
False
):
(
68
,
7
,
85
),
(
'ccx'
,
3
,
True
,
False
):
(
263
,
7
,
336
),
(
'ccx'
,
1
,
True
,
True
):
(
23
,
7
,
14
),
(
'ccx'
,
2
,
True
,
True
):
(
68
,
7
,
85
),
(
'ccx'
,
3
,
True
,
True
):
(
263
,
7
,
336
),
(
'no_overrides'
,
1
,
False
,
False
):
(
23
,
7
,
14
),
(
'no_overrides'
,
2
,
False
,
False
):
(
68
,
7
,
85
),
(
'no_overrides'
,
3
,
False
,
False
):
(
263
,
7
,
336
),
(
'ccx'
,
1
,
False
,
False
):
(
23
,
7
,
14
),
(
'ccx'
,
2
,
False
,
False
):
(
68
,
7
,
85
),
(
'ccx'
,
3
,
False
,
False
):
(
263
,
7
,
336
),
(
'ccx'
,
1
,
False
,
True
):
(
23
,
7
,
14
),
(
'ccx'
,
2
,
False
,
True
):
(
68
,
7
,
85
),
(
'ccx'
,
3
,
False
,
True
):
(
263
,
7
,
336
),
}
...
...
@@ -200,16 +244,22 @@ class TestFieldOverrideSplitPerformance(FieldOverridePerformanceTestCase):
__test__
=
True
TEST_DATA
=
{
(
'no_overrides'
,
1
,
True
):
(
23
,
4
,
9
),
(
'no_overrides'
,
2
,
True
):
(
68
,
19
,
54
),
(
'no_overrides'
,
3
,
True
):
(
263
,
84
,
215
),
(
'ccx'
,
1
,
True
):
(
23
,
4
,
9
),
(
'ccx'
,
2
,
True
):
(
68
,
19
,
54
),
(
'ccx'
,
3
,
True
):
(
263
,
84
,
215
),
(
'no_overrides'
,
1
,
False
):
(
23
,
4
,
9
),
(
'no_overrides'
,
2
,
False
):
(
68
,
19
,
54
),
(
'no_overrides'
,
3
,
False
):
(
263
,
84
,
215
),
(
'ccx'
,
1
,
False
):
(
23
,
4
,
9
),
(
'ccx'
,
2
,
False
):
(
68
,
19
,
54
),
(
'ccx'
,
3
,
False
):
(
263
,
84
,
215
),
(
'no_overrides'
,
1
,
True
,
False
):
(
23
,
4
,
9
),
(
'no_overrides'
,
2
,
True
,
False
):
(
68
,
19
,
54
),
(
'no_overrides'
,
3
,
True
,
False
):
(
263
,
84
,
215
),
(
'ccx'
,
1
,
True
,
False
):
(
23
,
4
,
9
),
(
'ccx'
,
2
,
True
,
False
):
(
68
,
19
,
54
),
(
'ccx'
,
3
,
True
,
False
):
(
263
,
84
,
215
),
(
'ccx'
,
1
,
True
,
True
):
(
33
,
4
,
13
),
(
'ccx'
,
2
,
True
,
True
):
(
68
,
19
,
84
),
(
'ccx'
,
3
,
True
,
True
):
(
263
,
84
,
335
),
(
'no_overrides'
,
1
,
False
,
False
):
(
23
,
4
,
9
),
(
'no_overrides'
,
2
,
False
,
False
):
(
68
,
19
,
54
),
(
'no_overrides'
,
3
,
False
,
False
):
(
263
,
84
,
215
),
(
'ccx'
,
1
,
False
,
False
):
(
23
,
4
,
9
),
(
'ccx'
,
2
,
False
,
False
):
(
68
,
19
,
54
),
(
'ccx'
,
3
,
False
,
False
):
(
263
,
84
,
215
),
(
'ccx'
,
1
,
False
,
True
):
(
23
,
4
,
9
),
(
'ccx'
,
2
,
False
,
True
):
(
68
,
19
,
54
),
(
'ccx'
,
3
,
False
,
True
):
(
263
,
84
,
215
),
}
lms/djangoapps/ccx/tests/test_overrides.py
View file @
63ddbd9b
...
...
@@ -9,6 +9,7 @@ from nose.plugins.attrib import attr
from
courseware.field_overrides
import
OverrideFieldData
# pylint: disable=import-error
from
django.test.utils
import
override_settings
from
request_cache.middleware
import
RequestCache
from
student.tests.factories
import
AdminFactory
# pylint: disable=import-error
from
xmodule.modulestore.tests.django_utils
import
(
ModuleStoreTestCase
,
...
...
@@ -66,6 +67,8 @@ class TestFieldOverrides(ModuleStoreTestCase):
get_ccx
.
return_value
=
ccx
self
.
addCleanup
(
patch
.
stop
)
self
.
addCleanup
(
RequestCache
.
clear_request_cache
)
# Apparently the test harness doesn't use LmsFieldStorage, and I'm not
# sure if there's a way to poke the test harness to do so. So, we'll
# just inject the override field storage in this brute force manner.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment