Skip to content

Commit 729030a

Browse files
authored
Merge pull request #32 from linkedin/remove-replay
temporarily removing 'replay' functionality.
2 parents 9a64ec7 + 60bb88a commit 729030a

File tree

3 files changed

+56
-90
lines changed

3 files changed

+56
-90
lines changed

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,10 @@ There are additional options that you can take advantage of. See below output:
5353
How many iterations of jstat to run before stopping
5454
-n, --no-jstat-output
5555
Do not show jstat output - only print summary
56-
-r [FILE], --replay [FILE]
57-
Replay a previously saved default is
58-
/tmp/jtune_data-{user}.bin.bz2 file
5956
-p PID, --pid PID Which java PID should I attach to
6057

6158
* You can also have it stop after X number of YGCs, FGCs, or jstat iterations (-y, -s, -c respectively). If you want it to make tuning suggestions, you'll want to let it run for at least 3 FGCs (-s <#>) before exiting.
6259
* There may be cases where you want jtune to optimize for a given number of CMS GCs, you can do this with the '-o #' parameter. Right now you can specify a range between 0 and 11 which corresponds to the 180 CMS/min to 1 CMS/min respectively. In most cases you can leave it as default. The way this parameter is used will likely change.
63-
* There may be cases where you see something odd in the suggestions, or want to save the data structures jtune used for further analysis. By default jtune saves this data in /tmp/jtune_data-{user}.bin.bz2. JTune can replay this file by passing it a -r \<path\> parameter.
6460

6561
Command Output
6662
--------------

jtune/jtune.py

