BQc@s>dZddlZddlmZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlmZddlmZddlmZddlmZddlmZdd lmZdd lmZdd lmZdd lmZdd lmZddlmZddlm Z ddl!m"Z"ddl!m#Z#ddl!m$Z$ddl!m%Z%ddl!m&Z&ddl!m'Z'ddl(m)Z)ddl(m*Z*ddl(m+Z+ddl(m,Z,dZ-defdYZ.dS(s%Contains the perfdiag gsutil command.iN(t defaultdict(tCommand(t COMMAND_NAME(tCOMMAND_NAME_ALIASES(tCONFIG_REQUIRED(t FILE_URIS_OK(tMAX_ARGS(tMIN_ARGS(tPROVIDER_URIS_OK(tSUPPORTED_SUB_ARGS(tURIS_START_ARG(tconfig(tCommandException(t HELP_NAME(tHELP_NAME_ALIASES(tHELP_ONE_LINE_SUMMARY(t HELP_TEXT(t HELP_TYPE(tHelpType(tIS_LINUX(tMakeBitsHumanReadable(tMakeHumanReadable(t Percentiles SYNOPSIS gsutil perfdiag [-i in.json] [-o out.json] [-n iterations] [-c concurrency] [-s size] [-t tests] uri... DESCRIPTION The perfdiag command runs a suite of diagnostic tests for a given Google Storage bucket. The 'uri' parameter must name an existing bucket (e.g. gs://foo) to which the user has write permission. Several test files will be uploaded to and downloaded from this bucket. All test files will be deleted at the completion of the diagnostic if it finishes successfully. gsutil performance can be impacted by many factors at the client, server, and in-between, such as: CPU speed; available memory; the access path to the local disk; network bandwidth; contention and error rates along the path between gsutil and Google; operating system buffering configuration; and firewalls and other network elements. The perfdiag command is provided so that customers can run a known measurement suite when troubleshooting performance problems. PROVIDING DIAGNOSTIC OUTPUT TO GOOGLE CLOUD STORAGE TEAM If the Google Cloud Storage Team asks you to run a performance diagnostic please use the following command, and email the output file (output.json) to gs-team@google.com: gsutil perfdiag -o output.json gs://your-bucket OPTIONS -n Sets the number of iterations performed when downloading and uploading files during latency and throughput tests. Defaults to 5. -c Sets the level of concurrency to use while running throughput experiments. The default value of 1 will only run a single read or write operation concurrently. -s Sets the size (in bytes) of the test file used to perform read and write throughput tests. The default is 1 MiB. -t Sets the list of diagnostic tests to perform. The default is to run all diagnostic tests. Must be a comma-separated list containing one or more of the following: lat: Runs N iterations (set with -n) of writing the file, retrieving its metadata, reading the file, and deleting the file. Records the latency of each operation. rthru: Runs N (set with -n) read operations, with at most C (set with -c) reads outstanding at any given time. wthru: Runs N (set with -n) write operations, with at most C (set with -c) writes outstanding at any given time. -o Writes the results of the diagnostic to an output file. The output is a JSON file containing system information and performance diagnostic results. The file can be read and reported later using the -i option. -i Reads the JSON output file created using the -o command and prints a formatted description of the results. NOTE The perfdiag command collects system information. It collects your IP address, executes DNS queries to Google servers and collects the results, and collects network statistics information from the output of netstat -s. None of this information will be sent to Google unless you choose to send it. tPerfDiagCommandcBs`eZdZi de6ddddge6de6de6de6ee 6ee 6de 6e e 6Zide6ge6eje6d e6ee6Zd!Zd"ZejjjjZe dZ e eedZ!e eedZ"dZ#dZ$e%j&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.dZ/dZ0dZ1d Z2RS(#s*Implementation of gsutil perfdiag command.tperfdiagtdiagt diagnostictperft performanceiis n:c:s:t:i:o:sRun performance diagnosticiiitrthrutwthrutlatc Cs<|jrdG|GHnttjd}d}g}xt|sN||kr7xft||kr|t||krddj|GHtj|d|d|}|j|qQW|} g}xn| D]f}|j } | d kr|j|q|r&| r&t d| dj|fq|d 7}qWq6Wd S( sExecutes a command n times with a window size of w. Up to w instances of the command will be executed and left outstanding at a time until n instances of the command have completed. Args: cmd: List containing the command to execute. n: Number of times the command will be executed. w: Window size of outstanding commands being executed. raise_on_error: See _Exec. Raises: Exception: If raise_on_error is set to True and any process exits with a non-zero return code. sRunning command:twisStarting concurrent command: %st tstdouttstderrs8Received non-zero return code (%d) from subprocess '%s'.iN( tdebugtopentostdevnulltlentjoint subprocesstPopentappendtpolltNoneR ( tselftcmdtnR traise_on_errort devnull_ft num_finishedtrunningtpt prev_runningtretcode((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pyt _WindowedExecs(  +    c Cs|jrdG|GHn|r$tjnd}tj|dtjd|}|j\}}|r|jrtd|jdj|fn|r|S|jS(sExecutes a command in a subprocess. Args: cmd: List containing the command to execute. raise_on_error: Whether or not to raise an exception when a process exits with a non-zero return code. return_output: If set to True, the return value of the function is the stdout of the process. mute_stderr: If set to True, the stderr of the process is not printed to the console. Returns: The return code of the process or the stdout if return_output is set. Raises: Exception: If raise_on_error is set to True and any process exits with a non-zero return code. sRunning command:R"R#s8Received non-zero return code (%d) from subprocess '%s'.R!N( R$R*tPIPER.R+t communicatet returncodeR R)( R/R0R2t return_outputt mute_stderrR#R6t stdoutdatat stderrdata((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pyt_Execs  cCs,|j|}|j|d|d|d|S(sXExecutes a gsutil command in a subprocess. Args: cmd: A list containing the arguments to the gsutil program, e.g. ['ls', 'gs://foo']. raise_on_error: see _Exec. return_output: see _Exec. mute_stderr: see _Exec. Returns: The return code of the process or the stdout if return_output is set. R2R=R>(tgsutil_exec_listRA(R/R0R2R=R>((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pyt_GsUtils csi_g_i_i_fd}x-jD]"}||}jj|q=W|j_tj t j j j_ dS(s?Performs setup operations needed before diagnostics can be run.cstjdddddt\}}|j|qXqW|jd|jgdtdtdS(sDPerforms operations to clean things up after performing diagnostics.trmR2R>N( RZR]R&tremovetOSErrorRCRbRLtTrue(R/RV((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pyt _TearDown6s ccsH|GdGHtj}dVtj}||j|||GdGHdS(sA context manager that measures time. A context manager that prints a status message before and after executing the inner command and times how long the inner command takes. Keeps track of the timing, aggregated by the given key. Args: key: The key to insert the timing value into a dictionary bucket. bucket: A dictionary to place the timing value in. Yields: For the context manager. s starting...Nsdone.(ttimeR,(R/tkeytbuckettt0tt1((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pyt_TimeAs    c Cstt|jd}|j\}}}}|djr5|j|q5q5WWdQXi}tdd}x|D]}|jd } | \ }}}} }} } } }}}||krt| |} t||}t| } t| } t| } t|}| | | || |f||sssegments receivedspackets receivedcss$|]}|tjkr|VqdS(N(RR(RR((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pys sssegments send outs packets sents segments sentcss$|]}|tjkr|VqdS(N(RR(RR((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pys sttcp_retransmitt tcp_receivedttcp_sentN( RARgRLtstriptlowerR.RR)Rt ValueErrort TypeError(R/tnetstat_outputt found_tcpRRRRtresult((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pyt _GetTcpStatss>       c Csi}tjtj|d[^.]+)\.tgoogservtgoogserv_routet googserv_ipstgoogserv_hostnamess -type=TXTso-o.myaddr.google.com.stext\s+=\s+"(?P[\.\d]+)"tdnsips dns_o-o_ipt cpu_counttload_avgs /proc/meminfoRtMemTotalRcss$|]}|tjkr|VqdS(N(RR(RR((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pys PsitMemFreecss$|]}|tjkr|VqdS(N(RR(RR((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pys SstBufferscss$|]}|tjkr|VqdS(N(RR(RR((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pys VstCachedcss$|]}|tjkr|VqdS(N(RR(RR((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pys YsNt mem_totaltmem_freet mem_bufferst mem_cachedtmeminfot gsutil_configs tsysinfo('tsockett gethostbynamet gethostnameRJt gettempdirRitstrftimetgmtimetGOOGLE_API_HOSTRARgtretsearchtgroupR.tgethostbyname_ext gethostbyaddrR,tmultiprocessingRtNotImplementedErrorRrR&t getloadavgtAttributeErrorRfR%t startswithRR)tIOErrorRtdirR tgetattrtisuppert isinstancet basestringRY(R/RR0tnslookup_cname_outputtmthostnamet aliaslistt ipaddrlistt googserv_iptnslookup_txt_outputRRRRRWRtattrt attr_value((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pyt_CollectSysInfosx            cst|}tt||tjtfd|D|}t|jdGdGddjdGdGd|djdGdGdt|ddjd GdGdt|d djd GdGHd S( sAPrints out mean, standard deviation, median, and 90th percentile.c3s|]}|dVqdS(iN((Rtx(tmean(s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pys rsiRs%.1fii i g?i g?N(R(tfloattsumtmathtsqrtR^trjustR(R/ttrialsR1tstdev((Rs5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pyt _DisplayStatsns )"c$ CsaHddGHdjdGHddGHd|jkrHddGHdjdGHddGHdGHdGHxft|jdD]N}t|jd|}|jd \}}t|}|d krd jd Gd Gt|jd Gd G|j|n|dkr5djd Gd Gt|jd Gd G|j|n|dkrydjd Gd Gt|jd Gd G|j|n|dkrodjd Gd Gt|jd Gd G|j|qoqoWnd|jkrEHddGHdjdGHddGH|jd}dt|d|dt|dfGHdt|ddGHnd|jkrHddGHdjdGHddGH|jd}dt|d|dt|dfGHd t|ddGHnd!|jkrHddGHd"jdGHddGH|jd!}d#|d$GHd%|d&GHd'|jd(GHd)|kr|d)}dV} yt j |d*} Wnt k rrnX| rt j| } tjj| } d+| jd,GHqnd-|d.GHd/d0j|d1GHd2d0j|d3GHd4|d5GHd6|d7GHd8|d9GHyJd:t|d;d<GHd=t|d;d>|d;d?|d;d@GHWntk ronX|dA} |dB} xOdXD]G}y-| dF|| dF|}dG||fGHWqtk rqXqWdH|krdI|krdJG|dH}|dI}d GdKjdLGx-dMdNdOdPdQdRgD]}|jdGq0WHxt|D]}||}||}|\}}}}}}|\}}}}} }!d G|jdLG||||||||| ||!|g}"x!|"D]}t|jdGqWHqUWqn|jr\t|jdS }#tj|j|#dTdUWdVQXHdW|jGHnHdVS(Ys/Displays results collected from diagnostic run.t=iNsDIAGNOSTIC RESULTSRot-tLatencysOOperation Size Trials Mean (ms) Std Dev (ms) Median (ms) 90th % (ms)sO========= ========= ====== ========= ============ =========== ===========RtMETADATAtMetadatai RtDOWNLOADtDownloadtUPLOADtUploadtDELETEtDeleteRsWrite Throughputs:Copied a %s file %d times for a total transfer size of %s.RTRRsWrite throughput: %s/s.RiRsRead ThroughputRsRead throughput: %s/s.RsSystem InformationsIP Address: %sRsTemporary Directory: %sRsBucket URI: %sR_Rs%a, %d %b %Y %H:%M:%S +0000sMeasurement time: %ss%Y-%m-%d %I-%M-%S %p %ZsGoogle Server: %sRs!Google Server IP Addresses: %ss RsGoogle Server Hostnames: %sRs#Google DNS thinks your IP is: %ss dns_o-o_ipsCPU Count: %sRsCPU Load Average: %sRsTotal Memory: %sRRsFree Memory: %sRRRt netstat_endt netstat_starttsenttreceivedt retransmitstcp_%ss!TCP segments %s during test: %dtdisk_counters_endtdisk_counters_startsDisk Counter Deltas: tdiskiRRRRRRR tindentiNsOutput file written to '%s'.(ssentRR(tcenterRYtsortedRRRRRRR.RitstrptimeRtcalendarttimegmtdatetimet fromtimestampRR)RR^t output_fileR%tjsontdump($R/RjRtoptnumbytest write_thrut read_thrutinfot ts_stringt timetuplet localtimetlocaldtt netstat_aftertnetstat_beforettcp_typetdeltat disk_aftert disk_beforetcolnametdisknametbeforetaftertreads1twrites1trbytes1twbytes1trtime1twtime1treads2twrites2trbytes2twbytes2trtime2twtime2tdeltasRW((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pyt_DisplayResultszs                                            cCsSy/t|}|dkr*t|n|SWntk rNt|nXdS(s^Tries to convert val argument to a positive integer. Args: val: The value (as a string) to convert to a positive integer. msg: The error message to place in the CommandException on an error. Returns: A valid positive integer. Raises: CommandException: If the supplied value is not a valid positive integer. iN(RR R(R/tvaltmsg((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pyt_ParsePositiveInteger s    cCs|d|_d|_d|_|j|_d|_d|_|jr x|jD]\}}|dkr||j |d|_n|dkr|j |d|_n|dkr|j |d |_n|d kr4g|_xX|j j d D]>}|j |jkrt d |n|jj|qWn|d krXtjj||_n|dkrLtjj||_tjj|jst d|ny=t|jd%}tj||_d|jGHWdQXWn!tk rt d|nXdSqLWn|js%t dn|jj|jd|_|jjsft d|jn|jj|_dS(s&Parses arguments for perfdiag command.iiis-ns,The -n parameter must be a positive integer.s-cs,The -c parameter must be a positive integer.s-ss,The -s parameter must be a positive integer.s-tt,s8List of test names (-t) contains invalid test name '%s'.s-os-isInvalid input file (-i): '%s'.RsRead input file: '%s'.Ns'Could not decode input file (-i): '%s'.s1Wrong number of arguments for "perfdiag" command.isOThe perfdiag command requires a URI that specifies a bucket. "%s" is not valid.(RtRR\tALL_DIAG_TESTSt diag_testsR.R t input_filetsub_optsR1RRRR R,R&R`tabspathtisfileR%R tloadRYRtargst suri_buildert StorageUriR_t names_buckett get_bucketRk(R/totat test_nameRW((s5/tmp/tmp.yUYbTOKr8o/gsutil/gslib/commands/perfdiag.pyt _ParseArgs"sZ                  cCsx|j|jr!|jdSd|jGHd|jGHd|jGHdt|jGHddj|j GHz|j |j |j |j dd sN              J