Skip to content

Commit b326a21

Browse files
authored
Merge pull request #6815 from readthedocs/humitos/use-mamba-for-conda-environment
2 parents 702f9a3 + 29d8657 commit b326a21

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

docs/guides/feature-flags.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ In case you prefer to use the latest ``conda`` version available, this is the fl
2727
Makes Read the Docs to install all the requirements at once on ``conda create`` step.
2828
This helps users to pin dependencies on conda and to improve build time.
2929

30+
``CONDA_USES_MAMBA``: :featureflags:`CONDA_USES_MAMBA`
31+
32+
``conda`` solver consumes 1Gb minimum when installing any package using ``conda-forge`` channel.
33+
This seems to be `a known issue`_ due conda forge has so many packages on it, among others.
34+
Using this feature flag allows you to use mamba_ instead of ``conda`` to create the environment
35+
and install the dependencies.
36+
``mamba`` is a drop-in replacement for conda that it's much faster and also
37+
reduces considerably the amount of memory required to solve the dependencies.
38+
39+
.. _mamba: https://quantstack.net/mamba.html
40+
.. _a known issue: https://www.anaconda.com/understanding-and-improving-condas-performance/
41+
3042
``DONT_OVERWRITE_SPHINX_CONTEXT``: :featureflags:`DONT_OVERWRITE_SPHINX_CONTEXT`
3143

3244
``DONT_SHALLOW_CLONE``: :featureflags:`DONT_SHALLOW_CLONE`

readthedocs/doc_builder/python_environments.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,23 @@ class Conda(PythonEnvironment):
484484
def venv_path(self):
485485
return os.path.join(self.project.doc_path, 'conda', self.version.slug)
486486

487+
def conda_bin_name(self):
488+
"""
489+
Decide whether use ``mamba`` or ``conda`` to create the environment.
490+
491+
Return ``mamba`` if the project has ``CONDA_USES_MAMBA`` feature and
492+
``conda`` otherwise. This will be the executable name to be used when
493+
creating the conda environment.
494+
495+
``mamba`` is really fast to solve dependencies and download channel
496+
metadata on startup.
497+
498+
See https://github.com/QuantStack/mamba
499+
"""
500+
if self.project.has_feature(Feature.CONDA_USES_MAMBA):
501+
return 'mamba'
502+
return 'conda'
503+
487504
def _update_conda_startup(self):
488505
"""
489506
Update ``conda`` before use it for the first time.
@@ -492,6 +509,8 @@ def _update_conda_startup(self):
492509
independently the version of Miniconda that it has installed.
493510
"""
494511
self.build_env.run(
512+
# TODO: use ``self.conda_bin_name()`` once ``mamba`` is installed in
513+
# the Docker image
495514
'conda',
496515
'update',
497516
'--yes',
@@ -502,6 +521,18 @@ def _update_conda_startup(self):
502521
cwd=self.checkout_path,
503522
)
504523

524+
def _install_mamba(self):
525+
self.build_env.run(
526+
'conda',
527+
'install',
528+
'--yes',
529+
'--quiet',
530+
'--name=base',
531+
'--channel=conda-forge',
532+
'mamba',
533+
cwd=self.checkout_path,
534+
)
535+
505536
def setup_base(self):
506537
conda_env_path = os.path.join(self.project.doc_path, 'conda')
507538
version_path = os.path.join(conda_env_path, self.version.slug)
@@ -525,8 +556,12 @@ def setup_base(self):
525556
self._append_core_requirements()
526557
self._show_environment_yaml()
527558

559+
# TODO: remove it when ``mamba`` is installed in the Docker image
560+
if self.project.has_feature(Feature.CONDA_USES_MAMBA):
561+
self._install_mamba()
562+
528563
self.build_env.run(
529-
'conda',
564+
self.conda_bin_name(),
530565
'env',
531566
'create',
532567
'--quiet',
@@ -612,6 +647,9 @@ def _get_core_requirements(self):
612647
'pillow',
613648
]
614649

650+
if self.project.has_feature(Feature.CONDA_USES_MAMBA):
651+
conda_requirements.append('pip')
652+
615653
# Install pip-only things.
616654
pip_requirements = [
617655
'recommonmark',
@@ -639,7 +677,7 @@ def install_core_requirements(self):
639677
# Install requirements via ``conda install`` command if they were
640678
# not appended to the ``environment.yml`` file.
641679
cmd = [
642-
'conda',
680+
self.conda_bin_name(),
643681
'install',
644682
'--yes',
645683
'--quiet',

readthedocs/projects/models.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,7 @@ def add_features(sender, **kwargs):
15781578
EXTERNAL_VERSION_BUILD = 'external_version_build'
15791579
UPDATE_CONDA_STARTUP = 'update_conda_startup'
15801580
CONDA_APPEND_CORE_REQUIREMENTS = 'conda_append_core_requirements'
1581+
CONDA_USES_MAMBA = 'conda_uses_mamba'
15811582
ALL_VERSIONS_IN_HTML_CONTEXT = 'all_versions_in_html_context'
15821583
SKIP_SYNC_TAGS = 'skip_sync_tags'
15831584
SKIP_SYNC_BRANCHES = 'skip_sync_branches'
@@ -1659,6 +1660,10 @@ def add_features(sender, **kwargs):
16591660
CONDA_APPEND_CORE_REQUIREMENTS,
16601661
_('Append Read the Docs core requirements to environment.yml file'),
16611662
),
1663+
(
1664+
CONDA_USES_MAMBA,
1665+
_('Uses mamba binary instead of conda to create the environment'),
1666+
),
16621667
(
16631668
ALL_VERSIONS_IN_HTML_CONTEXT,
16641669
_(

0 commit comments

Comments
 (0)