Lines changed: 55 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"""
55
@author Eric Bullen <ebullen@linkedin.com>
66
@application jtune.py
7-
@version 2.0.3
7+
@version 3.0.0
88
@abstract This tool will give detailed information about the running
99
JVM in real-time. It produces useful information that can
1010
further assist the user in debugging and optimization.
@@ -26,7 +26,6 @@
2626
import logging
2727
import math
2828
import os
29-
import pickle
3029
import re
3130
import resource
3231
import shlex
@@ -459,7 +458,7 @@ def reduce_k(size=None, precision=2, short_form=True, _place_holder=0):
459458
return "{0} {1}".format(value, iec_scale[_place_holder])
460459

461460

462-
def _run_analysis(gc_data=None, jmap_data=None, jstat_data=None, proc_details=None, replay_file=None, optimized_for_ygcs_rate=None):
461+
def _run_analysis(gc_data=None, jmap_data=None, jstat_data=None, proc_details=None, optimized_for_ygcs_rate=None):
463462
"""The meat-and-potatoes of this tool. This takes in numerous data structures,
464463
and prints out a report of the analysis of them."""
465464

@@ -1676,7 +1675,7 @@ def _get_widths(jstat_data=None, short_fields=False):
16761675
return widths
16771676

16781677

1679-
def _at_exit(raw_gc_log=None, jmap_data=None, jstat_data=None, proc_details=None, replay_file=None, optimized_for_ygcs_rate=None):
1678+
def _at_exit(raw_gc_log=None, jmap_data=None, jstat_data=None, proc_details=None, optimized_for_ygcs_rate=None):
16801679
"""The exit function that is called when the user presses ctrl-c, or when it exits after X number
16811680
of jstat iterations. It calls various functions to display useful information to the end-user."""
16821681

@@ -1728,7 +1727,7 @@ def _at_exit(raw_gc_log=None, jmap_data=None, jstat_data=None, proc_details=None
17281727
if in_stanza:
17291728
entry.append(line)
17301729

1731-
_run_analysis(gc_data, jmap_data, jstat_data, proc_details, replay_file, optimized_for_ygcs_rate)
1730+
_run_analysis(gc_data, jmap_data, jstat_data, proc_details, optimized_for_ygcs_rate)
17321731

17331732

17341733
def get_rotated_log_file(gc_log_file):
@@ -1808,25 +1807,18 @@ def main():
18081807
else:
18091808
group = parser.add_mutually_exclusive_group(required=True)
18101809

1811-
group.add_argument('-r', '--replay', dest="replay_file", const="/tmp/jtune_data-{0}.bin.bz2".format(user), help="Replay a previously saved default is /tmp/jtune_data-{0}.bin.bz2 file".format(user), metavar="FILE", nargs="?", default=None)
18121810
group.add_argument('-p', '--pid', help='Which java PID should I attach to', type=int)
18131811
group.add_argument('--gc-stdin', help='Read GC log data from stdin', action="store_true")
18141812

18151813
cmd_args = parser.parse_args()
18161814

1817-
replay_file = cmd_args.replay_file
18181815
raw_gc_log_data = list()
18191816
jmap_data = list()
18201817
jstat_data = list()
18211818
proc_details = list()
18221819

1823-
if DEBUG:
1824-
# Need to define it here for Pycharm (so I don't
1825-
# have to set up arguments).
1826-
replay_file = "/tmp/some_file"
1827-
1828-
if not (cmd_args.pid or cmd_args.gc_stdin) and not os.path.isfile(replay_file):
1829-
logger.error("The replay file '{0}' does not exist, or is not a file.".format(replay_file))
1820+
if not (cmd_args.pid or cmd_args.gc_stdin):
1821+
logger.error("Please specify -p (pid) or --gc-stdin")
18301822
sys.exit(1)
18311823

18321824
# A ygc of 1/min
@@ -1853,96 +1845,74 @@ def main():
18531845
logger.error("You must specify -s, -y, or -c arguments for this option to work.")
18541846
sys.exit(1)
18551847

1856-
if replay_file:
1848+
if not cmd_args.gc_stdin:
18571849
try:
1858-
with open(replay_file, "rb") as _file:
1859-
proc_details, jstat_data, display.display_output, jmap_data, raw_gc_log_data = pickle.loads(_file.read().decode('bz2'))
1860-
except (ValueError, IOError):
1861-
logger.error("I was not able to read the replay file. Exiting.")
1862-
sys.exit(1)
1863-
else:
1864-
print "* Note: Used cached data found in {0}.".format(replay_file)
1865-
else:
1866-
if not cmd_args.gc_stdin:
1867-
try:
1868-
config_error = False
1869-
proc_details = get_proc_info(cmd_args.pid)
1870-
1871-
java_path, proc_uptime = proc_details['java_path'], proc_details['proc_uptime_seconds']
1850+
config_error = False
1851+
proc_details = get_proc_info(cmd_args.pid)
18721852

1873-
if proc_details.get("min_heap_size", 0) != proc_details.get("max_heap_size", 1):
1874-
config_error = True
1875-
logger.error(
1876-
"It looks like either you didn't specify your min and max heap size (-Xms & -Xmx respectively), or they are set to two different sizes. They need to be set to the same for jtune.py to work properly.")
1853+
java_path, proc_uptime = proc_details['java_path'], proc_details['proc_uptime_seconds']
18771854

1878-
if not proc_details.get("print_gc_date_stamps", False):
1879-
config_error = True
1880-
logger.error("You need to include the '-XX:PrintGCDateStamps' option to the JVM for JTune to work correctly.")
1855+
if proc_details.get("min_heap_size", 0) != proc_details.get("max_heap_size", 1):
1856+
config_error = True
1857+
logger.error(
1858+
"It looks like either you didn't specify your min and max heap size (-Xms & -Xmx respectively), or they are set to two different sizes. They need to be set to the same for jtune.py to work properly.")
18811859

1882-
if not proc_details.get("print_gc_details", False):
1883-
config_error = True
1884-
logger.error("You need to include the '-XX:PrintGCDetails' option to the JVM for JTune to work correctly.")
1860+
if not proc_details.get("print_gc_date_stamps", False):
1861+
config_error = True
1862+
logger.error("You need to include the '-XX:PrintGCDateStamps' option to the JVM for JTune to work correctly.")
18851863

1886-
if not proc_details.get("print_tenuring_distribution", False):
1887-
config_error = True
1888-
logger.error("You need to include the '-XX:+PrintTenuringDistribution' option to the JVM for JTune to work correctly.")
1864+
if not proc_details.get("print_gc_details", False):
1865+
config_error = True
1866+
logger.error("You need to include the '-XX:PrintGCDetails' option to the JVM for JTune to work correctly.")
18891867

1890-
if not proc_details.get("survivor_ratio", False):
1891-
logger.warning("You probably want to include the '-XX:SurvivorRatio=<num>' option to the JVM for JTune to work correctly.")
1868+
if not proc_details.get("print_tenuring_distribution", False):
1869+
config_error = True
1870+
logger.error("You need to include the '-XX:+PrintTenuringDistribution' option to the JVM for JTune to work correctly.")
18921871

1893-
if not proc_details.get("use_cms", False):
1894-
config_error = True
1895-
logger.error("You need to include the '-XX:+UseConcMarkSweepGC' option to the JVM for JTune to work correctly.")
1872+
if not proc_details.get("survivor_ratio", False):
1873+
logger.warning("You probably want to include the '-XX:SurvivorRatio=<num>' option to the JVM for JTune to work correctly.")
18961874

1897-
if not proc_details.get("use_parnew", False):
1898-
config_error = True
1899-
logger.error("You need to include the '-XX:+UseParNewGC' option to the JVM for JTune to work correctly.")
1875+
if not proc_details.get("use_cms", False):
1876+
config_error = True
1877+
logger.error("You need to include the '-XX:+UseConcMarkSweepGC' option to the JVM for JTune to work correctly.")
19001878

1901-
if config_error:
1902-
logger.error("Exiting.")
1903-
sys.exit(1)
1879+
if not proc_details.get("use_parnew", False):
1880+
config_error = True
1881+
logger.error("You need to include the '-XX:+UseParNewGC' option to the JVM for JTune to work correctly.")
19041882

1905-
except (TypeError, KeyError):
1906-
logger.error("I was not able to get the process data for pid {0}".format(cmd_args.pid))
1883+
if config_error:
1884+
logger.error("Exiting.")
19071885
sys.exit(1)
19081886

1909-
###########################################
1910-
# Start the gc log watching in a subprocess
1911-
back_secs = 300
1912-
gc_log_file = get_gc_log_file(proc_details)
1887+
except (TypeError, KeyError):
1888+
logger.error("I was not able to get the process data for pid {0}".format(cmd_args.pid))
1889+
sys.exit(1)
19131890

1914-
if not gc_log_file:
1915-
logger.error("\n".join(textwrap.wrap("I was not able to find a GC log for this process. Is the instance up?", display.textwrap_offset)))
1916-
sys.exit(1)
1891+
###########################################
1892+
# Start the gc log watching in a subprocess
1893+
back_secs = 300
1894+
gc_log_file = get_gc_log_file(proc_details)
19171895

1918-
####################################################
1919-
# Get the file offset before starting jstat, so
1920-
# I can use it after jstat runs to read the log file
1921-
gc_log_file_pos = os.stat(gc_log_file).st_size
1896+
if not gc_log_file:
1897+
logger.error("\n".join(textwrap.wrap("I was not able to find a GC log for this process. Is the instance up?", display.textwrap_offset)))
1898+
sys.exit(1)
19221899

1923-
jmap_data = get_jmap_data(cmd_args.pid, proc_details)
1900+
####################################################
1901+
# Get the file offset before starting jstat, so
1902+
# I can use it after jstat runs to read the log file
1903+
gc_log_file_pos = os.stat(gc_log_file).st_size
19241904

1925-
if cmd_args.no_jstat_output:
1926-
jstat_data = dict()
1927-
else:
1928-
jstat_data = run_jstat(cmd_args.pid, java_path, cmd_args.no_jstat_output, cmd_args.fgc_stop_count, cmd_args.stop_count, cmd_args.ygc_stop_count)
1905+
jmap_data = get_jmap_data(cmd_args.pid, proc_details)
19291906

1930-
# This basically hits after the user ctrl-c's
1931-
raw_gc_log_data = process_gclog(gc_log_file, gc_log_file_pos)
1907+
if cmd_args.no_jstat_output:
1908+
jstat_data = dict()
1909+
else:
1910+
jstat_data = run_jstat(cmd_args.pid, java_path, cmd_args.no_jstat_output, cmd_args.fgc_stop_count, cmd_args.stop_count, cmd_args.ygc_stop_count)
19321911

1933-
#####################################################
1934-
# Keep the last dump of data in case there's an issue
1935-
try:
1936-
with open("/tmp/jtune_data-{0}.bin.bz2".format(user), "wb") as _file:
1937-
os.chmod("/tmp/jtune_data-{0}.bin.bz2".format(user), 0666)
1938-
_file.write(pickle.dumps((proc_details, jstat_data, display.display_output, jmap_data, raw_gc_log_data), pickle.HIGHEST_PROTOCOL).encode('bz2'))
1939-
except IOError as msg:
1940-
logger.error("\n".join(textwrap.wrap("I was not able to write to /tmp/jtune_data-{0}.bin.bz2 (no saving of state): {1}".format(user, msg), display.textwrap_offset)))
1912+
# This basically hits after the user ctrl-c's
1913+
raw_gc_log_data = process_gclog(gc_log_file, gc_log_file_pos)
19411914

1942-
if DEBUG:
1943-
_at_exit(raw_gc_log_data, jmap_data, jstat_data, proc_details, replay_file, optimized_for_ygcs_rate)
1944-
else:
1945-
atexit.register(_at_exit, raw_gc_log_data, jmap_data, jstat_data, proc_details, replay_file, optimized_for_ygcs_rate)
1915+
atexit.register(_at_exit, raw_gc_log_data, jmap_data, jstat_data, proc_details, optimized_for_ygcs_rate)
19461916

19471917

19481918
if __name__ == '__main__':

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
setup(
1414
name='jtune',
15-
version='2.0.3',
15+
version='3.0.0',
1616
description=description,
1717
long_description=description,
1818
url='https://github.com/linkedin/JTune',

0 commit comments

Comments
 (0)