From patchwork Mon Mar 10 00:39:43 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerry DeLisle X-Patchwork-Id: 328436 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 0E8DB2C00D3 for ; Mon, 10 Mar 2014 11:40:07 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:content-type; q=dns; s=default; b=AK0y109wl4h1e+ydb8qneCBpqVy6RD0q004TSJLD4+i XE5DKPFn2A2thN6W1gVGroWjhfwi/uE/Nl32s+2gP7M1+43MTL7nz7slHQ5GTo6b aExReR2Ifg7AmTIDZMcx94goZ6afwbtUJySGgN05oC8RALGoFRIv7tLpBPTZhuuE = DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:content-type; s=default; bh=MWp7iGARna2c6BGQVcMbPQbFX4E=; b=mmbAWP5BRvDZ37kTo HQS5vghzsenkQqPefPfSGpQkXPgVlif2MqQefwwOREWwCQmK3Lt+ApgEPgkhH63O C48iLnQZUUEsNwaeDon+mYRntdGs+IAJVhHWBCr/d+bf5TMHyYprEfOXPtNkWqHJ eDOkrv8IL/NCeLwwZx3qMHUW8k= Received: (qmail 6301 invoked by alias); 10 Mar 2014 00:39:54 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 6278 invoked by uid 89); 10 Mar 2014 00:39:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mta41.charter.net Received: from mta41.charter.net (HELO mta41.charter.net) (216.33.127.83) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 10 Mar 2014 00:39:50 +0000 Received: from imp09 ([10.20.200.9]) by mta41.charter.net (InterMail vM.8.01.05.02 201-2260-151-103-20110920) with ESMTP id <20140310003948.XMNZ21087.mta41.charter.net@imp09>; Sun, 9 Mar 2014 20:39:48 -0400 Received: from pavilion.localdomain ([68.5.43.244]) by imp09 with smtp.charter.net id bcfn1n00T5G55b005cfovD; Sun, 09 Mar 2014 20:39:48 -0400 X-Authority-Analysis: v=2.0 cv=TOkd0CZa c=1 sm=1 a=mw+G4YjGptsaRR05zBLClw==:17 a=cs1xLa0W9aIA:10 a=ugd2PDcsxy0A:10 a=yUnIBFQkZM0A:10 a=hOpmn2quAAAA:8 a=Zn5-cPFKisGAfCS1vdgA:9 a=wPNLvfGTeEIA:10 a=jFZZCWOWDLWjklYf0HMA:9 a=OBHM6s6KHMt-5CSw:21 a=Q4H64Okbq1Y0qCUr:21 a=mw+G4YjGptsaRR05zBLClw==:117 X-Auth-id: anZkZWxpc2xlQGNoYXJ0ZXIubmV0 Message-ID: <531D09CF.708@charter.net> Date: Sun, 09 Mar 2014 17:39:43 -0700 From: Jerry DeLisle User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.3.0 MIME-Version: 1.0 To: gfortran CC: gcc patches Subject: [patch, libfortran] [4.7/4.8/4.9 Regression] PR38199 missed optimization: I/O performance Hi all, This final patch does two things. First: In read.c it implements a simple space skipping scheme in read_decimal where I found a lot of repeated next_char calls happening. This gives a pretty good boost in performance and is applicable in general for reading integers. Second: I have taken Thomas idea of using LEN_TRIM in unit.c revised it to work on formatted READ. I tried to document the code with comments. There are certain conditions for which one can not shorten the string length for internal units. For arrays of characters you can not do this for strings more than rank 1 and stride 1. Also, you can not do this any time a BLANK='zero' is being used. I also skip the optimization if there is any BLANK= specified in the READ. Thats conservative. I could also test for BLANK='NULL' in the DTP structure. I will probably do that later. I have added a helper function which tests for the BZ within a format string when a format string is present. I also check to see if the UNIT has had the BLANK status set. The optimization is skipped for these conditions. So what are the results? For the case in comment 29 of the PR which was the last case to be worked out: Size: NoPatch Patch: 100000 7.48 .312 50000 3.65 .152 25000 2.07 .085 12000 1.00 .054 6000 .513 .036 3000 .255 .029 1500 .143 .028 750 .082 .026 300 .047 .025 150 .032 .024 75 .026 .022 50 .023 .021 Where Size is the size of the buffer string and format specifier in the read. Times are in seconds. I was thinking that at some string size we could just skip the optimization altogether to avoid the overhead on smaller strings. Maybe strings less then 50 bytes long. Regression tested on X86-64-Gnu-Linux. No new test case needed. OK for trunk? Regards, Jerry 2014-03-08 Jerry DeLisle PR libfortran/38199 Index: read.c =================================================================== --- read.c (revision 208303) +++ read.c (working copy) @@ -677,7 +677,13 @@ read_decimal (st_parameter_dt *dtp, const fnode *f if (c == ' ') { - if (dtp->u.p.blank_status == BLANK_NULL) continue; + if (dtp->u.p.blank_status == BLANK_NULL) + { + /* Skip spaces. */ + for ( ; w > 0; p++, w--) + if (*p != ' ') break; + continue; + } if (dtp->u.p.blank_status == BLANK_ZERO) c = '0'; } Index: unit.c =================================================================== --- unit.c (revision 208303) +++ unit.c (working copy) @@ -375,6 +375,25 @@ find_or_create_unit (int n) } +/* Helper function to test for BZ (Blank Zero) in format string. This + is used for optimization. You can't trim out blanks if they have + significance. */ +static bool +is_BZ (st_parameter_dt *dtp) +{ + if (dtp->common.flags & IOPARM_DT_HAS_FORMAT) + { + char *p = dtp->format; + off_t i; + for (i = 0; i < dtp->format_len; i++) + if (p[i] == 'b' || p[i] == 'B') + if (p[i+1] == 'z' || p[i+1] == 'Z') + return true; + } + return false; +} + + gfc_unit * get_internal_unit (st_parameter_dt *dtp) { @@ -402,6 +421,33 @@ get_internal_unit (st_parameter_dt *dtp) some other file I/O unit. */ iunit->unit_number = -1; + /* As an optimization, adjust the unit record length to not + include trailing blanks. This will not work under certain conditions + where trailing blanks have significance. */ + if (dtp->u.p.mode == READING && !dtp->u.p.ionml + && !(dtp->internal_unit_desc + && (GFC_DESCRIPTOR_RANK (dtp->internal_unit_desc) > 1 + || GFC_DESCRIPTOR_STRIDE(dtp->internal_unit_desc, 0) != 1)) + && !is_BZ (dtp) && dtp->blank_len == 0) + { + if (dtp->common.unit == 0) + { + int tmp = string_len_trim (dtp->internal_unit_len, + dtp->internal_unit); + if (tmp > 0) + dtp->internal_unit_len = tmp; + iunit->recl = dtp->internal_unit_len; + } + else + { + int tmp = string_len_trim_char4 (dtp->internal_unit_len, + (const gfc_char4_t*) dtp->internal_unit); + if (tmp > 0) + dtp->internal_unit_len = tmp; + iunit->recl = dtp->internal_unit_len; + } + } + /* Set up the looping specification from the array descriptor, if any. */ if (is_array_io (dtp)) @@ -414,27 +460,6 @@ get_internal_unit (st_parameter_dt *dtp) start_record *= iunit->recl; } - else - { - /* If we are not processing an array, adjust the unit record length not - to include trailing blanks for list-formatted reads. */ - if (dtp->u.p.mode == READING && !(dtp->common.flags & IOPARM_DT_HAS_FORMAT)) - { - if (dtp->common.unit == 0) - { - dtp->internal_unit_len = - string_len_trim (dtp->internal_unit_len, dtp->internal_unit); - iunit->recl = dtp->internal_unit_len; - } - else - { - dtp->internal_unit_len = - string_len_trim_char4 (dtp->internal_unit_len, - (const gfc_char4_t*) dtp->internal_unit); - iunit->recl = dtp->internal_unit_len; - } - } - } /* Set initial values for unit parameters. */ if (dtp->common.unit)