diff --git a/.travis/format.sh b/.travis/format.sh index e4c609a85..9313e6410 100755 --- a/.travis/format.sh +++ b/.travis/format.sh @@ -51,6 +51,11 @@ format_changed() { if ! git diff --diff-filter=ACM --quiet --exit-code "$MERGEBASE" -- '*.py' &>/dev/null; then git diff --name-only --diff-filter=ACM "$MERGEBASE" -- '*.py' | xargs -P 5 \ yapf --in-place "${YAPF_EXCLUDES[@]}" "${YAPF_FLAGS[@]}" + if which flake8 >/dev/null; then + git diff --name-only --diff-filter=ACM "$MERGEBASE" -- '*.py' | xargs -P 5 \ + flake8 --exclude=python/ray/core/generated/,doc/source/conf.py,python/ray/cloudpickle/ \ + --ignore=C408,E121,E123,E126,E226,E24,E704,W503,W504,W605 + fi fi if which clang-format >/dev/null; then diff --git a/.travis/install-dependencies.sh b/.travis/install-dependencies.sh index 31fbf18c8..e1db5ce97 100755 --- a/.travis/install-dependencies.sh +++ b/.travis/install-dependencies.sh @@ -25,7 +25,7 @@ if [[ "$PYTHON" == "2.7" ]] && [[ "$platform" == "linux" ]]; then bash miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" pip install -q cython==0.27.3 cmake tensorflow gym opencv-python pyyaml pandas==0.22 requests \ - feather-format lxml openpyxl xlrd py-spy + feather-format lxml openpyxl xlrd py-spy setproctitle elif [[ "$PYTHON" == "3.5" ]] && [[ "$platform" == "linux" ]]; then sudo apt-get update sudo apt-get install -y cmake pkg-config python-dev python-numpy build-essential autoconf curl libtool unzip @@ -34,7 +34,7 @@ elif [[ "$PYTHON" == "3.5" ]] && [[ "$platform" == "linux" ]]; then bash miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" pip install -q cython==0.27.3 cmake tensorflow gym opencv-python pyyaml pandas==0.22 requests \ - feather-format lxml openpyxl xlrd py-spy + feather-format lxml openpyxl xlrd py-spy setproctitle elif [[ "$PYTHON" == "2.7" ]] && [[ "$platform" == "macosx" ]]; then # check that brew is installed which -s brew @@ -51,7 +51,7 @@ elif [[ "$PYTHON" == "2.7" ]] && [[ "$platform" == "macosx" ]]; then bash miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" pip install -q cython==0.27.3 cmake tensorflow gym opencv-python pyyaml pandas==0.22 requests \ - feather-format lxml openpyxl xlrd py-spy + feather-format lxml openpyxl xlrd py-spy setproctitle elif [[ "$PYTHON" == "3.5" ]] && [[ "$platform" == "macosx" ]]; then # check that brew is installed which -s brew @@ -68,7 +68,7 @@ elif [[ "$PYTHON" == "3.5" ]] && [[ "$platform" == "macosx" ]]; then bash miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" pip install -q cython==0.27.3 cmake tensorflow gym opencv-python pyyaml pandas==0.22 requests \ - feather-format lxml openpyxl xlrd py-spy + feather-format lxml openpyxl xlrd py-spy setproctitle elif [[ "$LINT" == "1" ]]; then sudo apt-get update sudo apt-get install -y cmake build-essential autoconf curl libtool unzip diff --git a/doc/requirements-doc.txt b/doc/requirements-doc.txt index 5d953d346..f598baa08 100644 --- a/doc/requirements-doc.txt +++ b/doc/requirements-doc.txt @@ -9,6 +9,7 @@ pyarrow pyyaml recommonmark redis +setproctitle sphinx sphinx-click sphinx_rtd_theme diff --git a/python/ray/rllib/test/test_policy_evaluator.py b/python/ray/rllib/test/test_policy_evaluator.py index 102a2a6c5..c99e24e97 100644 --- a/python/ray/rllib/test/test_policy_evaluator.py +++ b/python/ray/rllib/test/test_policy_evaluator.py @@ -165,11 +165,14 @@ class TestPolicyEvaluator(unittest.TestCase): }, }) pg.train() - self.assertEqual(counts["sample"], 1) + pg.train() + pg.train() + pg.train() + self.assertEqual(counts["sample"], 4) self.assertGreater(counts["start"], 0) self.assertGreater(counts["end"], 0) - self.assertGreater(counts["step"], 50) - self.assertLess(counts["step"], 100) + self.assertGreater(counts["step"], 200) + self.assertLess(counts["step"], 400) def testQueryEvaluators(self): register_env("test", lambda _: gym.make("CartPole-v0")) diff --git a/python/ray/scripts/scripts.py b/python/ray/scripts/scripts.py index 688fbb3ae..f5889d4b7 100644 --- a/python/ray/scripts/scripts.py +++ b/python/ray/scripts/scripts.py @@ -388,6 +388,12 @@ def stop(): "grep -v grep | awk '{ print $2 }') 2> /dev/null" ], shell=True) + subprocess.call( + [ + "kill -9 $(ps aux | grep ' ray_' | " + "grep -v grep | awk '{ print $2 }') 2> /dev/null" + ], + shell=True) # Find the PID of the Ray log monitor process and kill it. subprocess.call( @@ -591,7 +597,7 @@ export IFS=" # Call sudo to prompt for password before anything has been printed. sudo true workers=$( - ps aux | grep default_worker.py | grep -v grep | grep -v raylet/raylet + ps aux | grep ' ray_' | grep -v grep ) for worker in $workers; do echo "Stack dump for $worker"; diff --git a/python/ray/worker.py b/python/ray/worker.py index 53c3900c7..8b1d7e1c4 100644 --- a/python/ray/worker.py +++ b/python/ray/worker.py @@ -2,6 +2,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from contextlib import contextmanager import atexit import colorama import hashlib @@ -10,6 +11,7 @@ import logging import numpy as np import os import redis +import setproctitle import signal import sys import threading @@ -899,8 +901,15 @@ class Worker(object): "name": function_name, "task_id": task.task_id().hex() } + if task.actor_id().id() == NIL_ACTOR_ID: + title = "ray_worker:{}()".format(function_name) + else: + actor = self.actors[task.actor_id().id()] + title = "ray_{}:{}()".format(actor.__class__.__name__, + function_name) with profiling.profile("task", extra_data=extra_data, worker=self): - self._process_task(task, execution_info) + with _changeproctitle(title): + self._process_task(task, execution_info) # Increase the task execution counter. self.function_actor_manager.increase_task_counter( @@ -1844,6 +1853,7 @@ def connect(info, # Initialize some fields. if mode is WORKER_MODE: worker.worker_id = random_string() + setproctitle.setproctitle("ray_worker") else: # This is the code path of driver mode. if driver_id is None: @@ -2087,6 +2097,14 @@ def disconnect(worker=global_worker): worker.serialization_context_map.clear() +@contextmanager +def _changeproctitle(title): + old_title = setproctitle.getproctitle() + setproctitle.setproctitle(title) + yield + setproctitle.setproctitle(old_title) + + def _try_to_compute_deterministic_class_id(cls, depth=5): """Attempt to produce a deterministic class ID for a given class. diff --git a/python/setup.py b/python/setup.py index bd0ef97a6..1a5719e2d 100644 --- a/python/setup.py +++ b/python/setup.py @@ -151,6 +151,7 @@ setup( "pytest", "pyyaml", "redis", + "setproctitle", # The six module is required by pyarrow. "six >= 1.0.0", "flatbuffers" diff --git a/test/runtest.py b/test/runtest.py index bd87c66d6..681575a4b 100644 --- a/test/runtest.py +++ b/test/runtest.py @@ -4,6 +4,7 @@ from __future__ import print_function import os import re +import setproctitle import string import subprocess import sys @@ -2299,6 +2300,26 @@ def test_wait_reconstruction(shutdown_only): assert len(ready_ids) == 1 +def test_ray_setproctitle(shutdown_only): + ray.init(num_cpus=2) + + @ray.remote + class UniqueName(object): + def __init__(self): + assert setproctitle.getproctitle() == "ray_UniqueName:__init__()" + + def f(self): + assert setproctitle.getproctitle() == "ray_UniqueName:f()" + + @ray.remote + def unique_1(): + assert setproctitle.getproctitle() == "ray_worker:runtest.unique_1()" + + actor = UniqueName.remote() + ray.get(actor.f.remote()) + ray.get(unique_1.remote()) + + @pytest.mark.skipif( os.getenv("TRAVIS") is None, reason="This test should only be run on Travis.")