X-Loop: help-debbugs@HIDDEN Subject: bug#32099: New uniq option for speed Resent-From: "Kingsley G. Morse Jr." <kingsley@HIDDEN> Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> Resent-CC: bug-coreutils@HIDDEN Resent-Date: Sun, 08 Jul 2018 22:22:01 +0000 Resent-Message-ID: <handler.32099.B.153108848723887 <at> debbugs.gnu.org> Resent-Sender: help-debbugs@HIDDEN X-GNU-PR-Message: report 32099 X-GNU-PR-Package: coreutils X-GNU-PR-Keywords: To: 32099 <at> debbugs.gnu.org X-Debbugs-Original-To: bug-coreutils@HIDDEN Received: via spool by submit <at> debbugs.gnu.org id=B.153108848723887 (code B ref -1); Sun, 08 Jul 2018 22:22:01 +0000 Received: (at submit) by debbugs.gnu.org; 8 Jul 2018 22:21:27 +0000 Received: from localhost ([127.0.0.1]:51528 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1fcI3a-0006DD-NU for submit <at> debbugs.gnu.org; Sun, 08 Jul 2018 18:21:26 -0400 Received: from eggs.gnu.org ([208.118.235.92]:40853) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <kingsley@HIDDEN>) id 1fcGqv-0000SK-J0 for submit <at> debbugs.gnu.org; Sun, 08 Jul 2018 17:04:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <kingsley@HIDDEN>) id 1fcGqp-0005y7-By for submit <at> debbugs.gnu.org; Sun, 08 Jul 2018 17:04:12 -0400 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50 autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:35868) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from <kingsley@HIDDEN>) id 1fcGqp-0005xy-8T for submit <at> debbugs.gnu.org; Sun, 08 Jul 2018 17:04:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60056) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from <kingsley@HIDDEN>) id 1fcGqo-0008Bu-3D for bug-coreutils@HIDDEN; Sun, 08 Jul 2018 17:04:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <kingsley@HIDDEN>) id 1fcGqk-0005uU-Vs for bug-coreutils@HIDDEN; Sun, 08 Jul 2018 17:04:10 -0400 Received: from outbound-smtp12.blacknight.com ([46.22.139.17]:56978) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from <kingsley@HIDDEN>) id 1fcGqk-0005ty-PG for bug-coreutils@HIDDEN; Sun, 08 Jul 2018 17:04:06 -0400 Received: from mail.blacknight.com (pemlinmail01.blacknight.ie [81.17.254.10]) by outbound-smtp12.blacknight.com (Postfix) with ESMTPS id 4CCCC1C2C39 for <bug-coreutils@HIDDEN>; Sun, 8 Jul 2018 22:04:04 +0100 (IST) Received: (qmail 15507 invoked from network); 8 Jul 2018 21:04:04 -0000 Received: from unknown (HELO debian1.loaner.com) (kingsley@HIDDEN@[97.113.25.140]) by 81.17.254.9 with ESMTPSA (AES256-SHA encrypted, authenticated); 8 Jul 2018 21:04:04 -0000 Received: from kingsley by debian1.loaner.com with local (Exim 4.90_1) (envelope-from <kingsley@HIDDEN>) id 1fcGqa-0003dq-6z for bug-coreutils@HIDDEN; Sun, 08 Jul 2018 14:03:56 -0700 Date: Sun, 8 Jul 2018 14:03:56 -0700 From: "Kingsley G. Morse Jr." <kingsley@HIDDEN> Message-ID: <20180708210356.c5fwiocbvdndkgxh@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: NeoMutt/20170306 (1.8.0) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -5.0 (-----) X-Mailman-Approved-At: Sun, 08 Jul 2018 18:21:24 -0400 X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -6.0 (------) Thank you very much for maintaining coreutils! It seems to me that it would be hard to underestimate how useful it is. The main reason I'm writing is to humbly suggest a performance improvement to the "uniq" command. It currently requires its input to be sorted. Sorting generally takes about O(N*log(N)) time. However, it seems to me that sorting is unnecessary. You can see this is so in the following example $ echo -e "b\na\nb" | awk '!seen[$0]++' It basically avoids sorting by using hashed indexes into an associative array to find previously seen values in about O(N) time. I expect it would be about O(log(N)) times faster than the sorting the uniq command currently requires. For big values of N, the time saved could be substantial. Humble suggestion. Add an option to the "uniq" command. Let it work quickly with unsorted data. Maybe the new option could be something like "-usi" for "unsorted input". Thanks, Kingsley -- Time is the fire in which we all burn.
Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Mailer: MIME-tools 5.505 (Entity 5.505) Content-Type: text/plain; charset=utf-8 X-Loop: help-debbugs@HIDDEN From: help-debbugs@HIDDEN (GNU bug Tracking System) To: "Kingsley G. Morse Jr." <kingsley@HIDDEN> Subject: bug#32099: Acknowledgement (New uniq option for speed) Message-ID: <handler.32099.B.153108848723887.ack <at> debbugs.gnu.org> References: <20180708210356.c5fwiocbvdndkgxh@HIDDEN> X-Gnu-PR-Message: ack 32099 X-Gnu-PR-Package: coreutils Reply-To: 32099 <at> debbugs.gnu.org Date: Sun, 08 Jul 2018 22:22:02 +0000 Thank you for filing a new bug report with debbugs.gnu.org. This is an automatically generated reply to let you know your message has been received. Your message is being forwarded to the package maintainers and other interested parties for their attention; they will reply in due course. Your message has been sent to the package maintainer(s): bug-coreutils@HIDDEN If you wish to submit further information on this problem, please send it to 32099 <at> debbugs.gnu.org. Please do not send mail to help-debbugs@HIDDEN unless you wish to report a problem with the Bug-tracking system. --=20 32099: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D32099 GNU Bug Tracking System Contact help-debbugs@HIDDEN with problems
X-Loop: help-debbugs@HIDDEN Subject: bug#32099: New uniq option for speed Resent-From: Paul Eggert <eggert@HIDDEN> Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> Resent-CC: bug-coreutils@HIDDEN Resent-Date: Mon, 09 Jul 2018 16:36:02 +0000 Resent-Message-ID: <handler.32099.B32099.153115414624605 <at> debbugs.gnu.org> Resent-Sender: help-debbugs@HIDDEN X-GNU-PR-Message: followup 32099 X-GNU-PR-Package: coreutils X-GNU-PR-Keywords: To: "Kingsley G. Morse Jr." <kingsley@HIDDEN>, 32099 <at> debbugs.gnu.org Received: via spool by 32099-submit <at> debbugs.gnu.org id=B32099.153115414624605 (code B ref 32099); Mon, 09 Jul 2018 16:36:02 +0000 Received: (at 32099) by debbugs.gnu.org; 9 Jul 2018 16:35:46 +0000 Received: from localhost ([127.0.0.1]:52731 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1fcZ8c-0006On-Jn for submit <at> debbugs.gnu.org; Mon, 09 Jul 2018 12:35:46 -0400 Received: from zimbra.cs.ucla.edu ([131.179.128.68]:54520) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <eggert@HIDDEN>) id 1fcZ8a-0006Oa-Uw for 32099 <at> debbugs.gnu.org; Mon, 09 Jul 2018 12:35:45 -0400 Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id F08BA160655; Mon, 9 Jul 2018 09:35:38 -0700 (PDT) Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id o_A58ABuek0B; Mon, 9 Jul 2018 09:35:36 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id BE8FF1607DC; Mon, 9 Jul 2018 09:35:36 -0700 (PDT) X-Virus-Scanned: amavisd-new at zimbra.cs.ucla.edu Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id XXBQl52XpZO4; Mon, 9 Jul 2018 09:35:36 -0700 (PDT) Received: from [192.168.1.9] (unknown [47.154.30.119]) by zimbra.cs.ucla.edu (Postfix) with ESMTPSA id 7CC27160655; Mon, 9 Jul 2018 09:35:36 -0700 (PDT) References: <20180708210356.c5fwiocbvdndkgxh@HIDDEN> From: Paul Eggert <eggert@HIDDEN> Openpgp: preference=signencrypt Autocrypt: addr=eggert@HIDDEN; prefer-encrypt=mutual; keydata= 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 uNcby4U= Organization: UCLA Computer Science Department Message-ID: <a275d0d6-02a1-32d9-9000-4a9bd8753da3@HIDDEN> Date: Mon, 9 Jul 2018 09:35:35 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 In-Reply-To: <20180708210356.c5fwiocbvdndkgxh@HIDDEN> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Kingsley G. Morse Jr. wrote: > $ echo -e "b\na\nb" | awk '!seen[$0]++' >=20 > It basically avoids sorting by using hashed > indexes into an associative array to find > previously seen values in about O(N) time. No, it's still O(N log N) because hash table lookup is really O(log N), d= espite=20 what many textbooks say. Though no doubt we could make it faster than tha= n the=20 sorting pipeline, it wouldn't be algorithmically faster. See, for example= : https://lemire.me/blog/2009/08/18/do-hash-tables-work-in-constant-time/
X-Loop: help-debbugs@HIDDEN Subject: bug#32099: New uniq option for speed Resent-From: Assaf Gordon <assafgordon@HIDDEN> Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> Resent-CC: bug-coreutils@HIDDEN Resent-Date: Mon, 09 Jul 2018 20:54:02 +0000 Resent-Message-ID: <handler.32099.B32099.153116959514853 <at> debbugs.gnu.org> Resent-Sender: help-debbugs@HIDDEN X-GNU-PR-Message: followup 32099 X-GNU-PR-Package: coreutils X-GNU-PR-Keywords: To: "Kingsley G. Morse Jr." <kingsley@HIDDEN>, 32099 <at> debbugs.gnu.org Received: via spool by 32099-submit <at> debbugs.gnu.org id=B32099.153116959514853 (code B ref 32099); Mon, 09 Jul 2018 20:54:02 +0000 Received: (at 32099) by debbugs.gnu.org; 9 Jul 2018 20:53:15 +0000 Received: from localhost ([127.0.0.1]:52794 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1fcd9m-0003rV-N3 for submit <at> debbugs.gnu.org; Mon, 09 Jul 2018 16:53:14 -0400 Received: from mail-pf0-f171.google.com ([209.85.192.171]:43106) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <assafgordon@HIDDEN>) id 1fcd9l-0003rF-Eg for 32099 <at> debbugs.gnu.org; Mon, 09 Jul 2018 16:53:13 -0400 Received: by mail-pf0-f171.google.com with SMTP id y8-v6so14477307pfm.10 for <32099 <at> debbugs.gnu.org>; Mon, 09 Jul 2018 13:53:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:to:references:from:message-id:date:user-agent:mime-version :in-reply-to:content-language:content-transfer-encoding; bh=zOJxE1l5in9VCvy8J44BeiHu+rEFfyyxOEj10/OAUWM=; b=bC7ArVD7/quEVfj0knNIafWd+jiOazYrsZxAW4V2P79wUxtXNBBPpqcQVxj7qgiUnQ 79Il2Lsj791y8toFmB/YzEBURvPsxD4jk/JeeafCHlIRlwPB2TszGhYbEA+KW3sMPwqW IRgu181mdTlAxRs5yzV3F44c+4UWgH/nAOpdM7fLRkio02VKgX1ow1+3eTNYP40RPzP+ I7XH+OP8Ik5D6tTU7fzHaLhCOXkryWJ29KdaHdQPdH8VqHO1WMWkIF2bksrD2HbUOC79 O0d/MNH9fpVUndRUtcCARiiOu8slfnxHw8Ry0m3ZwMD7JA+VZMjx9GSl+i+dsj4VQfvb dESw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=zOJxE1l5in9VCvy8J44BeiHu+rEFfyyxOEj10/OAUWM=; b=bR79wMPOSkZTKOfxn5U++yMi22IrTFGUU1FFWJeqKh96/CkFA0lboY9ciI1ykE/7h8 N6BwP9WbTIANXSmpDVWvllydf9VQVGkn/aQoKAG0bYBhFKNdo2CiDtn7vkuV+soWeRbO 82/n3/Xu5M3kI7jGbSfH9g/oT4pKTN9Zayv8THNIR/ap11sTT4wJIMb5hT5YGgyCgdTa 6z6x49Tg7yZfxxbBnndMI2hBmkxFYhusNQpYH+n3vbM0Zv+0DrQ49Yw/MqBrPwhybnFA Xxnvc15AaIfQRISmz/mDLpoKnvo7+pSKV0p9vQGVuq3CMz+HoXQfEAPlBEpGyjT+rMfX NDAw== X-Gm-Message-State: APt69E1izbd5wq7r0ZjvCAEqXQ6kN9VPJm/5oPZoSszUoeoT032DkeaV 8n3zeg9w1+bcbPmOGr0ynKrdp2Of X-Google-Smtp-Source: AAOMgpeZ/0bqaXhuk/gUQNuBzEZdS55IBS8+t8NF8+684FEBH7c3/0zmghQUCo16jQs2bePe/RboGw== X-Received: by 2002:a62:f909:: with SMTP id o9-v6mr22937773pfh.141.1531169586925; Mon, 09 Jul 2018 13:53:06 -0700 (PDT) Received: from tomato.housegordon.com (moose.housegordon.com. [184.68.105.38]) by smtp.googlemail.com with ESMTPSA id q28-v6sm25388418pfg.144.2018.07.09.13.53.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 09 Jul 2018 13:53:05 -0700 (PDT) References: <20180708210356.c5fwiocbvdndkgxh@HIDDEN> From: Assaf Gordon <assafgordon@HIDDEN> Message-ID: <a499a8ae-df6d-8342-8d89-e105f6b2bc62@HIDDEN> Date: Mon, 9 Jul 2018 14:53:04 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 In-Reply-To: <20180708210356.c5fwiocbvdndkgxh@HIDDEN> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) Ηello, On 08/07/18 03:03 PM, Kingsley G. Morse Jr. wrote: > The main reason I'm writing is to humbly suggest > a performance improvement to the "uniq" command. > > It currently requires its input to be sorted. > > Sorting generally takes about O(N*log(N)) time. > > However, it seems to me that sorting is > unnecessary. > > You can see this is so in the following example > > $ echo -e "b\na\nb" | awk '!seen[$0]++' In addition to Paul's reply, here are couple of more practical issues: 1. GNU sort has several non trivial (and not obvious) advantages: It can sort a file larger than available memory (i.e. you can sort a 3GB file on machine with 1GB of RAM). It can sort using multiple threads, making sorting faster. If you have a powerful machine (lots of ram and lots of CPUs), you can sort entirely in memory like so: sort -S 10GB --parallel=10 -T /foo/bar INPUT > OUTPUT The "-S" sets the maximum amount of memory sort is allowed to use, The "--parallel" sets the number of parallel sorting threads, The "-T" points to a non-existing directory - ensuring that if sort runs out of memory (input too large) then it will fail instead of resorting to using disk storage (and slower I/O). There are many other combinations (e.g. "--compress-program"). A simple hash implementation will not be able to do so. 2. Sort already supports printing only unique values with the "-u" option. So by using the correct combination of keys (-k) and unique (-u) you can get unique values without even invoking "uniq" (if your concert is starting another process). Note that uniq will compare the entire line, and sort will "unique" only the specified "keys", but sort also has last the "--stable" option that can affect the results. 3. Sometimes you really just want to see the list of unique values, and that's valid. But often times you want to later examine or do something with the list of unique values, and then it is common to sort it. A hash implementation of "unique" will not print sorted items, and then you'll likely need to pipe it to another "sort" anyhow (perhaps with much smaller number of items, but still need sort). 4. The Unix philosophy often says "Write programs that do one thing and do it well." ( https://en.wikipedia.org/wiki/Unix_philosophy ) GNU Sort does sorting very well. Other programs that require sorted input can rely on it (e.g. join, uniq, etc.). 5. Using your awk example is actually a fantastic way to achieve what you wanted - it fits perfectly in "do one thing and do it well". Note that If you're using a recent Debian or Ubuntu machine, they have switched the default awk implementation from GNU awk (gawk) to "mawk". "mawk" is indeed faster in some aspects, but it seems gawk is much faster when it comes to hashing. Observe the following: $ seq 1000000 | time -p gawk '!seen[$0]++' > /dev/null real 0.40 user 0.35 sys 0.04 $ seq 1000000 | time -p mawk '!seen[$0]++' > /dev/null real 10.48 user 10.40 sys 0.07 Using awk will also enable you to later extend your task to achieve more. Eg. the following program: awk 'NR==FNR{seen[$1]++;next} seen[$1]>0' a.txt b.txt Will only print lines from "b.txt" which have a key matching from file "a.txt". kind of a hash-based join between two files. 6. Lastly, if you still want a program that uses hashing to discard duplicates in a file, may I humbly suggest GNU datamash: https://www.gnu.org/software/datamash/ (disclaimer: I'm datamash's developer). It can easily remove duplicates, and it uses the same hashing code that other coreutils program use. Example: $ printf "%s\n" a a b a b c b | datamash rmdup 1 a b c Datamash has several additional useful features, for example it can remove duplicates from a specific column but still print the entire matching line: $ printf "FOO %s %s\n" a 1 a 2 b 3 a 4 b 5 c 6 b 7 \ | datamash -W rmdup 2 FOO a 1 FOO b 3 FOO c 6 Hope this helps, regards, - assaf
X-Loop: help-debbugs@HIDDEN Subject: bug#32099: Benchmarks: Hashing ~70% faster (Was: New uniq option for speed) Resent-From: "Kingsley G. Morse Jr." <kingsley@HIDDEN> Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> Resent-CC: bug-coreutils@HIDDEN Resent-Date: Tue, 10 Jul 2018 04:31:02 +0000 Resent-Message-ID: <handler.32099.B32099.153119701314687 <at> debbugs.gnu.org> Resent-Sender: help-debbugs@HIDDEN X-GNU-PR-Message: followup 32099 X-GNU-PR-Package: coreutils X-GNU-PR-Keywords: To: Assaf Gordon <assafgordon@HIDDEN> Cc: 32099 <at> debbugs.gnu.org, Paul Eggert <eggert@HIDDEN> Received: via spool by 32099-submit <at> debbugs.gnu.org id=B32099.153119701314687 (code B ref 32099); Tue, 10 Jul 2018 04:31:02 +0000 Received: (at 32099) by debbugs.gnu.org; 10 Jul 2018 04:30:13 +0000 Received: from localhost ([127.0.0.1]:52945 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1fckI1-0003op-E4 for submit <at> debbugs.gnu.org; Tue, 10 Jul 2018 00:30:13 -0400 Received: from outbound-smtp27.blacknight.com ([81.17.249.195]:57107) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <kingsley@HIDDEN>) id 1fckHx-0003nj-4n for 32099 <at> debbugs.gnu.org; Tue, 10 Jul 2018 00:30:10 -0400 Received: from mail.blacknight.com (pemlinmail05.blacknight.ie [81.17.254.26]) by outbound-smtp27.blacknight.com (Postfix) with ESMTPS id D76E8B8899 for <32099 <at> debbugs.gnu.org>; Tue, 10 Jul 2018 05:30:02 +0100 (IST) Received: (qmail 15376 invoked from network); 10 Jul 2018 04:30:02 -0000 Received: from unknown (HELO debian1.loaner.com) (kingsley@HIDDEN@[97.113.25.140]) by 81.17.254.9 with ESMTPSA (AES256-SHA encrypted, authenticated); 10 Jul 2018 04:30:01 -0000 Received: from kingsley by debian1.loaner.com with local (Exim 4.90_1) (envelope-from <kingsley@HIDDEN>) id 1fckHh-0001sI-Di; Mon, 09 Jul 2018 21:29:53 -0700 Date: Mon, 9 Jul 2018 21:29:53 -0700 From: "Kingsley G. Morse Jr." <kingsley@HIDDEN> Message-ID: <20180710042953.2w46nfztrxrg6gmi@HIDDEN> References: <20180708210356.c5fwiocbvdndkgxh@HIDDEN> <a499a8ae-df6d-8342-8d89-e105f6b2bc62@HIDDEN> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="qzkemyanjw2idojc" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <a499a8ae-df6d-8342-8d89-e105f6b2bc62@HIDDEN> User-Agent: NeoMutt/20170306 (1.8.0) X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> --qzkemyanjw2idojc Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit Hi Assaf, I like datamash. And I like avoiding a pipe with sort's "-u" option. And I like your benchmarks. Mine are humbly attached. They compare sorting to hashing. At the moment, hashing seems to me to be about 70% faster. And to scale better. I'd still like uniq to be faster and free from sort. Feel free to let me know if I screwed up. Thanks, Kingsley On 07/09/2018 14:53, Assaf Gordon wrote: > Ηello, > > On 08/07/18 03:03 PM, Kingsley G. Morse Jr. wrote: > > The main reason I'm writing is to humbly suggest > > a performance improvement to the "uniq" command. > > > > It currently requires its input to be sorted. > > > > Sorting generally takes about O(N*log(N)) time. > > > > However, it seems to me that sorting is > > unnecessary. > > > > You can see this is so in the following example > > > > $ echo -e "b\na\nb" | awk '!seen[$0]++' > > In addition to Paul's reply, here are couple of more practical issues: > > 1. > GNU sort has several non trivial (and not obvious) advantages: > > It can sort a file larger than available memory (i.e. you > can sort a 3GB file on machine with 1GB of RAM). > > It can sort using multiple threads, making sorting faster. > > If you have a powerful machine (lots of ram and lots of CPUs), > you can sort entirely in memory like so: > > sort -S 10GB --parallel=10 -T /foo/bar INPUT > OUTPUT > > The "-S" sets the maximum amount of memory sort is allowed to use, > The "--parallel" sets the number of parallel sorting threads, > The "-T" points to a non-existing directory - ensuring that > if sort runs out of memory (input too large) then it will fail > instead of resorting to using disk storage (and slower I/O). > > There are many other combinations (e.g. "--compress-program"). > > A simple hash implementation will not be able to do so. > > > 2. > Sort already supports printing only unique values with the "-u" option. > So by using the correct combination of keys (-k) and unique (-u) > you can get unique values without even invoking "uniq" > (if your concert is starting another process). > > Note that uniq will compare the entire line, and sort will "unique" > only the specified "keys", but sort also has last the "--stable" > option that can affect the results. > > > 3. > Sometimes you really just want to see the list of unique values, > and that's valid. > But often times you want to later examine or do something with the list > of unique values, and then it is common to sort it. > > A hash implementation of "unique" will not print sorted items, > and then you'll likely need to pipe it to another "sort" anyhow > (perhaps with much smaller number of items, but still need sort). > > > 4. > The Unix philosophy often says > "Write programs that do one thing and do it well." > ( https://en.wikipedia.org/wiki/Unix_philosophy ) > > GNU Sort does sorting very well. > Other programs that require sorted input can rely on it (e.g. join, > uniq, etc.). > > > 5. > Using your awk example is actually a fantastic way to achieve > what you wanted - it fits perfectly in "do one thing and do it well". > > Note that If you're using a recent Debian or Ubuntu machine, > they have switched the default awk implementation from GNU awk (gawk) > to "mawk". "mawk" is indeed faster in some aspects, but it seems gawk is > much faster when it comes to hashing. > > Observe the following: > > $ seq 1000000 | time -p gawk '!seen[$0]++' > /dev/null > real 0.40 > user 0.35 > sys 0.04 > $ seq 1000000 | time -p mawk '!seen[$0]++' > /dev/null > real 10.48 > user 10.40 > sys 0.07 > > Using awk will also enable you to later extend your task to > achieve more. Eg. the following program: > awk 'NR==FNR{seen[$1]++;next} seen[$1]>0' a.txt b.txt > > Will only print lines from "b.txt" which have a key matching from > file "a.txt". kind of a hash-based join between two files. > > > 6. > Lastly, if you still want a program that uses hashing to discard > duplicates in a file, may I humbly suggest GNU datamash: > https://www.gnu.org/software/datamash/ > (disclaimer: I'm datamash's developer). > > It can easily remove duplicates, and it uses the same hashing code > that other coreutils program use. Example: > > $ printf "%s\n" a a b a b c b | datamash rmdup 1 > a > b > c > > Datamash has several additional useful features, > for example it can remove duplicates from a specific column but still print > the entire matching line: > > $ printf "FOO %s %s\n" a 1 a 2 b 3 a 4 b 5 c 6 b 7 \ > | datamash -W rmdup 2 > FOO a 1 > FOO b 3 > FOO c 6 > > > > Hope this helps, > regards, > - assaf > -- Time is the fire in which we all burn. --qzkemyanjw2idojc Content-Type: image/png Content-Disposition: attachment; filename="hash_v_sort_benchmarks.1.png" Content-Transfer-Encoding: base64 iVBORw0KGgoAAAANSUhEUgAABAMAAAJoCAYAAAATXSiNAAAABHNCSVQICAgIfAhkiAAAIABJ REFUeJzs3Xm8HEW99/HPSUISIIQQ9mBMkIgGAsgmAZHFjYiocNkvCKhc5cENEFBZ5KBschFR dhWILAroZYkbiktUuBIui+wkLLJDJCF7SEJy6vnjN2Mmfbqre3p6m5nve171Ss50d3V1d3V1 T3VVdQ+wABiGiIiIiIiIiHSDhT2AKzsVIiIiIiIiIlKcAWUnQERERERERESKpcoAERERERER kS6jygARERERERGRLqPKABEREREREZEuo8oAERERERERkS6jygARERERERGRLqPKABERERER EZEuo8oAERERERERkS6jygARERERERGRLqPKABEREREREZEuo8oAERERERERkS6jygARERER ERGRLqPKABEREREREZEuo8oAERERERERkS6jygARERERERGRLqPKAJFu1Qu4iHBPB61TRKRq BgJ7Az8CHgBeB5YSXjaeVVtmScR0BxxVXNJzN4jo7XTAvuUlre31omuwiKxClQFSTRPw3wzc 2GR898XENzSTVIuIiPhtAzwI/Bo4GtgWWA8YXGaiRESkG6kyQERERPL1KNGVsSeWmK6ivQv4 M7BV2QkRERFRZYCIiIhIMS4G1ik7ESIiImZQ2QkQERER6XibAh+OmedR4CVgRcN3T+aWIhER 6XKqDBCR4swCpkdMe67AdIiIFG33mOn7A7d4pk8HhkRMm5cqRdJtdA0WkQBVBohIcS6pBRGR bvM2z7RX8FcEgA08KNIKXYNFJEBjBoiIiIjkbbhn2muFpUJEROTf1DJApFnDgXHAKGCj2t9D gR5gQS28BDxCdjd4Q4F3YyNRrw+sCawGvAnMB14GXgCewt5VnYdhwPuBtwMjgTnA08Bd2Puv qyav9A7BmvuOBdbF3g/+IvA3YHEL8eah6HyzFvBe7NwYiR2DucBs4DFWjiifpTLWGWZL7Mnt aOAtYAYwFVgYs9wmrMynYPnpQeAhWkt3FcqMsowEdsTK55HA6lgz+jeAZ7D9+1YJ6fI9fiki jyaVZ9m5GzZ2Qr3sfAH4a4vxdosqXoPDjmlVr4dZqMr1RiRjvrevKyiUEybgvJ8bm4zvvpj4 hnqWXR/Ht3DcgePVmHiCn5dwXIBjfMr9MAnHFByLE65vOY7pOK7H8QUc63ni7vXEc0/DfJvh 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 WfnpCk8ct+WwncGwDv7z1/dZHDO9SuV41vm67O1QUCggqJuAVFOS1wSCNcXyvd866CJsEKNm /ZHkLRCqbgXWTO7ODOJ6CzgW+HmCeY+n+dcozqH5/opZ+yYwI6e4Z2BPbLJS1rHNcju65Rzt lu1slcqrfGVdBmUlr3K3rPxUtjnYdi9scrkVRL/Fyafs8i2rfF32dogUQJUBUk2TsaZqcZot bN/EmnE1U7j/EuvXuLzJdVXZImw/nILtkzRmALuS/Bg8hN0oJ73BrsefVxP9OEuwZpPn5rye Y7H3cmeljGML2W1Ht5yj3bKdWVB5la+sy6BWFFHullVGlu1ubLt9A2Q2Woi93jFqHCefKpRv WeTrKmyHSM5UGSDVNAd7XaDP3cCjKeJ+CRsR+mz8ryN8COtj90lgcYr1VF0fdsM1GjgdeAJr MOTzJjZi8v7Y+6GTDNzY6GbsdTu+UZdfxJ4KbYv1NU3jEuAQ4HLs5jxJxVLdDKxf6WbA91Ou vxmLsSc2O2Ppvhe7WVvaQpxlHNsst6NbztFu2c4sdHJ5Vbaszt12KnfLyE9VcDfwLuAyokfc X4wNiLkN6SoC6sou37LK12Vvh0jOeogv/kQ612BgJ2BLYCRWE/4qVqjn1TS8ytbFLnobAetg owvPwypnngHuJ/rVj83aGHg/9i7fodjovzOAv5N9qTQQez/4GGATbKCf1bHq0EXYCNP/BJ4E Xsl43VVR5LHNUreco92ynVnq1PKqU7RbuduuZWRaQ7C3YozFypzZWOXWX2mu+2USnVK+dcp2 iDRQZYCIiIiIiIhIl1E3AREREREREZEuo8oAERERERERkS6jygARERERERGRLqPKABERERER EZEuo8oAERERERERkS6jygARERERERGRLqPKABEREREREZEuo8oAERERERERkS6jygARERER ERGRLqPKABEREREREZEuo8oAERERERERkS6jygARERERERGRLqPKABEREREREZEuo8oAERER ERERkS6jygARERERERGRLqPKABEREREREZEuo8oAERERERERkS6jygARERERERGRLqPKABER EREREZEuo8oAERERERERkS6jygARERERERGRLqPKABEREREREZEuo8oAERERERERkS6jygAR ERERERGRLqPKABGRLLwGuIbw9XKT03WqvP8PBn4PzATeYtV0blRiukQkf1Uum0Sk66kyQKSd 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 n8r00L+tz53YIE3NjBcQNBBrJh/sdwjWNL3xicX5hPc/rQ8SdQfNvZKvaBdgTzei3AR8q4W4 v4g142w0EHsSNjDw/Zv4j1szx6WI9GVx7C/GnmKFjVAvqzoL+DrhfYSDrsTGmqiyudjgl4/E zLcIa8J+S4p1PIo9cW1GO+znLPZdHvv/HGwE+qXYee0C0+fXvq/v20uBp1jZReEVrKVbMy6j /+sfG30P+FWTcRbhi/TvKtXoxyRvkZbVPsj6miUilaTKAJF29BbWn3o3rHnns8Bi7KL9PHbT 8HHsne/B0b/jXAkcDlyCvbf+WeymbUXt30ewG5NdgeMDyy6qpakXewXZstoy9wJfwF4RVeWb haVY5cmxwP9hA4EtxPbDkdg7sZP8KIhyKdak/zTsxm8mto+W1f7/99o8BwDrs+qxa+W4FJG+ rI79j7Am218D/oAN1rgUOw7PYj/mvsTKAcbyEGz2HRxMqyq+gw3Cdh62n9/A8uc87IfvZVg/ 42PwD0hYFS9gY6B8GqvMehXLR3OxZsjnYk36b2hhHQdh3aoewcrMJNphP2ex77Lc/zti5z3A 2fR/bWXdz7Fy45fYfn0LGyj1cmAHmn+rxjJsnI+zautcVov3N9iYJSfQv1KiChZhfe6/jO3r N7H89VdsENb/Inm6s9wHrVwTRKQt9FDNYlFEJH+vseorlr6B3fBLd/sD8MHa/x02HkNwMDkR kSL9GPhsw9/T6D84oIhIk9QyQEREpG4oK9+HDvbUVxUBIiIi0oFUGSAiIlL3fla+tvCfWHcF ERERkQ6kygAREZG6D9f+dViTXA1mKCIiIh1KlQEiIiJ1J7PyzRy+0b1FRERE2pwGEBQRERER ERHpMmoZICIiIiIiItJlVBkgIiIiIiIi0mVUGSAiIiIiIiLSZVQZICIiIiIiItJlVBkgIiIi IiIi0mVUGSAiIiIiIiLSZVQZICIiIiIiItJlVBkgIiIiIiIi0mVUGSAiIiIiIiLSZVQZICIi IiIiItJlVBkgIiIiIiIi0mVUGSAiIiIiIiLSZVQZICIiIiIiItJlVBkgIiIiIiIi0mXatzJg OHAJ8CqwBHgQOLCJ5bcFbgX+CSwGZgN/B47IYV0iIiIiIiIiFdKelQE9wC+BI4Fzgf2A6cDN wMEJ43h77d/Lgc8BpwHLgJ8A38p4XSIiIiIiIiIV0gO4shPRtP8A/gc4Griq9l0PMA3YCBgL 9KWIdyDwMLA+sEHO6xIREREREREpSXu2DNgPe4r/04bvHHAtMBrYIWW8K4BXgOUFrEtERERE RESkJO1ZGTABeAZ4M/D9Iw3TkxoCDMN+2B8PfAA4L6d1iYiIiIiIiFTAoLITkMq6wAsh37/R MD2pq4DDav9/CzgR+EFO6xIRERERERGpgPasDMjSt4ArsDEC9gMuBNYEzmox3iQjMfS0uA4R ERERERGRFNqzMmA2MDLk+5EN05OaUQsAt9T+7cVaDLzawrrifui337CNIiIiIiIi0iHac8yA R4BxwBqB77eu/ftoC3Hfi71V4B0FrEtERERERESkBO1ZGXArsBor+/qDbckRwIvAfQniGBjy 3QBgH+yp/bMZrktERERERESkQtqzm8BtwF+B7wFrAU9hP853AA4B+hrmnQj8HTgTa/5fdwsw H/gH8DqwIXAA8N5avK+mWJeIiIiIiIhIG2jPygAHfAI4BzgZGAE8CRwM3JwwjtuwH/Ufwfr/ LwQeBo4Erst4XSIiIiIiIiIV0oOGsiuHQ28TEBERERERkVK055gBItI1Dj/8cJxzOOeYNGlS 2clpWZbbs8cee/w7rsMPPzyjFHa2LPdZp+XNImnfdZbe3t5/H8/GcMEFFySO45JLLuHpp5/O MZXRJkyYEJr+5557rpT0iIgURZUBIiIi0nF22GGHf/+omzhxYuR8V1xxxb/n22effQpMYWda sWLFKqEow4YN46STTuKee+5h1qxZLFmyhOeee47rr7+e3Xff3busc66UNJcp6fkhIp1NlQEi IiI1++yzz79vkA855JCykyPSdsaNG8egQYMYNGgQX/va1wpZ53ve8x4eeeQRzj//fHbaaSfW XXddhgwZwpgxYzjssMOYOnUqF198MT094f0zH3vssX+nedCgQdx9992FpFtEpGztOYCgiIjw j3/8gz333BOAJ554ouTUtAftM5HOMnr0aH7729+y0UYbATBlyhRuuOEG5s6dyzbbbMNxxx3H qFGj+OIXv8iiRYv4+te/XnKKRUSqQ5UBIiJtau7cuUydOrXsZLQV7TORath444350pe+xF57 7cW4ceNYa6216OnpYf78+cyaNYuXX36Z+++/nz/96U9MmTIlMp7vfOc7/64IOOusszj99NP/ Pe33v/89119/PdOmTWP06NGcdNJJ3HDDDTzyyCO5bttLL73EoEGDOPnkk7n22mvbdh0i8v/Z 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 G7XJ6soc8/709vTC9oXAx0vXvvfOIVrP3wx8igjG87YD3g0cmP78ZzQfy39Cetss4C06l/au x3icB2wkVjDIr06wLfB56udPgLFd19HeLxPlvSJJ6gs9X9/QYrFYLJa+KV8n1mq/j4TzSfgq CR8q7PNOEp5J97uWhAtJuDv9eQWN69ePdswDifXrExLuSPe5koQtJHwu3f5gbv/p6bZft/G8 Wv2fVtvnpduva3G8j6WPf6yw/XASVqWPLSfhMhK+RcJNJKxNtx+f7vsgCVtJ+CUJ3yDhAhJu Tfd5goSDSz63dq/H5eljxe1lyunp/30mfW7nk/B7EtakzzMh4a2M7bqWeb+M9ZgWi8VisTSW nlfAYrFYLJb+KbNIOIeEZdQCzG832e8IEi4hYTUJm0l4iIR/J2GvMR7zRST8gAik15PwCxI+ kD42SMkASNiDhM+mx1xPwjoisP0OCX9Mwox0v5NJOJeE35LweLrfXSR8iYR92rxu7VyP8SQD IOFEIrmxkUgCXEzCftSC8bfm9m3nupZ9v4zlmBaLxWKxFMqk9I4kSZIkSRoSzhkgSZIkSdKQ MRkgSZIkSdKQMRkgSZIkSdKQMRkgSZIkSdKQMRkgSZIkSdKQMRkgSZIkSdKQMRkgSZIkSdKQ MRkgSZIkSdKQMRkgSZIkSdKQMRkgSZIkSdKQMRkgSZIkSdKQMRkgSZIkSdKQMRkgSZIkSdKQ MRkgSZIkSdKQmQys63UlJEmSJElS16z7vxWue1XdkIr+AAAAAElFTkSuQmCC --qzkemyanjw2idojc Content-Type: image/png Content-Disposition: attachment; filename="hash_v_sort_benchmarks.2.png" Content-Transfer-Encoding: base64 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 3kK8YS7Cmq19Buufl/QE+TzWpPZzjeV3w/pD1kle27QoRef5uin6GB3ALtjGY4PMPUr80+Cl 2OjX+2Pvl44bgKwIdT8ustAPnIo1ET8J68f9ElY+vgDcDpyCvUHli9i2eV3MOuMGj6uCTsnD WZmLned8ZgAPtbheld2mrPx2FXbN4nvzwLPY0/i3YH380yj6HCSSkR6q3ZhNJN4IrM/dNli/ s0XAi9iJNa9mVsOx99ROwC4KxwKvwarXFmN9Cv+JDcj3Qk5pyMJIYEdstPCxjTCAbcO52G/4 B/5X9EjxysjzdVPGMboedtG/EbBuI7752LH0BHA30a8wk3r5b+C8iGkOG4D1leKSkxnl4Xyp 7F5d0fltY+AdwCbYgIEvYdv9b2R/N9Qp14nS8VQZICIiIpLUcOA+YNuI6XcDOxeXHBERkbTU TUBERES60wexpsvrJpy/B3tDS1RFAMD17SZKRESkGKoMEBERke60FvBVrM/wT7FBzsaEzDcS ey/4LcAXPOubgw0yKCIiUgO9ZSdAREREpFRrYe8uPwwbN+VpYDY2uOBYbGCvEQnWcwL1e9OK iIh0LVUGiIiIiAwahg2qulmLy30De2OLiIhITagyQERERCStecBxwIVlJ0RERKQ1GjNARERE utO/SN+sfw7w/4CtUUWAiIjUkl4tKCIiIt1rOPbu912BnbDxATYF1sHeRb4Ce/f5fOBx4B7g duDmxjQREZGaUmWAiIiIiIiISJdRNwERERERERGRLqPKABEREREREZEuo8oAERERERERkS6j ygARERERERGRLqPKABEREREREZEuo8oAERERERERkS6jygARERERERGRLqPKABEREREREZEu o8oAERERERERkS6jygARqY4+wEWE28pLloiIJNQLfBC4ELgXeBlYQXi5flJJaWzWS/R5xwEf KS9pIiJ56y07ASIiIiLSAXYCLgW2KjshIiKShFoGiIiISOd6iOinvseVmK5Osx3wJ1QRUATl aRHJiCoDRERERKQ95wNjyk6EiIi0Qt0ERERERCS9bYG3e6Y74EHgBWBl0/f/yDNRIiISR5UB IlIds4HHIqY9VWA6REQkuT090waAdwJ/LigtIiKSmCoDRKQ6pjaCiIjUx3jPtLtRRYCISEVp zAARERERSc83VsCLhaVCRERapJYBItK+0cA7gNcD44C5wOPArcCyktI0EtgD2AxYD3vX9bPA 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 wDuwdwSPwkYWnok94dURbUZiI6JPxPrIzsZubP7C6hcxvVhz2Chhg4hFKXu/jAR2xEaQHtsI A1gFyFzgn9ho6EmfnGVpBNbvdBtsfywCXsQuLvNoLt0J1sMu0DcC1sX6Nc/H9uUTwN34824r ys67dTQcmIQNRPc67Hh7DfaYZTHW+uif2ECeL5SUxmZF5qcqCJ4D5rDqHLA4h/g6pYzrlN8h IomoMkBEuluWlQEiIiIiIjWhbgIiIiIiIiIiXUaVASIiIiIiIiJdRpUBIiIiIiIiIl1GlQEi IiIiIiIiXUaVASIiIiIiIiJdRpUBIiIiIiIiIl1GlQEiIiIiIiIiXaYHcGUnQkRERERERESK o5YBIiIiIiIiIl1GlQEiIiIiIiIiXUaVASIiIiIiIiJdRpUBIiIiIiIiIl1GlQEiIiIiIiIi XUaVASIiIiIiIiJdRpUBIiIiIiIiIl1GlQEiIiIiIiIiXUaVASIiIiIiIiJdRpUBIiIiIiIi Il1GlQEiIiIiIiIiXUaVASIiIiIiIiJdRpUBIiIiIiIiIl1GlQEiIiIiIiIiXUaVASIiIiIi IiJdRpUBIiIiIiIiIl1GlQEiIi8Bril8taR0/CSQjtvaXN/BwO+BWcCrgXVv1Oa6RSQfceVR VcqrTlJUWZl1GS8i0qbeshMgIhnZHjgS2B3YDBgNLARmAy8DDwJ3AXcC95eURinOWcDxZSei BkYCewE7N4VNA/OcDpzURhx7NcKgecA5bawva+8FDsF++3is7FiBlR0PA78FLgYWedYxHPgE cADwFuC1jfmfAm4CpgIvZpTeduNqZ/ki8osUq1PLyr2odrkjIpXhFBQUah6+hWMlLtFnWQXS W7XwUmAbfbWkdPwkkI7bUq7ndTj6A+taieN5HE81wvoV2O5VCG/Gf7w4HKe1GUdfYH1PVeB3 g2NNHL9O8Psddoy8LWI9r8dxf8zyC3F8PIM0txtXu8sXkV/iyqOqlFedEIouK7Mq45OEvkBc T1VgeysoKFQuqGWASN0dBXyt7ERIpeyMPf1stjvwtxLSItV1BrBvyPf9DG03uCFwDbAFsKTp +7HAn4GJMXGNBi4BlgK/SpHWLOIqMq15+hEwpunvO8tKSAdQWSkiXU6VASJ11sPQioAl2AXs w1jT13WALYFdgDcWmjopy+iQ73TDEM4Bz2BdaO5u/HslduPY6Y4I/P0c1nT+TmA9rLn8QU3T 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 1jsceABYH9gg57hERERERERESlLPlgH7YU/xr2j6zgGXAOOBnVOudyXwAtBfQFwiIiIiIiIi JalnZcC2wBPA0sD3DzZNT2okMBq7sT8GeCdwZk5xiYiIiIiIiFRAb9kJSGU94JmQ719pmp7U hcDHG/9/FTgO+H85xSUiIiIiIiJSAfWsDMjSN4ELsDEC9gO+C6wFnNbmepOMxNDTZhwiIiIi IiIiKdSzMmAOMC7k+3FN05Oa2QgAv2r824e1GHixjbjibvTrN2yjiIiIiIiIdIh6jhnwIDAJ WDPw/faNfx9qY913YG8VeEMBcYmIiIiIiIiUoJ6VAdcAa7Cqrz/YLzkMeBa4K8E6hod8NwzY F3tq/2SGcYmIiIiIiIhUSD27CVwL/AX4HrA28A/s5nxn4GPAQNO8k4G/Aadizf8H/QpYANwH vAxsCBwAvK2x3hdTxCUiIiIiIiJSA/WsDHDAh4BvAScAY4G/AwcDVyVcx7XYTf17sf7/i4AH gMOBSzOOS0RERERERKRCetBQduVw6G0CIiIiIiIiUop6jhkgIh3r0EMPxTmHc44pU6aUnZy2 Zfl79tprr3+v69BDD80ohZ0ty23WaXmzSNp2naWvr+/f+7M5nH322YnXMXXqVB5//PEcUxlt 2223DU3/U089VUp6RETKosoAERERqb2dd9753zd1kydPjpzvggsu+Pd8++67b4Ep7EwrV65c LRRh9OjRHH/88dx2223Mnj2bZcuW8dRTT3HZZZex5557xi7vnCs8zWVLenyISHdRZYCIiHSt fffd998XyB/72MfKTo5I7UyaNIne3l56e3v5yle+knt8b37zm3nwwQc566yz2GWXXVhvvfUY OXIkEyZM4OMf/zjTp0/n3HPPpacnui/mww8//O809/b2MmPGjNzTLSJSRfUcQFBEpAvdd999 7L333gA8+uijJaemHrTNRDrH+PHjufHGG9loo40AuP7667n88suZN28eO+ywA0cffTSbbLIJ Rx11FIsXL+arX/1qySkWEak2VQaIiNTEvHnzmD59etnJqBVtM5Fq2HjjjfnCF77A+973PiZN msTaa69NT08PCxYsYPbs2Tz//PPcfffd/OlPf+L6668PXce3v/3tf1cEnHbaaZx88sn/nvb7 3/+eyy67jNtvv53x48dz/PHHc/nll/Pggw/m/tuee+45ent7OeGEE7jkkktqG4eIdB9VBoiI iIhIbvbcc0+uvfZaxo4dC1if/aVLlzJy5Eh6enrYbLPN2Gyz/8/enYc5Vd2PH38Pm4rIJqgg iyIqimIVFFS0iOO3/KpSEa1rq1KtFnCpWLWVKlas2mrVFiuKey2iiPtSLQoIyKLiRkUrKLIL IkWQZVju74+bCZlhMpNJbpJZ3i+e+0xy7sk5J5OEZ+4n53zO3vTs2ZPCwsIygwF77713fCnP nDlzuOGGG7ars3TpUi6//HKeeeYZ6tSpwzXXXJOTZKt77LEHdevWpWHDhtW6D0m1jzkDJFV5 xx9/PM888wyLFi1i48aNLF26lKeffpqjjjqqwsfuueeeDBw4kCeffJI5c+awdu1aNm3axIoV K3jrrbf47W9/S7NmzSpsZ5dddmHIkCFMnDiR5cuXU1RUxOrVq5k3bx5Tpkzh1ltvpXfv3ll9 PhVlxi8rY3smvzuAevXqMXjwYKZNm8aqVav4/vvv+fTTT7njjjto164dAFOmTCEIgrQygz/x xBMEQcDatWupX79+mXUmTZoUf1733XdfmXX23nvveJ3rr78+Xp7sd9ajRw+CIODFF1/cbiyJ x/jx48sdf6a/3yhE8R7P9uuQqt/+9rds3bqVIAiYMWMGLVu2rHQbUYric9+mTRtuvvlmZs6c yTfffENRURHLly/njTfe4LLLLqvUxV0mbWXj/4dUNG3alKeffpqmTZvy/fff8+tf/5pdd92V hx9+mPnz57PLLrvQtGlTfvSjH/H3v/+d1atXl9lO//7943kARo0axdatW8us9/zzz7NkyRIA Tj75ZHbYYYfInosk1USBRx6OoAqMwSP7R3sCuhLQrgqMpZoc5557blCsT58+wR133BEks2XL luDCCy9M2lbz5s2DrVu3Jn18seXLlwc9e/ZM2k7nzp2DhQsXVtjOsmXLsvp8evXqFa977rnn ZrUvIGjRokXw3nvvJW1j1apVQe/evYMpU6YEQRAEc+fOrfTrfeGFF8bbK+s1aNiwYbBx48Z4 nc8//7zCdo4++ugKf2c9evRI+rwSjR8/Piu/3xEjRsTrDh48OO3PS1Tv8Wy/DqV/d6UfV7du 3eDee++N13nxxReDhg0bVup30a1bt/jje/TokbTeyJEj4/VOOumkrHzui48rr7wy2LBhQ7mP nz9/fnDooYdW+PwybSvK9++wYcPidffaa69yx/2LX/wiXnfAgAElPgNl/Z9Rv379Mtt54YUX 4u106dKl3D4ff/zxeN3y3gvFR/H/YfPnz0/rc7h58+YgCILgkksuSevxuegj1c+Hh4dH7Tpc JiBlwwXAcGBXoAhoAKwErgMeyd+wqpsrr7ySE044gVmzZvHQQw/x2WefsdNOO3HiiSdy0UUX UadOHUaMGMGkSZP4/PPPt3t8nTrh5KcpU6bw6quv8uGHH7J8+XLq1avHXnvtRb9+/ejfvz8t W7bkhRde4JBDDmHhwoUl2igoKOCpp56iTZs2ADz66KOMGzeOxYsXs379elq0aMHBBx9MYWEh hx12WFafTy5/d3Xr1uWll16KP6e3336bu+66izlz5tCoUSN+9KMfcdVVVzF27FhWrVqV9jjf eOON+O3jjz+eKVOmlDh/zDHH0KBBg/j9jh070q5dOxYsWFCi3vHHHw/A2rVrmTlzZoX9Tp8+ nYKCAk466aT47ICzzjqLMWPGpDTuXL6W5YniPQ75ex0AGjZsyJgxYzj55JMBuP/++xk4cGCl t3xbs2YNkyZNAuC7776r1GNLi+Jzf+ONN8ZnR8yZM4dRo0bx3nvv8d1337H77rtz0kkncfHF F9O+fXtef/11unXrxldffZX1tiC3799OnTrFb7/66qsV1t+0aVOZ5Z07dwZg69atFSYD/c9/ /lPicdOnT09lqDValJ8PSTVL3iMStfJwZkDNPR4k4PvYa1z63/cEPFAFxliFj8Rvr4IgCO6/ //6gTp0629W74oor4nXuuOOOMtvaYYcdgk6dOpXb33HHHRds2rQpCIIgGDFixHbnDz300Hg/ t9xyS7ltNW7cOKvPpzIzAzLta9CgQfE6Y8eOLbOdQw45JFizZk28XjozA4Dgiy++CIIgCCZP nrzdudtuuy0IgiCYNm1asGTJkiAIguCCCy4oUaegoCD4+uuvgyAIgldeeaVSv7OTTjopfv7M M8/M2XszqpkBUbzHc/E6JJsZ0LJly2D69Onxc0OHDk37d5HqkcrMgEw/98ccc0x8xsaoUaOC evXqlfnYnj17BuvXrw+CIAiefPLJMutE1VaU79/KzAy4+eab43WPPPLIEp+ByvyfUfweXrx4 cYV1zz777HifN954Y4X1a8PMAA8PD4+yDnMGSFG6ADgTSLZssyFwFvDznI2oWps7dy6DBg0q c23oiBEj+Oabb4BwXXhZNm7cyKefflpuHxMmTGD06NFAuCa1tFatWsVvT548udy2Kvq2JdPn UxmZ9jVo0CAgfE4XX3xxme18+OGH3HzzzRmP9c033wSge/fu7LzzziXOFX/TPH78eCZMmFCi rNhBBx3EbrvtBpT8hjubMv39vv7669x2223cdtttvPfee2mPI4r3eLFcvw777LMPb7/9Nt27 d2fz5s2cf/75DB8+vMLHZaqoqCh+e+PGjWXWyfRzP3ToUAoKCpg7dy4DBw5k8+bNZT52ypQp jBw5EghfmyZNmmS1rWK5/L+o+NtogL///e/st99+lW5jxx13pF69cDLrmjVrKqyfWGeXXXap dH+SVFsYDJCiNJzkgYBiDYE/5mAsNcDjjz+edMro5s2beeeddwDo0KFDRv0UX4ztscceJS4C ABYvXhy/PWDAgKTJ1VKRq+eTaV9t2rThgAMOAMJkXN9++23Sfh5++OGMx1p84Vi/fn2OPfbY eHmzZs049NBDgfAitLhe6YRtiReluQoGZPpavvDCC1x77bVce+21TJs2LWvjLFbee7xYLl+H I444gmnTptGxY0fWrFnDiSeeyKOPPlrJZ5WexAR1yZLVZfK5b9KkSfx3MXbs2KTvk2LFSSrr 1q3LEUcckbW2EuXy/6LXX3+dV155BYAf/OAHfPLJJ7z99tv06tWLhg0b0rlzZ+rWrVtuGzvt tFP8dmIwJ5nEII/Z9yUpOYMBUlTaE+YISEULoG0Wx1JDzJ49u9zzK1euBKBx48bl1uvWrRt3 3303M2fOZOXKlRQVFZXIGH/33XfH67Zo0aLEYz/66KP4H8b9+/dn/vz5jBgxgtNPP53WrVvn 5flku68uXbrEb1e07vvrr78ucw16ZRR/Iw0lLyh79epFnTp1WLduHdOmTYtfYLZq1YoDDzxw u8d88803fPjhhxmNJVW5fC1Tkcl7vFiuXocTTzyRCRMm0LJlS5YtW8YPf/hDXn/99fSeeBpS CQZk8rnv2rVr/OL2mmuuYfPmzeUezz//fPyxu+++e9baSpTr9+9pp53GX/7yFzZs2EDdunU5 8sgj6dy5M61atWL27NmsXLmS0aNHc+SRR5b5+PXr18dvJ+auSCZxB4F169ZlPP5ly5Ztt9NI 4lH8Gt17773l1iveGjFffUhSaQYDpKi0JEwWmIoiYLcsjqWG+P7778s9X5xgrDiJWmn16tVj 1KhRvPPOO1x22WUcfvjhNG/evNxv+Up/ixQEAf369YtPdW3dujWDBg3iqaeeYvHixcybN4+7 7767xEVRtp5PZWTSV/PmzeO3ly9fXmFfX3/9dSVHt/3jiy9OCgsL4+XFF5eTJ0+mqKiIr776 innz5pU4V69ePX74wx8CMHHiRIIgyGgsqcrla1meKN7jxXL1OgwePDg+hrPPPpv3338/1acb iVSCAZl87ouXSkD4+tetW7fCo9iOO+6YtbYS5fr9u379eoYMGUKbNm0YMGAAjz32GMuWLYuf b9KkCWeddRZvv/02I0aMiG8hWGzDhg3x5RGNGjWqsL/EpQGpLCuQpNrK3QSkqCwn3DUgFQ1i 9ZVVN910ExdeeCEA06ZN4+9//zvvvvsuS5YsYd26dfE/LgcOHMg999wDsN0foRBOGe7VqxdH H300p556KscccwyHHHIIDRo0oEOHDlx22WUMHjyYm266iWHDhuXs+dUkb775JgcddBBdunSh RYsWfPPNN/ELzcQp52+88Qb77LMPxx9/PH/72984/PDD43/452qJQFUS1Xu8WC5eh7Fjx3La aadRUFDAo48+yvHHH5/VHRdKSyUYAOl/7ovXtgNccskl3HfffWmPNcq2qoKVK1fy8MMP8/DD DzNixAhOPPFEzjzzTPr27cvAgQNp2rQpgwYNYtGiRdx6660lHrtgwQI6dOhAq1atqF+/frlL Jtq1a1ficZm6/PLLSyxVKO3BBx+kTp06PPbYY/GcGmWZMWNGXvuQpNIMBkhRWUC4fWAqM8dX AJnNrFYFdtxxRy699FIgvEg65phjkm5V1qxZs5TanDp1KlOnTo233717d/r168dFF11Ew4YN ueGGG/jggw947rnnonkSeZKYIyDxm8lkUqlTkTfeeIPLLruMgoICevfuzeTJk+NbkpW+CP3l L39Jr169qFu3bl7yBVQV2XiP5+J1eOihh3j55Zd56KGHaNu2LZMmTaKwsJBPPvkkpTFm6sUX X2TvvfcGSk4/T6ayn/sVK1bEH5u4rV46omyrKtqyZQszZsxgxowZPPTQQ7zzzjs0a9aMyy+/ nNtuu63EDJP//Oc/dOjQgTp16nDAAQfw0UcfJW33oIMOKvG4TD355JPlnn/ggQeA8HP4yCOP VNk+JKk0lwlIUboOqGh54jrgdzkYSy3XqVOneEb0MWPGlLtneXmJtpLZsGEDkyZN4oorrojv jw7UiPWaiX9kH3744eXW3X333Ut8C5euSZMmxV+jwsLC+MXlypUrS0wjnzBhAkEQ0KRJE7p2 7Rqvt3DhwrS+Xc7VsoJsyMZ7PFevw6OPPso555zD5s2badWqFRMnTuSQQw5JaYyZWr9+PfPn z2f+/PmVfmwqn/tZs2bF31c//vGPy52JUZEo26rq5s2bx7hx44Aw0WXp3BaJuxKUTl6ZqE6d Ohx33HFAuNNDrpehSFJ1YjBAitIjwBMkDwisA0YD/8jVgGqvxPWy5WWT3nvvvfl//+//ZdTX hAkT4hmukyVnq04WLVrEnDlzADjllFNo2rRp0rrnn39+JH2uXr2ad999FwjXoRdfXBZfdBZb sWIFH3/8MQAnn3xyPOFYYvK7ykj8Zri8NdZVUTbe47l8HcaMGcPpp59OUVERLVu2ZMKECRUG n6qSZJ/7FStWxLcj3G+//TIKEEbZVnWQuNVh6S0Ux40bF38P/vKXv0yaz+AnP/lJPMnjiy++ mHT7SEmSwQApehcCA4HFwEZgTeznIuAS4KL8Da02mTdvXvwPx7POOqvMC71mzZrx5JNPlpts rVu3bhx88MHl9tWrV694huvixGrVXfH68saNGzNy5Mgy//A++OCDue666yLrs/hCskOHDvTr 1w/YtlVaouJp6Jdeemk8a3i6SwQWLVoUv53O/ufpOuWUU7j99tu5/fbbOfroo9NqI6r3eGm5 fB2ee+45TjnlFDZs2ECzZs0YP348Rx11VKXaqKz+/fvHf/fFW2iWlunn/oYbboi/NiNHjiyx VWNZOnToEF/yUVqUbeXDGWecUWKHkmTatGkTf7999dVXrFq1qsT5+fPnM2bMGAAOOOAAbrzx xu3aaNWqFXfddRcQBhZK5x2QJJVkMEDKhkeBNsC+wHFAR8KtBJ0RkDMrVqzgpZdeAsKt8qZO nco555zDYYcdRo8ePRgyZAgfffQRhx9+eHw9cFl69OgR32Zs2LBh9O3bl65du9KlSxdOOOEE brvttvh2Xps3b2bkyJE5eX7ZNnLkyHgiqjPOOINJkybRv39/OnfuzBFHHMHvf/97pk6dyqZN m/jiiy+AzKfcJ15INmnSZLuy0vWK6ySrl4q5c+eyZMkSeguo4QAAIABJREFUAC6++GJ+9rOf 0blzZzp27EjHjh0rvX1kqgoLCxkyZAhDhgzh0EMPTauNqN7jpeX6dXj11Vc58cQT+f7772nc uDGvv/56fJp3Npxwwgnx3/0+++xTZp1MP/cTJ07k+uuvB8KA2ptvvsmYMWM444wzOPzww+na tSt9+vTh2muvZeLEicydO5dzzjmnzLFE2VY+HHPMMXzwwQf8+9//ZsCAAXTq1CkeuCooKODA Aw/kyiuv5N1336Vly5YA8Qv60q655pr47iVDhw7l+eef5/TTT+eEE07gN7/5De+++2582dKf //znCrdQlKTazgSCUjYtxESBeXTxxRfTqVMn9t13Xw477DAef/zxEue3bt3K9ddfz4oVKyr8 drZbt25069Yt6fm1a9cyYMCAGrM+dcuWLZx00km89tprHHbYYfTs2ZOePXuWqLN69Wp++tOf 8oc//IEOHTqwYcOGjPqcOnUqGzZsiF8ofPXVV8ydO3e7em+99RabN2+OZ1r/9NNP4xf0lbV1 61aGDRvG/fffT/PmzXnsscdKnH/jjTdKbLNX1UT5Hi+Wj9fhzTffpE+fPrzyyivssssuvPzy y/Tr14/XXnstrfaiksnnfvjw4Sxbtow777yTRo0accYZZ3DGGWckbau8nQ2ibCvXli1bRkFB AYWFhSU+S0EQUFBQsF2Cv/vuu4+77767zLYWLlxInz59eO6552jfvj19+/alb9++29W75557 +O1vfxvtE5GkGsiZAZJqrKVLl9K1a1duuOEGPvroI9avX8/69ev58ssveeSRRzjqqKO46aab ym1j1KhR9O7dm+HDh8e/dfvuu+/YvHkzK1euZOrUqdxwww3su+++jB07NkfPLDe++eYbevTo waWXXsr06dNZvXo169ev5/PPP+evf/0rP/jBD3jjjTfi3wxnegGyYcMG3n777fj9ZN8yr1mz hpkzZ8bvp5svoNioUaP48Y9/zIsvvsiSJUvi68Crgyje46Xl63WYMmUKhYWFrFq1ip122onn n3++zAu9XIjqc//AAw/Qrl07rr76av7973+zdOlSNm7cyMaNG1m6dCmTJ0/mz3/+M717964w r0OUbeXS8OHD6dixI0OGDOGFF15g7ty5fP/99/HzGzZs4Msvv+SJJ57g+OOP55JLLil3ltEH H3zAQQcdxDXXXMOMGTP49ttv2bhxI1999RWjR4+mV69eDB48uFonB5WkXAo88nAEVWAMHh4e HhkeO+ywQ7Bhw4YgCILgwQcfzPt4PDw8sn8MGzYsKLbXXnul1ca9994bzJ07N+/PBQimTJkS BEEQzJ8/P+9j8fDw8Mjl4cwASVLaTjvttHjyuMqsS5dUM3z55ZcEQUAQBNx+++0pPy6f39wf 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 GuifQr1LYnUlqQzdunXj4IMPLrdOr169aNCgAcB2Sf/uvDNMSlK3bl3+8Y9/lDk1vl27dtxz zz3bPSZTixYtit/eb7/9ImmzIpMnT2bTpnC7kyuvvLLM53vooYdy++2352Q8kiTVBG4Rrdoi mpwB/YEPUqjXjdSCBpJqpR49evC3v/2Nd999l5dffplZs2axePFiNm3axO67705hYSG/+tWv gDCx38iRI0s8/pFHHuGnP/0pffr0oXv37nzwwQfcfvvtzJo1i3r16nHsscdy1VVXxafU//Wv f43nJcjU3LlzWbJkCa1bt+biiy9mzpw5zJo1i40bNwKwbt26crdGTMeKFSsYPXo05513Hvvv vz8zZszgzjvvZN68eTRt2pQTTjiBCy64gGXLlrF8+fKcBSkkSarO3CJatUmQ8REQMDSFev8g YFME/dWEI6gCY/DwqGLH4MGDg1SsWbMmOP3008tso2HDhsEzzzxT7uO3bt0a/OUvfwnq1KlT ZhvnnntuvG6fPn1SHv9FF12UtM/x48dn5XfWvHnz4MMPP0za75dffhkceOCBwfTp04MgCILZ s2fn/XX28PDw8PCoysd0CIIyjulVYGweHlEe0cwMSMVOhFnUvs5Zj5KqmVGjRvGf//yH3r17 07NnT9q0acNuu+1Gw4YNWb16NZ9++imvv/46999/P8uWLSuzjXXr1nHqqadywgkncP7553P0 0Uez++67s2XLFhYvXsykSZMYOXIks2bNysr4Fy1axK9+9Su6du1KixYt4ksasuXbb7/lqKOO 4oorruD0009n3333ZevWrcyfP5+nn36au+66i9WrV2d1DJIk1SRDCXMEJC4VcIto1UQFhFGB yktcFnAIsIzkF/r1gPZAI+AB4KK0eqxZAsre8lCSJElSXhXiFtGq+dIPBlT2Uf8DXgAuj92u 7QwGSJIkSZLyJP1lAs0Sbq8CbgaSJawuAtal3ZMkSZIkSYpQ+sGAxG/3fw28jd/4S5IkSZJU DaS/TECZcZmAJEmSJClP6kTSytNA/xTqXRKrK0mSJElV1NXAGmBj7OfV+R2OlBXRbC3Yn5K7 CyTTjdSCBpIkSZKUB1cDt7DtW9MGsfsAf8rLiKTsiGZmQKp2ADbntEdJkiRJStnv2f4iqU6s XKpJchcM2AnoAXydsx4lSZIkqVIaVLJcqq7SXyZQelnAIOC0cnppDzQCHki7R0mSJEnKqiLK vvAvyvVApCxLPxhwSKn7e8SOZP4HPAb8Ju0eJUmSJCmrbqJkzgCArbFyqSZJPxjQLOH2KuBm 4PYkdYuAdWn3JEmSJEk5UZwk8PeEMwSKCAMBJg9UTVNAuON9Zq4A3gZmZtxS7REQ/vYlSZIk ScqxaIIBxZoBZxJuIbgr8BQwOnauE9CGMGjgLAGDAZIkSZKkvEl/mUBp/YGHgMYJZYlJBg8A ngHOYVuAQJIkSZIk5Vw0WwseCYyJtTYM6F1GnZeBNcApkfQoSZIkSZEqBKYDCwgvXRbE7hfm c1BSlkQzM+A6winvfYCpSeoUAe8BB0fSoyRJkiRFppBwAnPLhLJGQNtY+dnA+DyMS8qWaGYG HEWYPDBZIKDYUsK8AZIkSZJUhQynZCAgUcvYeakmiSYYsDOwPIV6LTBpniRJkqQqp0mG56Xq JppgwGKgcwV1dgC6AF9E0qMkSZIkRWZ1huel6iaaYMCrQEfgF+XU+T2wO/BSJD1KkiRJUmSG AiuSnFsROy/VJAWEO95npi3wIdAUGEW4heC/gHsIs2ycR7iLwNeECQSTfcpqkwCXTEiSJElV SCFhboDWQDNgFbCEMBBg8kDVNNEEAwCOAMaRPEHgEqAv4Y4CMhggSZIkScqb6IIBECYS/Bnw f0B7oC6wCPg38BDhZp0KGQyQJEmSJOVJtMEApc5ggCRJkiQpT6JJIFiWnWOHJEmSJEmqUqIN BpwIvEy478ba2LE6VnZipD1JkiRJkqQ0RbNMoA5wPyW3FlwJbAVaJpQ9CPwyVl7buUxAkiRJ kpQn0cwMuJQwELAQuBBoBLQAdiNcKlB87hfA4Eh6lCRJkiRJaYpmZsAcoB1wIPBVkjrtgdmE QYEDM+6x+nNmgCRJkiQpT6KZGdABGE/yQACxc+NjdSVJkiRJUt5EEwz4BticQr1NwIpIepQk SZIkSWmKJhjwHNCbME9AMrsChcAzkfQoSZIkSZLSFE3OgMbAG0AD4BrgX6XO/wj4E1BEGDRY k3GP1Z85AyRJkiRJeZLezIAppY5XCC9uuwCvAv8DPood/yMMDnSJ1Xk10yHHNAZGAEuBDcD7 wOmVePwxwEjgE+B7YBHwPNA1C31JkiRJklSFpDczINO5BJl+I14ATAQOA64DPgfOA84AzgSe TKGNlwh3OHgW+AzYg3CLxD2BPoQzHaLqqyzODJAkSZIk5Ul6wYA2Gfa6KMPHnwqMAy4EHoyV FQAzCC/q9wK2VtBGR2BuqbI2wH8JZzv8X4R9laWKBQMKgeFAE2A1MJRw8wdJkiRJUs0TTc6A XPsH8FOgKbA+oXww8DegOzAzzbY/AuoCnbPcVxUKBhQCo4GWCWUrgLMxICBJkiRJNVE0uwnk 2kHAPEpenAN8nHA+HbsB+wEf5KCvKmQ4JQMBxO4Pz8NYJEmSJEnZVz2DAbsC35ZR/m3C+cqq AzxA+I39zVnuq4ppUslySZIkSVL1Vi/fA6gyRgAnAj8j3GEgU9Vo8cXqSpZLkiRJkqq36jkz YCXQvIzy5gnnU1VAGAi4hDBJ4OiI+iqo4KhChhLmCEi0IlYuSZIkSap5qmcw4GPC3QAalirv Evs5O8V2CoB7gYGEgYCHs9hXFTaeMFngDODT2E+TB0qSJElSzVU9dxPoBzwD/BIYFSurQ3gV uzupbfdXANwP/IIwEPBQFvsqSxXaTUCSJEmSVLtEkzOgJbAP8AWwPKG8DXAjcDCwgDA9/Qfb PbryngPeAu4EdgE+B34OdAPOpOTFeQ9gWmwcwxLK7yAMAjwPfAeclnCuCHghjb4kSZIkSaoG ogkGDAUuI9xmrzgY0Ah4G2gbu3848H+E0+vnZ9hfAPQF/ghcDTQlnN9+BvBUim0cFfv5k9iR aHWszaj6kiRJkiSpColmmcBHQH3ggISyQYSJ+Z4Cfg/8P+CuWNmlGfdY/blMQJIkSZKUJ9EE A1YSzgI4OaHsNaAQ2BNYFiubBewIHJhxj9WfwQBJkiRJUp5Es5tAI2Btwv26QHfC/ADLEso/ YduyAUmSJEmSlBfRBAOWAnsn3O8BNAEmlqpXD9gcSY+SJEmSJClN0QQDZgBHEGbkbwFcHyt/ qVS9TsCSSHqUJEmSJElpiiZnwKGEAYH6CWXTgJ5s23pvT2Ah8ChwQcY9Vn/mDJAkSZIk5Uk0 Wwu+D/QGrgB2A94DhrMtEADQD1gAvBxJj5IkSZIkKU3RzAxQ5TkzQJIkSZKUJ9HkDJAkSZIk SdWGwQBJkiRJkmoZgwGSJEmSJNUy6SUQnB37eSvweML9VB2UVq+SJEmSJCkC6QUDOsd+tih1 X5IkSZKquULCzdGaAKuBocD4vI5Iil56uwnsGPu5CdiScD9VGyrdY83jbgKSJElSlVMIjAZa JpStAM7GgIBqFrcWzBeDAZIkSVKVMx3oXkb5DKBHjsciZZMJBCVJkiQppkkly6XqymCAJEmS JMWsrmS5VF0ZDJAkSZKkmKGEOQISrYiVSzWJOQPyxZwBkiRJUpXkbgKqDQwG5IvBAEmSJElS nkSzTOB24Ba8uJUkSZIkqRqIZmbAJmAmcHTGLdUezgyQJEmSJOVJNDMDFkXWkiRJkqQIFALT gTmxn4X5HY6kKiaaS/ixwGFA20hakyRJkpSBQmA00B3oFPs5GgMCkraJZplAQ+A1oClwGTAh 4xZrPpcJSJIkKUumEwYASpsB9MjxWCRVTfUiaeX1WEudgTeBlcACYF2S+j0j6VWSJElSGZpU slxS7RNNMKB04sBdY4ckSZKknFtdyXJJtU80wQBzBUiSJElVxlDCHAEtE8pWxMolCaLKGaDK M2eAJEmSsqgQGE64NGA1YSBgfF5HJKkqMRiQLwYDJEmSJEl5Es0ygWLNgDOBboQ5A54inJ8E 4Z4mbYC3SZ5YUJIkSZIkZV10wYD+wENA44SyDxJuHwA8A5zDtgCBJEmSJEnKuTqRtHIkMCbW 2jCgdxl1XgbWAKdE0qMkSZIkSUpTNMGA6wjXv/cBbgQmlFGnCHgPODiSHlUFFALTgTmxn4X5 HY4kSZKUsUJgLWGKr+JjRl5HJGVHNMGAo4CZwNQK6i0lzBugaq+QcLVHd8J0EN1j9w0ISJIk qboqBF4Fdi5VfgQGBFTzRBMM2BlYnkK9FphBv4YYTsl9a4ndH56HsUiSJElRGE7ypGpH5HIg Ug5EEwxYDHSuoM4OQBfgi0h6VJ41qWS5JEmSVNX5t6xqk2iCAa8CHYFflFPn98DuwEuR9Kg8 W13JckmSJKmq829Z1SbRBANuBVYBo4D7gB/FylsQ7h7wLGGSwa+BOyPpUXk2FFhRqmxFrFyS JEmqjoYCm5Ocm5nLgUg5UECYIDNzRwDjSJ4gcAnQl3BHAYW/9WqeP6GQcF1VE8Io6lBgfF5H JEmSJGWmEHiOkkkEZxImzJZqkuiCARB+Yn4G/B/QHqgLLAL+DTwErImsp+qvBgQDJEmSJEnV UzTBgEaEm3HmUmPgj0B/oBnhZvd/BMam+Phdgd8BXYHDgF2AC4BHStXrBryTpI3jgImVGHMi gwGSJEmSpDxJtnNG5awinP4/ifDieCrwXSQtl60AeJHwIv464HPgPOAp4EzgyRTaaAWcD8wC XgNOq6D+n4D3S5V9kvKIJUmSJEmqMqKZGfApsH/C/S2EF84TCQMEU4D/ZdzLNqcS5ie4EHgw VlYAzAD2APYCtlbQRp2EOr2ACZQ/M+Bkot0JwZkBkiRJkqQ8iWY3gU6E37SfBYwk/Ka+G3AV 4Tf4KwlnDvwF+EkE/fUDioDRCWUB8BjQNtZ3RSoKFpRlF6B+Go+TJEmSJKkKiSYYALAMGAP8 CjiA8Bv6M4B7gc8Ip/T/mjA1Z6YOAuYB60uVf5xwPmqjCZc+bCCcKdA3C31IkiRJkpQD0QUD SvsfsDTh2Bhh27sC35ZR/m3C+aisAx4FLiVcKnAl0AJ4Hjg7wn4kSZIkScqRaBIIAuwA9AB+ SLgG/0hgx9i5ZYQzAiaSfvb9fPmEMNFgon8QzkK4lZJLFRJFt2GjJEmSJEmRiiYYMIEwEJB4 8f882y7+P42kl21WAs3LKG+ecD6bviUMbgwkzJWwtIw6FSUHNFggSZIkScqTaIIBvWI//wP8 AXia9BL0pepjwi0EGxJO4y/WJfZzdhb7LlacSHBLDvqSJEmSJClC0eQMeA1YC3QGngRWAM8C lwOHEP0Wes8SXoyfk1BWB/g5sBB4N8K+yto9oBVwCmESw+UR9iVJkiRJUg5EMzOgT6ylbmzL GXA84QUzhNPq32LbsoEPM+zvuVh7dxJu9/c5YSCgG+GMgcRZCT2AacCNwLBS7fQFGhAGMYg9 fm3s9vPAJuApwl0L3iNcftABuJgwSeGFGT4PSZIkSZLyoIBsrV6vC3QlDAz0AnoTJhks7jVT TYA/Av2BpoR5Cf5IePGeqLxgwP9i7ZSlWez8IOBcYN9Y3f/F2rsVeDuD8QdEP2NCkiRJkqQU ZC8Y0I5tswR6EX6jnthrbWcwQJIkSZKUJ9FtLdie8KK/OACwd8K5ImAKMInqt7VgFhQCw3uE Ew1WA0OB8fkdkiRJkiSpFolmZsCXwF4J9zcCMwkv/CcRTqdfn3EvNUIhMBpomVC2AjgbAwKS JEmSpNyIJhiwAZjBtgSB02Jl2s50oHsZ5TMI0xvyU4JzAAAgAElEQVRIkiRJkpRt0SwTaIoX /ylKlq8wWbkkSZIkSVGrE0krBgJStrqS5ZIkSZIkRS363QSOBo4B9ozdXwxMBqZG2ku1Zc4A SZIkSVK+RRcM6AQ8DnRNcv494Fzg00h6q9YKgeHdockMdxOQJEmSJOVeNMGAPQkv9ncHlgBj gfmxlvcCTo/V+Ro4LFantgsIf/uSJEmSJOVYNMGAe4FLgLuBawi3FkzUALgFuDJWd2DGPVZ/ BgMkSZIkSXkSTTDgK6AI2B/YmqROHWAOsAPhbIHazmCAJEmSJClPotlNoBXwPskDAcTOzYrV lSRJkiRJeRNNMGA10C6Fem1xDz1JkiRJkvIsmmDAVKA7cGo5dfoSbjvoFoOSJEmSJOVVNDkD egBTYq2NA/5JuJsAQHvgLMIdBSAMCMzIuMfqz5wBkiRJkqQ8iSYYAOEF/yhg5yTnvwcuBMZE 0lv1ZzBAkiRJkpQn0QUDAFoD5wM9Y7cBlhDOGngYWBpZT9WfwQBJkiRJUp5EGwxQ6gwGSJIk SZLyJJoEgpIkSZIkqdowGCBJkiRJUi1TL61Hzc6w14MyfLwkSZIkSUpbejkDMs0y4Fp5cwZI kiRJkvImvZkBO0U8ilqmEBjeA5oAq4GhwPj8DkmSJEmSVIu4m0COFQKjgZYJZSuAszEgIEmS JEnKDYMBOTYd6F5G+QygR47HIkmSJEmqndLbTaBbRL0fHlE71UiTSpZLkiRJkhS19IIB7wAv AUen8dgC4FjgFWBmWr1Xa6srWS5JkiRJUtTSCwZcBRwFTAHmAn8AepP86+1mwI+AW4AvgUmE c+WHpNV7tTaUMEdAohWxckmSJEmSciH9nAHNgN8AvwB2i5UFwDJgFbAGaAw0j50v3kbva2AU cAfwvzRHXc0VAsO7Q5MZ7iYgSZIkScq9zBMI1gdOAX4MHAPsU0aducBk4GXgBWBTRj3WDAHb AiSSJEmSJOVQ9LsJ7Ey4b14Twq+9lwPrIu2hZjAYIEmSJEnKE7cWzBeDAZIkSZKkPEkvgaAk SZIkSaq2DAZIkiRJklTLGAyQJEmSJKmWMRggSZIkSVItYzBAkiRJkqRaxmCAJEmSJEm1jMEA SZIkSZJqmWiCAS2BHsBupcrbAA8CM4GngR9E0pskSZIkScpAARBk3MrdwGXAQcB/YmWNgE+A tgn11gBdgPkZ91j9BYS/fUmSJEmSciyamQHHAZ+yLRAAcB5hIOApYH/gCmAXYEgkPUJjYASw FNgAvA+cXonH7wrcAUwEviO8OD8/S31JkiRJklSFRBMM2BOYW6qsL7AVuBz4L+HsgfeB4yPo rwB4kTDgcAvQD/iMMPBwRopttCK8+N8EvJblviRJkiRJqkKiWSawEXgGOCt2vy6wEpgHdE2o 9zjwE8IZApk4FRgHXEiYkwDCZzID2APYizAQUZ46CXV6AROAC4BHstBXWVwmIEmSJEnKk2hm BiwF9k643wNoQjgFP1E9YHME/fUDioDRCWUB8Bjh0oRuKbSR6gV8FH1JkiRJNVAhMB2YE/tZ mN/hRGYB4Z/8xceC/A5HyopoggEzgCOA04AWwPWx8pdK1esELImgv4MIZx2sL1X+ccL5qOSy L0mSJKmaKCT8vqw74Z/53WP3q3tAYAElc6ATu29AQDVNNMGAWwm/8R8LrAD+D5gGTEqosyfh TgIzI+hvV+DbMsq/TTgflVz2JUmSJFUTwwl3GE/UMlZenZUOBFRULlVX9SJp5X2gN+GOAbsB 7xH+L5A4Fb8fYTjt5Uh6rPoyz8QgSZIkVVlNKlkuqWqJJhgAMCV2JDMidkRhJdC8jPLmCeej km5fFSUHNFggSZKkamx1JcslVS3RLBPItY+BjkDDUuVdYj9nV9O+JEmSpGpiKOEK4UQrYuXV 2cJKlkvVVXozA07LsNenM3z8s8DPgHOAUbGyOsDPCT+l72bYfr76kiRJkqqJ8cDZhKuDmxDO CBgaK6/O2rF9EsGFsXKpJkkvGDA2w14rmkJfkeeAt4A7gV2AzwkvzrsBZ1IyV0EPwmSGNwLD SrXTF2gAdI7d7wasjd1+HthUyb4kSZKkymhPuBvXCqpluvrxVP+L/+20h3YtgAuB/Qh3Tvtd fockZUMB6axev72MsrbAT4Eiwl0EFhBeKO8FHAvsQBhEWABcldZYS2oC/BHoDzQFPo3df6pU vfKCAf8jeYaTZrHzlemrMgIyD4pIkiSperqA8Cv1XQn/fm5AmIvqOuCR/A2rVit+TVpR9t/p qwmvBaQaIr1gQGkdgenABOByYEmp862AvwLHAUcAX2TcY/VnMECSJKl2epBwhmnpnFQA64An CL+VVu6U95okCqiuWdek7UTzVr4N+J5wXX3pQADA0ti5tcCtkfSoWqSQMNY0J/azML/DkSRJ St8FlH/R2RA4i3BZqnKjotckUQGwKrvDkXIlmpkBK4HXCf/jKs/jQB/CdVG1nTMDUlIIjAZa JpStIExWU+PWp0mSpJpvMdA6xXptsjwWhVJ9TRL5d7xqgGhmBjQEdkuh3m6kFnGTYoZTMhBA 7P7wPIxFkiQpI+0JcwSkogUl09krOyrzmiTyj1HVANEEAz4AfkiYKDCZY4HesbpSipLld0xW LkmSVGW1JEwWmIoiUvuyTZmpzGuS6MioByLlXjTBgJuBusBrwEjCRIEdYkcv4N7YubqxulKK VleyXJIkqcpaTrhrQCoaxOoruyrzmiSaFvVApNyLJmcAwADgbyRfBrAOGAw8HElv1Z85A1Ji zgBJklSjpLo+fREuE8gVcwaoloouGADhh+g84Bi2faCWAFOARwk/aAoZDEhZIeGyrCaEMwKG YiBAkiRVU+cD91B+Hq11wCXAP3IxIKX0miRaBTTP2miknIk2GKDUGQyQJEmqnR4g3IWrrIvP dYTTIi/K6YhU3muSKCCqhdZS3kUbDGgJHEU4K2CHcurdFVmP1ZfBAEmSpNrrPMJcWi0IE9g1 IFwL+TucEZAvxa9Ja8r+O90ZAaphogkG1AX+AgwE6qXYa21nMECSJEltCXcN+JowT4Dyr/g1 +TlwEOGS5xvyOiIpK6IJBlwP3EgY1XwGmAN8V059ZwYYDJAkSZIk5U00wYAvCafTHA28m3Fr tYPBAEmSJElSnkQTDCgC3iEMBig1BgMkSZIkSXkSTS7MJYR5AyRJkiRJUpUXTTDgn8AhQLtI WpMkSZIkSVkUzTKBHYCXCbfauAD4MOMWaz6XCUiSJEmS8iSaYMAUwmUC3WP3FwMLga1J6vfM uMfqz2CAJEmSJClPogkGVLYFL4INBkiSJEmS8qZeJK20jaQVSZIkScq/9sBNQAfgLeB3+R2O lA3RzAxQ5TkzQJIkSapaLgAepOy/01cDTXM7HCmbDAbki8EASZIkqep4EBhQQZ2AqPZjk/Iu mmUCiY4GjgH2jN1fDEwGpkbekyRJkiRl7oLYUZECYBXQLLvDkXIhupkBnYDHga5Jzr8HnAt8 Gklv1Z8zAyRJkqSqYTHQuhL1/TteNUA0wYA9CS/2dweWAGOB+bGW9wJOj9X5GjgsVqe2Mxgg SZIk5V97YC6VmzN9MzA0O8ORciWaZQJDCQMBdwPXABtLnb8GuAW4MlZ3YCS9SpIkSVJmWlL5 L+mOzMZApNyKZmbAV0ARsD+wNUmdOsAcYAfC2QK1nTMDJEmSpPxrB8zDmQGqdaLJhdkKeJ/k gQBi52bF6kqSJElSVbAAWF7JxxgIUA0QTTBgNWFErSJtY3UlSZIkqaq4jtTnS6/K5kCk3Ikm GDAV6A6cWk6dvoTbDrrFoCRJkqSq5BHgoRTqBUDz7A5FypVocgb0AKbEWhsH/JNwNwEIs3Oe RbijAIQBgRkZ91j9mTNAkiRJ2dYeaAGsIJwOr/KdRxgUKOsr01UYCFCNEk0wAMIL/lHAzknO fw9cCIyJpLfqz2CAJEmSsuUCYDiwK2Gi7wbASsLp8I/kb1jVRlvgBsIE6W/Gbks1THTBAIDW wPlAz9htgCWEswYeBpZG1lP1ZzBAkiRJ2fAgcCbQsIxz64AnCL+kk1SrRRsMUEoKgeHdocmM MJ/iUGB8nsckSZKkGuACYARlBwKKrQN+BTyWkxFJqqIMBuRYITAaaJlQtgI4GwMCkiRJytBi ts3QrahemyyPRVKVFs1uAjsDnQjXJCXTPFYnWU6BWmI4JQMBxO4Pz8NYJEmSVIO0p/y/xxO1 IFwXL6nWiiYYMASYA3Qup84BsTqXRdJjtdWkkuWSJElSSloSJgtMRRGwWxbHIqnKiyYY0Bf4 CnirnDpTgXnAKZH0WG2trmS5JEmSlJLlhLsGpKJBrL6kWiuaYEAH4JMU6s2J1a3FhhLmCEi0 IlYuSZIkpW0B4faBqVgBLMziWCRVedEEAxoC61Ootx5oHEmP1dZ4wmSBM7rDp8AMTB4oSZKk iFxHuFtAedYBv8vBWCRVadHsJvA54VSjvYGtSerUIVwmsBXYJ+Meq7+A8LcvSZIkRekB4CzK 3l5wHeHWVhfldESSqqBoZga8CrQDflNOnd8Ae8XqRqEx4R6qS4ENwPvA6VlooxvhhXtZR6/0 hi5JkiRlzYXAQMLtAzcCa2I/FwGXYCBAEhDVzIC2wEdAU8L57vcDc2Pn9gEuBgqBVcAhZL4+ qQCYCBxGOBXqc+A84AzgTODJCNvoBrwD/IkwWJDoTdJPvOLMAEmSJGVbW8JdA74mDAZIUkw0 wQCAo4FxwO5Jzi8F+gPTIujr1FhfFwIPxsoKCBfg70E4AyHZcoXKtlEcDDgZeCmCsRczGCBJ kiRJypNolglAuHXgfsAVwIvAB7HjReAyYH+iCQQA9CPcG3V0QlkAPEYY/eyWpTZ2AeqnMV5J kiTp/7d35+FyVHXCx783gbAECBKCShKTV1BhREaEIQg6I8ooMmw6IJss0eCLgoyM8/qMgIoa kFFeRQRxBoJRfIIT2UbQkZfAiIImURYF2ZdIEraQyJKFBJLz/nHqkrqd6r5V3dX795PnPNX3 1Ok651b/+qbqVNU56hqfY/3TFS8mP0u9ZqNSt/YC8O0kNdMuxMEIK2cwuDu1fn7J25hF7AxY B9wBfBX4aaFWS5IkSepwnwO+xvqrpqOSnyE+OSz1ivLuDGilscCyjPxlqfVlbWMl8APg08RH Bf4Z2Bb4L+KcgJIkSZJ6xhfY8CRpRJIv9ZJy7wx4DXHwvT2IJ9OzWX8b/k7ABOA3DD/3aSe5 FzihIu9y4h0E5zL0MYO0ckZikCRJktRCowrmS92qvDsD/hFYAHwX+BhwCHEMgUE7AzcCh5ZQ 11Jgm4z8bVLrm7mNZcC1xLEFXl+lzMAwSZIkSVLHWVMwX+pW5XQGvBP4cbK1s4D3ZpT5GXH0 jTI6A+4GdgQ2r8jfNVne04JtDA4kuDZHXZIkSZK6wlfZcGKydUm+1EvK6Qw4g3i1e3/gy8D/ ZJRZA9wOvK2E+q4hnowfk8obARwHLAR+X+I2smYPeD2xU+MR4JkiDZckSZLUyb4OfB5YTjyF WZ787OCB6jXljBmwN3Hk/duGKfck+ab9G861wK+AbxFH+H+IeBK/B3HMgnRX3l7EKQ2/TLxr oeg2ZhNnHLid+OjAG4H/TRwTYVoJv0snmUQcHHEJ8Hib2yJJkqTu0IPHkF8Hvn4xsDvxPOeU 9rZHaoZyOgNGk+8K+baU87x8AA4GziHO/bE1cD9wBPHkvcxtzAE+CrwfGAM8R+xcOJc4GGIv mApMJ3ZwrCGOjrKUeMfHzPY1S5IkSR2sV48hVwKbpX7+G+Bk4gXCykeMpS42QBnj3j9KfHb+ Tam8wNCr8ZsAfyZ2GuyKAp0xkOAM4p0QWX/YVgJX0Ht3QEiSJKkxvXoMmefMqBOO4aUSlDNm wH8TB+P7eI0yXwBeC1xfSo0qw1Sq/xEnyT+K+PiEusZ+wFzgvmS5X3ubI0mSek0bjyGbepyT mv583hQIA+vTvCmpcivKrFRqn3LuDJgI/IF4q/0lwNXAL4CLiLfZH08ccO9p4gCCSxqusft1 wp0Bi4Htc5ab0OS2qBT7AbOAcam8JcDRxK+iJElSw9p0DNn045zkrGjeFNhz/oar5+8JU+Yl P7T7OF4qQTmdAQB7AldR/Qv/BPEZ/dtLqa37tbszYBLwAPHxjeGsJj4CsrCpLVIJ5gJTMvLn EcfSlCRJakgbjyGbepxzMXBSfBlqHKMPDJ45fQc4tdFKpfYqZwBBiKNs7gQcSxxsbxIwElgE 3AhcBrxYWm1q1DjiQC95/pCvAbbDzoAuMKZgviRJUiFtPIZs6nFO0RnPvMqiHlBeZwDE52e+ lyR1tmeII77mMYp8s0Wo7Z4vmC9JklRIG48hm3qcM49iHQJzy6hUaq9yBhAcR+wd264ifwJx pNH5wJXA20upTWV4nDj1Sx5L8K6ALnEmGw7JsSTJlyRJalgbjyGbepxzyvqX8/fMLjIk30cE 1APK6Qw4E/gtQ0fz2AL4DfAx4tyc/wj8CphcSo0qwxkMGTU100rg9Ba0RaWYQxxEZx5wf7J0 8EBJklSqNh1DNv04Z1VcTJm3YYfAkMEDnU1APaKcAQT/CGwM7JzKOxm4EJhNnFbwg8D5Sd6n G66x+7V7AMFBlxKnfqk2R+ws4MSWtkiSJEmdrlePIfOcGXXCMbxUgnI6A5YS7wI4KJV3A3H+ j/HAU0neHcCmwF81XGP3C8TBFh+m/c8cHQ+cDWxLHOhlFPGeq9OBy4d576TkfUuIt41JkiSp PzRyDNnJVpDdybGCePez1CPK6QxYDVxN7B2EOIvAUuARYPdUuR8BhwBbNlxj95pB/MM5kvV3 B6wFZgLT2tcsACYSx314mjgLRC1TgenAWNb/8V9KvG1sZvOaKEmSpA5T5Biym1xAHBftNuC0 NrdFaoJyOgMWEK/+D06xsQ9wK/BN4LOpcj8GPgC8puEau9MDwJtrrH8QeEuL2tKIGcCRVL8t 7Ara37EhSZIkSaqqnAEE5wF7AocRbxP6YpJ/fUW5nYAnSqmx+8xgSEfAfnNg7l5w385xud+c ZP2/t6l9eU2lekcASf5RwHEta5EkSZIkqaBy7gzYjdghsHEq77fAu4B1yc/jiVOL/IB4Qtlv XiE+GkA88Z91NIxLzY2yZBwcPQvm7Ats1I4G5rQY2D5nuQlNboskSZIkqS7l3BlwJ/Be4Crg 18RZAw5ifUcAwIeIA8z9rJQau8vevNoRADD9zKEdARB/nn5mUm5KC9tWxCTiGAF5bEt8fkyS JEmS1HHKuwZ9a5KquTBJ/WgHhkwlOOb57GJjnk/KvYl4p0WnGUccLHCTHGXXEAeSWdjUFkmS JEmS6lDOnQGq7SGGzEf6/JjsYs+PSco91II21eMZ4qwBeYxKykuSJEmSOo6dAa0wlzh9YOLM 6XGMgLQl42I+a+nMuwIgPuaxNGfZJXhXgCRJkiR1qJHAWe1uRF94A/CO+PLRN8Kdu8FbHoTl W8IjO8DJF8Gc/YBL2HAWhk6yDHg/QweLrLSSOBfrH1vSIkmSJElSQeXMJqB8HmDI9IKZ63dq UVsacSlx+sCs6QVXArOAE0uucxJxUMIlxDsUJEmS1J9adVx4MbA7MB84pYn1SG1iZ0Cr3QL8 bUb+L4F9W9uUhhwPnE38Q7yGOEbAEuB04PIS65kKTCfOYjBYz1LgDGBmifVIkiSps7XquHAl sFlG/iqyL4ZJXcrOgFaaARxJ9SvqVwDTWtqixk0kzhrwNLCo5G334v6SJElSca06LsxzZjQw fBGpGziAYKtMpfofMJL8o4DjWtaiciwEbqf8joBe3V+SJEkqplXHhStzllvRYD1Sh/DOgFZZ DGyfs9yEJrelG7i/JEmSBK07LixyVuTdAeoB3hnQCpOIzzblsS3x1vt+5v6SJEkStO648OKC 5S+osx6pg9gZ0ArjiIOc5LGG+Ax+P3N/SZIkCVp3XLhHwfJ71VmP1EHsDGiFZ4ijneYxKinf z9xfkiRJgtYdF84rWH5unfVIHcQxA1ol77NOi/C2d3B/SZIkKWrVcaFjBqjPeGdAq5zB8COU rgROb0FbuoH7S5IkSdC648JVOcs5m4B6hJ0BrTKTOP9ptT9kK4FZwOWtalCHm4n7S5IkSa07 Lqw2dWGlLRqsR+oQdga00jTgU8RbnSD2Kq4BngROAk5sU7s6VXp/rQZeTJaLcH8NZxKwO/CG djdEkiSpBK06LhygeqfDCnw8QD3FMQPaYSpwGbEjYA2wMbCUeAvUzPY1q6NNJI4O+zTxj76y TQWmE6fgWUMcSMfYkiRJvaRVx4UXEGcNuA04rYn1SG1iZ0CrzQCOJPs2pJXEW6CmtbRF6hXG liRJkqScfEyglaZS/WSNJP8o4LiWtUi9wtiSJEmSVIB3BrRS3mlRFgMTmtwW9RZjS5IkSVIB 3hnQKpOIz3HnsS2NzZGq/mJsSZIkSSrIzoBWGUcc0C2PNcRBUaQ8jC1JkiRJBdkZ0CrPEEd2 z2NUUl7Kw9iSJEmSVJCdAa3yOHGKtzyWAAub2Bb1FmNLkiRJUkF2BrTSGcQp3mpZCZzegrao txhbkiRJkgqwM6CVZhLneq920rYSmAVc3qoGqWfMxNiSJEmSlFv3dgZsBVwIPAm8BNwJHN6k bZRR16BpwKeS16uBF5PlIuAk4MQ6tysNxtZijC1JkqRG3UA8jvp5uxsiNccAENrdiMIGgF8C 7yDeHv0QcDxwBHAk8J8lbqOMurIE4A3Ekd2fJv6hkcoyEWNLkiSpHmvJvmS6DhjZ4rZITdSd nQEfBq4iXgmdkeQNAPOA1wGTiV/WMrZRRl1ZQrIdSZIkSZ0hz5mRx/DqEd35mMCHiPOlz0rl BeCHxCuie5S4jTLqkiRJktTZ1q5/uXwLCAPr0/ItUuVeaXnLpKbozs6AXYBHgFUV+Xen1pe1 jTLqkiRJktTZkjOj5VvA6BVDV41ekeoQ8FEB9Yju7AwYCyzLyF+WWl/WNsqoS5IkSVLnumH9 y8qOgMz865raGqklNmp3A3pWnueNum+0BkmSJEkH4rG8Gtfm8Se6szNgKbBNRv42qfVlbaPe uob7YB1AUM1gXKkZjCs1g3GlZjCuVK+fAx8sUP564KAmtUX9oQM6k7rzMYG7gR2BzSvyd02W 95S4jTLqkiRJktS5Dlj/csXo7CJD8u0IUA/ozs6Aa4CNgWNSeSOA44CFwO9L3EYZdUmSJEnq bMl04Vss37BDYMXomA8MmXVA6mbd+ZjAtcCvgG8BWwIPEU/O9wCO5NUvMgB7Ab8FvgycVcc2 itQlSZIkqTuN5NVbt1898c/SnWdQ0ga6M5QDcDBwDvA5YGvgfuAIYHbJ2yijLkmSJEmdbwB4 hezpA9fSrWdPUqYBOmLogj7kADdqBuNKzWBcqRmMKzWDcaUyXQfsBozHuFL5OuDvlZ0B7dIB H756kHGlZjCu1AzGlZrBuFIzGFdqhg6Iq+4cQFCSJEmSJNXNzgBJkiRJkvqMjwlIkiRJktRn vDNAkiRJkqQ+Y2eAJEmSJEl9xs4ASZIkSZL6jJ0BkiRJkiT1GTsDJEmSJEnqM3YGSJIkSZLU Z+wMKNNWwIXAk8BLwJ3A4RVlxgPXAy8ADwFHZ2xnX+A5YPumtVSd6N3A94B7gRXAIuC/gN0z yhprqse/EieTfbbKeuNKRewN/AxYBqwC7gPOyChnXCmv3YBrgSeAlcADwFeBLTPKGleqNBb4 v8AviZ95AE6oUjZP/BQpa6z1rrxxVeQ4HjoqroKphDRA4BYCLxI4lcAHCfyYQCBwRKrcDQSu I7AlgYMJvELgban1mxJ4kMAnO+B3MrU2XU/gbgJfIXAMgc8SWEDgZQLvS5Uz1kz1pLcQWEXg CQLPZqw3rkxF0hHJZ38bgZMJfJTAFwl8u6KccWXKm95K/Bv1IIGpBA4gcA4xFm6uKGtcmbLS LgSWEriRwE+I8XBCRrm88WOsmYrEVd7j+M6Lqw7Yyb2QPpx8gB+v+KDnE3icwAgCGxMDYv9U mT8R+JfUz2cTD64GOuB3MrU27ZiRN4HASgL/L5VnrJmKphEEbiUwg/ifVVZngHFlypteRzyA uZYYF7XKGlemvGk6MVZ2q8j/jyR/YirPuDJlpfTfo/dQ/aQtT/wUKWus9XbKG1d5j+Oho+LK xwTK8iFgDTArlReAHwITgT2qvC+kXu8C/BPwiYp89YeHM/IWJfnjU3nGmoo6BdgR+JcaZYwr 5XUCsAXweWAdtR84NK6U18vJ8i8V+cuS5apUnnGlLOtylisSP8aa8sZV3uN46Ki4sjOgLLsA jzD0PyuAu1PrXwZuBk4GtgYOBXYCbiB+Ev8BfAv4Uwvaq+6wHfBm4K5UnrGmIiYD5wCnsuFB dppxpbz+FngK2Jk4TsArxBO2GcA2FWWNK+V1OfA88RnatwCvAf6BeKB7CUPHOjGu1Ig88VOk rLGmarKO46Gj4srOgLKMZX3vddqy1HqAjxH3+uPAecDxxA/+k0mZ6c1tprrICOBSYm/f2al8 Y01FXEL8z2T2MOWMK+W1PXFAtx8k6f3AN4gDG80BNkqVNa6U16PAO4EdgPuJMXI98crZSRVl jSs1Im/8FClrrKlSteN46Ki42mj4IirVYmJPd9p4YpAcCqwGvkjsCd8MuIZ4C8iKFrZRneFC YqwcSxyZtChjTdOAKcBflbhN40ojgNHAacD5Sd4c4lWMbwAHEkeEL8K40mTgp8ByYsfSM8TO gc8TO5+Or2ObxpVaxVhTpUaP46ElceWdAWVZyoa3R5LKW1rjvRcCVxGnrDiK+FzvIcBfE/8j /FJprVQ3GCDGxEnEk7lZFeuNNeWxLbEX+WvEg+utk7QRMca2BjZPlTeulNdgLPyiIn/w53dU lDWulMe5wOuB/YArgJuIV73OAI4jTp81yLhSI4rEj7GmooY7joeOiis7A8pyN3GArs0r8ndN lvdUed+HiHM1Dw7stT/wc+B24qAT3wcOKCZ9+bEAAAw3SURBVLWl6mQDwMXAp4h/QL6fUcZY Ux4TgDHE8QL+kkofIP5n8xfgslR540p5/SFZVh5BjEyW6cGWjCvl9XbgMTY8CP5dsnxrKs+4 UiOKxI+xpiLyHMdDR8WVnQFluQbYGDgmlTeC2Ju9EPh9xnu2Ar4DfIbaA3upPwwQBwP5BPEP yGVVyhlryuNh4pW0yjQXeCF5/ZVUeeNKeV2VLA+qyD8wWc5N5RlXyusJ4I3EAbfS9kmWC1N5 xpUaUSR+jDXllfc4Hjourto/f2MvpAECtxBYTuCfCRxE4CfEOSSPqPKeiwj8vCLvaAIvEHgH gfHE+STP64Dfz9T89E1ivFxL4LCKdHCqnLFmaiRdT+DZjHzjylQk/YTAauLc8IckyzUEbmbo fMfGlSlvOpjAOgL3EOfePpjAuQReSj7vUamyxpWpVhwdRuBLxHi4kPXHUhtTPH6MNVPeuMp7 HN95cdUBO7hX0pjkg3qK+J/XXQQ+UqXsXsmHN7kif4DAWQSeILCMwPcJbNEBv5up+Wkuoeq/ 5yrKGmumelO1zgAwrkz50yYEvkJgAbETYCGBbxDYPKOscWXKm/YlcAOBJwmsJPAA8cB2bEZZ 48qUlZ6j+rHU1qlyReLHWDPliasix/EdFFcDyQtJkiRJktQnHDNAkiRJkqQ+Y2eAJEmSJEl9 xs4ASZIkSZL6jJ0BkiRJkiT1GTsDJEmSJEnqM3YGSJIkSZLUZ+wMkCRJkiSpz9gZIEmSJElS n7EzQJIkSZKkPmNngCRJkiRJfcbOAEmSJEmS+oydAZIkSZIk9Rk7AyRJkiRJ6jN2BkiSJEmS 1GfsDJAkSZIkqc/YGSBJkiRJUp+xM0CSJEmSpD5jZ4AkSd3iVOBPwGogAHMa3N55yXYOa3A7 nWQC8Xe6td0NybApsW33tLshder29kuShrAzQJKkemxNPDG6q0X1HQp8G9gOmA38O3Bdi+qu pdX7odX1dWobJElq0EbtboAkScrhkGR5LPCLdjZEdXsZOA14tt0NqVO3t1+SNISdAZIkdYPx yXJBOxuhhqwFzm93IxrQ7e2XJA3hYwKSpOrSz19vSbxNfSHwEnAv8Rn2av+TTAAuBB5Jyi8j 3tb+zhp1bAZ8LXnPGuIz7elyFwAPAquS7f0O+AIwusQ2jAK+AjxKfDb/UeCLwMhU+c8Af0le /3Xy3sF0ZZW2VJoCXAM8k9SzAPgusH1FuenJdv8++fm+VF3vylnXPwC/AVYSr+rOBt5Yo/yB wGVJXS8CK4A/AKcDm6TKFdkPebdZS9H9nuezLNq2Rj774Z653xW4ImnnS8TYuAP4JjBumG2/ K9n2j6qsPz9Zf2gqr2jc5xkzoFqsVY5PUU970+3O872WJNXknQGSpOGNAm4C3gzcDGwMvJfY OfA24MSK8nsC/w1sAzxMvK39tcABwP7AkcBVFe/ZCLiBeJJ8B/AU8bZkgH2A64nPai9Ktr0Z sDPxBOYnwP0ltGEk8DPiicofkzbsAXwZGAv8U1LuN8DZwBlJmYtS27iP4R1JPAkaCcwHHgd2 Az4JfBh4T+r3uZF4wnMCsANxnw/epv3nHHVNJZ7orgNuIZ5g7pPUe1OV98wENid2+NwIbAX8 DfF3fh/wfuJV4iL7Ie82aylSX97PsmjbGv3sq9mH9d+t+cA8YgfcDsRb82cDSxrYfi1F9lUt 9cRaUfV8ryVJVQWTyWQymTLTBMKr/+4mMC617n8RWJisOyCVP5rA4wTWEZhWsb13E1hO4HkC r6moY11Sx8RU+QECWxF4KilzBoGRFdv8OwJjK/IaacNdBCanyk8hsIbAyxW//9bJe+4quE9f n9S/lsDhqfyRBC5Itvm7jPfNSdbtVKCu7QmsIPASgX1T+ZsQuCr12R5W8b6jk/2eztuGwE1J +ePq2A9FtlkrDVdfPZ9l0bbV+9lvmrzvnox1V1b5LCCwC4Hthtn2u5L3/6jK+vOT9Yc2sK9q tb9orNXT3qLfa5PJZDLVTD4mIEnK53MMvTL5GPHKIcDJqfxjgYnAJcClFdv4NfF24a2IV/DS BoiPHSxM5QXi1cbXEq+ans2GV49vAZZW5NXbBohX4Bekfp4HXE28c2HvjPJFTSU+1nA18Y6G QWuB/8P6q7L7lFDX8cQr3j8A/ieVv5q4r9dUed8s4IWKvGXAp5PXh1BcM7Y5nBPI91m2o22V tkuWv8xYdw/xKnsznUBjcV9vrBXRyPdakrQBHxOQJA3veeKtuZWuIB6Yp59dH3y2/eoq27ol We5Rkb+UoScRg96XLL83fDMbbsNisqeLuzdZVj7PX4/BfZX1rPRq4u3gpwLvBm5rsK53J8sf Z6xbDPwK2K/Ke8cA+xJvUx9NHBti8BLCm+psTzO2WU3Rz7KVbctyO/Hzupz46Ms84u32rVBG 3DcSa3nV+72WJGWyM0CSNLzHq+SvIJ7EjyWeQK0AJifrhpv+bmzOOiYmy4eH2V5avW1YmFlq /VXjvAPd1TJ4YrWgyvrHkuX4Kuvrqava2ALV8k8j3oWxWZX1W9bRlmZss5Yin2Wr25ZlOnG8 jP2T9DwwF/gp8Wr7iibWXUbc1xtrRUxOlkW/15KkTHYGSJIaU3n1cnD08YuoPR/5gxU/ryyt RfW3oVVXYmsJLawr6/c9kDh6/SLiyPm/JT4e8jJxIMnVxEc6imjGNoeT97NsR9uyLCXeNfKe pE3vIV4J/wDwr8Rb9Rc1sP1aD4a2Iu6L1pHV3nq/15KkTHYGSJKG94Yq+ZsTpzx7gfVXLhcR p1ybA1xbQt0LgbcTb9++M+d7ym5DmZ4gtm0Scfq6SpOT5eIS6noyqesNxKniKk3KyDsqWX6S OINDWq3pCGtpxjbL0kltW0ccG+Pm5OfXEWeP+AhxfI6P13jv4DP51e5iqPYdLkvRWKunvZ38 vZakLuQAgpKk4Y0hTq9W6YhkmX62fU6yPLakuge394k63lNWG7IMnswU7Va/NVkelbFuFHB4 8vrX9TSqwuA2PpKx7nXA32XkD85nn/XYxuEZeXn2Q9Ft1lLvfq+mnraV3YZqngK+kLx+2zBl n0yWO2WsG8PQcT2aoWis1dPeVnyvJamP2BkgScrn34hzew+aCHwpef3dVP4M4oH+h4GziCe4 aZsBxwA756x3JvGk6O+Bz7LhLdt7V7SrGW3IshJ4jnjFs9qz5llmEu+iOBw4KJU/AjiHOFbA 7TQ+eCDEZ81XEWcwSM9OsDFwPtnPgj+SLKdV5O9NnFGiUp79UHSbtdS736upp21ltwHgFLLH ifhAsqw2psaghcTxJt4MHJfK34L4fWj2c/RFY62e9rbiey1Jfabt8xuaTCaTqUPT4DzkvyPw ewJLCfwncd7wF5N13894354EnknWP0ngBgKzCcwlzgMeCOxXUcetNdqxD4HnknKPJm34KYGH k7ydmtyGzyTrP1OR/8Mk/yEClxO4lMBJOfbrUQReSd77awKzCNyf/PxUld9nTo3ftVaalrzv lWQfXE7gMeJnOZsN57bfmThffCDwx6T8zQTWEjgvyV9QcD/Us81aqVZ9RT/LettWz2e/afKe ezLWLSCwjsCdBK4g8CPidy4QeIHA23Psl+OS8oPf2ZuIn/NjyfYCgUNT5Yvuq1rtryfWira3 6PfaZDKZTMOltjfAZDKZTJ2a0icLYwhcRGAxgdXEk9fTCIyo8t7XEjiXeOKwgsBy4onT1QQ+ SmDzjDpqtWUSge8STxRWE3iWwHwCpxMY3eQ2VOsM2IbADAJPsP7k/sqc+3YvAtcSWEJgDYE/ E7iYwPgq5evtDIDAQcSTpVXEk62rCOzI+pPdwyrKv5XAdcSTrhUE7iBwYrIu6+Q4z34ous1a qVZ99XyW9bStns++1sn04QRmEriX2PG1nMB9BL5DYHKBffNRAn8gfkeeIXAZge0InE/zOwPq ibUi7S36vTaZTCZTzTSQvJAkaUMTiLfz3kbznzmW1LvOIz7mczhwZZvbIkkCHDNAkiRJkqS+ Y2eAJEmSJEl9xs4ASZIkSZL6jGMGSJIkSZLUZ7wzQJIkSZKkPmNngCRJkiRJfcbOAEmSJEmS +oydAZIkSZIk9Rk7AyRJkiRJ6jN2BkiSJEmS1GfsDJAkSZIkqc/YGSBJkiRJUp+xM0CSJEmS pD5jZ4AkSZIkSX1mBLC83Y2QJEmSJEkts/z/Azuhrfclm7ntAAAAAElFTkSuQmCC --qzkemyanjw2idojc Content-Type: text/plain; charset=us-ascii Content-Description: benchmarking script Content-Disposition: attachment; filename=uniq_demo # Tweaking these... max_lines_of_data=100000 # The total number of lines of data to search for unique values in. Bigger values have lomger run times. max_line_length=10 # How many bytes are in each line that may be unique. Smaller values create fewer unique lines. # leads to... interval_between_lines_of_data=$(( $max_lines_of_data / 5 )) # Report heading. echo lines,percent unique,algorithm,time # Benchmark with increasing lines of data... for data_lines in $( seq 1 $interval_between_lines_of_data $max_lines_of_data ) ; do # Benchmark with increasing line length.. for line_length in $( seq $max_line_length ) ; do # Generate a certain number of lines of random data of a certain length tr -cd '[[:alnum:]]' < /dev/urandom | fold -bw "$line_length" | head -n "$data_lines" > /tmp/data # Calculate the percentage of lines that are unique. number_of_unique_lines="$( sort -u /tmp/data | wc -l )" percent_unique="$( calc -dp "$number_of_unique_lines/$data_lines" )" # Benchmark sort with its unique option. /usr/bin/time -o /tmp/sort_time -f %e sort -u /tmp/data > /dev/null echo "$data_lines,$percent_unique,sort,$( cat /tmp/sort_time )" # Benchmark awk hashing. /usr/bin/time -o /tmp/hash_time -f %e awk '!seen[$0]++' /tmp/data > /dev/null echo "$data_lines,$percent_unique,hash,$( cat /tmp/hash_time )" done done --qzkemyanjw2idojc Content-Type: application/gnumeric Content-Description: spread sheet (gnumeric) Content-Disposition: attachment; filename="hash_and_sort_benchmarks.gnumeric" Content-Transfer-Encoding: base64 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 tXyehov9BGOCv3pZ2ET640+HP7n78E/gbHqF1W5JrvCGX+HN01eQ+e11i4RFkvcFGM8NlXOW PeRsdJEMXk+Kz9JBs+xN01H5xNrUumLC7SYDaIaGF1tXwSYD/cuR6lMjw2hsyOFROdPuZujn MkOrV3p3M/QzmaGFZ3lqhp7LVM/Q3vc3Q/M3ZFZ78sVn4kBMxY79JefiQEzGT19jNxt/gdn4 cTD8fmbjk+a+PL1udxdXvWF7YZUo6BBCXep4XhRELgnDjRYC6wq529nCa+Jn88L5u33Np14u E5ts6/8Vmz8cX2P9bCPeKdvTsLr2SETSGmzuaSpoHdgdxw+I7fiu7UZuZIchteyO59sRjRyH wjnqkcDnaUEYEhgXBOyQ2q5LIM3xfJ+6PvEDj9p2aEu3Ta7tiOGLUcmJtclzobhz21Xnzuvs Zg1321l321l321nlte+2s+62s+62s67e3ueye2+3nXXT7axN7t1+1qWSz2VEPN/9rJdiN2u/ 3sfqcPOP7L/ZtrPxrqDdhtbv6En3eW9ojcsS8Dfpt+tvcuCbvLjn++UEoPWPux1i35CL2+0Q +/qvanY7xNZMi+P6G5Cm8x8nv4rvE9OO75C/4Nhtkl0quXOBOxe4c4HfnAvcbZLdrKLf1xac 3SbZadlv1antNsl+P5tkX/EtrK++5U2yO7/9PPz2buvktOyz9tu7rZNb9s+BcNDf9tbJ3Ya6 5/nG67t9zaB+tH42G+qcwIkCl4auaweBG4kNdU7ghS7fKEc8P7S957mhrj679J2R9fdpJlm2 /C2SPM2afhHr9AuVP/EX7FfCIoldz/rNd4fy7E/W4KzUMF25rVdqN6jKXakqzgYAMtVwtEEt 3kotFbhyjQqctZr4dmv6exVapR1U6VUJ+GPRBhV4K5e3NUq7qK67qK672K67qK57qK57qK57 2K57qK77qK77qK772K77qK4HqK4HqK4H2K4HqK4TVNcJqusE23WC6nqI6nqI6nqI7XqI6nqE 6nqE6nqE7XqE6jpFdZ2iuk6xXaeorjvrOU+bStZD3sbFzalmPdRpd1+OdK5t21p9kHMd/5EG z6E08qGukFIaUB73oV+luSwK2uvodUtOfNrKyLHP7rg2PHbRyIlsm9qgTLBJhea6KFBQUxc5 DmrrImdCu0OJ7wVOGLm+Y0ch9bXsBY2JjoITO7arU4OcFbV1kQMj6EKpB/V4PgwnN7Btf5MK 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 --qzkemyanjw2idojc--
X-Loop: help-debbugs@HIDDEN Subject: bug#32099: Benchmarks: Hashing ~70% faster (Was: New uniq option for speed) Resent-From: Assaf Gordon <assafgordon@HIDDEN> Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> Resent-CC: bug-coreutils@HIDDEN Resent-Date: Tue, 10 Jul 2018 18:22:01 +0000 Resent-Message-ID: <handler.32099.B32099.153124688530418 <at> debbugs.gnu.org> Resent-Sender: help-debbugs@HIDDEN X-GNU-PR-Message: followup 32099 X-GNU-PR-Package: coreutils X-GNU-PR-Keywords: To: "Kingsley G. Morse Jr." <kingsley@HIDDEN> Cc: 32099 <at> debbugs.gnu.org, Paul Eggert <eggert@HIDDEN> Received: via spool by 32099-submit <at> debbugs.gnu.org id=B32099.153124688530418 (code B ref 32099); Tue, 10 Jul 2018 18:22:01 +0000 Received: (at 32099) by debbugs.gnu.org; 10 Jul 2018 18:21:25 +0000 Received: from localhost ([127.0.0.1]:54337 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1fcxGO-0007uY-NB for submit <at> debbugs.gnu.org; Tue, 10 Jul 2018 14:21:25 -0400 Received: from mail-pf0-f193.google.com ([209.85.192.193]:35516) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <assafgordon@HIDDEN>) id 1fcxGN-0007uJ-97 for 32099 <at> debbugs.gnu.org; Tue, 10 Jul 2018 14:21:23 -0400 Received: by mail-pf0-f193.google.com with SMTP id q7-v6so15544691pff.2 for <32099 <at> debbugs.gnu.org>; Tue, 10 Jul 2018 11:21:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=Wpac84Wp3ytdwo+YpMknwNKNVIHRzjx3qHWVQ9t6SVQ=; b=PyKRr1DYxN09bshtZtsPsGk5yBDyfw54pSAmGjpnaaXMDZ+xy5c2OudaGWlPgI9jbs Gzj0B0fY5eaRDEPRf0ZITjxj9XpU0dNm/0NMZh2iZzoIEWIUiF+3oTOc1Ma94z9PdvY/ ulCLJZ3Gei7y5tKsnIn4+2Q6RH4KHnYFSFEhEEjLYO3zLvf6Np3HeNotv9I7stl4/YBB tHlLHYpR7GIe3/nBiQqYodZE/g1w5G87CZyWZmppk/T42CEbaCFbXJdSFMkpsvfKIZCS eNTdoMKZuxUkRB71P2oeZ6jEYp2YpX6wkFrQDD0vFZd4owqIAF9heAdAsvzuhxrg9GfG f8sg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=Wpac84Wp3ytdwo+YpMknwNKNVIHRzjx3qHWVQ9t6SVQ=; b=qGXPiY7M20gBjNtiCdadME+DnGLMBd1K9EeXIxRt824L3Fe6zqOXEIJhc8UG1INV9l i2h0PusoofFOyf6DaZH4Rrb9CHZaZ98hFaUrST82wQXkG6D7MpMPFKrvTYPOd8mxikAL ANkrx7sZehc24iV32YJDi7tl0nmTcks0tRl344iDizwClLb/gY+2vf8w13kZIDpyBhso u2OXWoi6+OqiFsaih0e9kTUoRDJvuXBmITXkuxtmIESk82UO2CRaidJfM0sqWbTAAde5 7C4H4/qQK6UVWGXINLGVrgmln4dMGl5/UbnkYSKPErNivqXIWzqcRkmA6BPvb0mmOj3y 7ecA== X-Gm-Message-State: APt69E0IJqZFBvhoLAWpwzeRfZfeorJ6JPx1u0nxZFUedLZvm9ltUMmr avEGytPlyHYaHwMLzKgG/2Y= X-Google-Smtp-Source: AAOMgpfmm6OQEcstrr/IvgNQBZsDZMUASqp5m/kSuBC5pHn5IGX5RtW1GX9zqLysp4UkR/rrKw7cIQ== X-Received: by 2002:a63:4c21:: with SMTP id z33-v6mr2382564pga.383.1531246877080; Tue, 10 Jul 2018 11:21:17 -0700 (PDT) Received: from tomato.housegordon.com (moose.housegordon.com. [184.68.105.38]) by smtp.googlemail.com with ESMTPSA id p26-v6sm34607987pfi.164.2018.07.10.11.21.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 10 Jul 2018 11:21:15 -0700 (PDT) References: <20180708210356.c5fwiocbvdndkgxh@HIDDEN> <a499a8ae-df6d-8342-8d89-e105f6b2bc62@HIDDEN> <20180710042953.2w46nfztrxrg6gmi@HIDDEN> From: Assaf Gordon <assafgordon@HIDDEN> Message-ID: <12517fed-acc1-7935-403a-f0a6be3444a3@HIDDEN> Date: Tue, 10 Jul 2018 12:21:14 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 In-Reply-To: <20180710042953.2w46nfztrxrg6gmi@HIDDEN> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) tag 32099 notabug severity 32099 wishlist close 32099 stop Hello Kingsley, On 09/07/18 10:29 PM, Kingsley G. Morse Jr. wrote: > And I like your benchmarks. > > Mine are humbly attached. > > They compare sorting to hashing. > > At the moment, hashing seems to me to be about 70% > faster. > > And to scale better. > > I'd still like uniq to be faster and free from > sort. Thank you for taking the time to create and provide these, including the scripts to reproduce it. I've marked this item as "closed / wishlist" - but only because it is technically not a bug report. Discussion is welcomed to continue by replying to this thread. Being "faster" alone is important but not the only criteria (as mentioned in the previous email's examples). Your measurements are a good start towards stronger support to hash-based uniq implementation (a working patch, btw, would be even stronger). I would suggest several improvements to the measurements, to ensure relevant information is conveyed: 1. Specify exactly which versions of awk/sort you are using (e.g. which versions, whether from your distribution or compiled from source, if compiled than which compiler / optimization flags). What CPUs is being used, how much memory does the computer have, etc. 2. I would suggest adding "sort | uniq" to the charts, because that is the real base-line you are trying to improve. I would also consider adding "datamash rmdup" to the charts, because its hash-based implementation could serve as a ball-park indication of how a naive hash implementation would work in uniq. 3. You input is very small (up to 90K lines of 10 characters each) - that does not seem to stress-test any significant parts of the algorithms (and for a typical user, waiting 0.05 seconds vs 0.15 seconds does not matter). I would recommend much larger input files, with much longer lines - trying to simulate various real-world scenarios. Here's a project of someone who tried to compare various hashing functions: https://github.com/jhunt/hash/ Under the "corpus" directory you'll find few demo data files. Even the largest one (qnames) is only 84MB - not very big. Perhaps consider duplicating the content few times, then test it: for i in $(seq 1 5);do cat qnames; done > input To get even closer to real-world input, try several input files with different ratios of duplicated lines (your script create completely random data - not very similar to real-world input files). For example, what happens with many lines share similar sub-strings? depending on the hashing implementation, this could lead to lower performance. 4. It would be beneficial to see what's the memory requirements and limits of a hash-based implementation. Currently, because 'sort' is not limited by available RAM, there is no memory limit (though resorting to disk I/O might make everything slow). For example, is it possible to hash an 800M file on a machine with only 1GB of RAM ? and without additional code, hashing files larger than available memory is simply not possible - a very big disadvantage. 5. To compare "sort' fairly against other options, I would add to the measurements using "--parallel 1" and later "--parallel N" (N being the number of cpu/cores you have). Does that improve performance? The "awk" (or datamash) programs do not have a built-in memory limit, while sort does. It would be useful to specify a large amount of memory for sort (using "-S") to ensure sort did not revert to disk I/O. 6. The reported time in your script is the elapsed time (aka "wall time"). A more relevant option would be "user time" + "kernel time" (optiosn %S and %U in "time -f") - the wall time can be affected by factors that don't immediately relate to hashing/sorting performance. 7. In your script you are providing a file-based input, it might be useful to clear the kernel's cache before each run to ensure these do not affect the results (especially when dealing with large files). See: https://www.tecmint.com/clear-ram-memory-cache-buffer-and-swap-space-on-linux/ To conclude, There is definitely merit in trying to optimize uniq's performance, but it must be weighed against other factors (e.g. the ability to 'uniq' a file larger than available memory, and the ease of using existing programs to achieve the same effect). IMHO it is not a top-priority, so I don't want to give the impression that if an amazing speed improvement is presented, uniq will be swiftly rewritten. But of course, a working patch and strong pro arguments would go a long way towards incorporating this feature. regards, - assaf
X-Loop: help-debbugs@HIDDEN Subject: bug#32099: datamash wins! (Was: New uniq option for speed) Resent-From: "Kingsley G. Morse Jr." <kingsley@HIDDEN> Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> Resent-CC: bug-coreutils@HIDDEN Resent-Date: Wed, 11 Jul 2018 23:44:01 +0000 Resent-Message-ID: <handler.32099.B32099.15313526084893 <at> debbugs.gnu.org> Resent-Sender: help-debbugs@HIDDEN X-GNU-PR-Message: followup 32099 X-GNU-PR-Package: coreutils X-GNU-PR-Keywords: To: Assaf Gordon <assafgordon@HIDDEN> Cc: 32099 <at> debbugs.gnu.org, Paul Eggert <eggert@HIDDEN> Received: via spool by 32099-submit <at> debbugs.gnu.org id=B32099.15313526084893 (code B ref 32099); Wed, 11 Jul 2018 23:44:01 +0000 Received: (at 32099) by debbugs.gnu.org; 11 Jul 2018 23:43:28 +0000 Received: from localhost ([127.0.0.1]:56075 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1fdOlb-0001Gr-Am for submit <at> debbugs.gnu.org; Wed, 11 Jul 2018 19:43:27 -0400 Received: from outbound-smtp08.blacknight.com ([46.22.139.13]:60177) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <kingsley@HIDDEN>) id 1fdOlX-0001Gb-Ck for 32099 <at> debbugs.gnu.org; Wed, 11 Jul 2018 19:43:24 -0400 Received: from mail.blacknight.com (pemlinmail03.blacknight.ie [81.17.254.16]) by outbound-smtp08.blacknight.com (Postfix) with ESMTPS id 7C2A21C2D74 for <32099 <at> debbugs.gnu.org>; Thu, 12 Jul 2018 00:43:17 +0100 (IST) Received: (qmail 27275 invoked from network); 11 Jul 2018 23:43:17 -0000 Received: from unknown (HELO debian1.loaner.com) (kingsley@HIDDEN@[97.113.25.140]) by 81.17.254.9 with ESMTPSA (AES256-SHA encrypted, authenticated); 11 Jul 2018 23:43:16 -0000 Received: from kingsley by debian1.loaner.com with local (Exim 4.90_1) (envelope-from <kingsley@HIDDEN>) id 1fdOlJ-0007Mf-Aa; Wed, 11 Jul 2018 16:43:09 -0700 Date: Wed, 11 Jul 2018 16:43:09 -0700 From: "Kingsley G. Morse Jr." <kingsley@HIDDEN> Message-ID: <20180711234309.jaq663dsktjljkoa@HIDDEN> References: <20180708210356.c5fwiocbvdndkgxh@HIDDEN> <a499a8ae-df6d-8342-8d89-e105f6b2bc62@HIDDEN> <20180710042953.2w46nfztrxrg6gmi@HIDDEN> <12517fed-acc1-7935-403a-f0a6be3444a3@HIDDEN> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="3auohxm5ypw3cvru" Content-Disposition: inline In-Reply-To: <12517fed-acc1-7935-403a-f0a6be3444a3@HIDDEN> User-Agent: NeoMutt/20170306 (1.8.0) X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) --3auohxm5ypw3cvru Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hey Assaf, Thank you very much for taking the time to share your thoughts. People like you, willing to improve free software and help the common good, restore my faith in humanity. I followed much of your advice. I ran more benchmarks: gawk, mawk, sort -u, sort | uniq and ... datamash rmdup! Plus, I benchmarked them against a bigger file. ~1 GB! Plus, plus, I measured how much memory they used! The result? Hashing algorithms always won. I expected it. When I benchmarked data compression apps, one named "rzip" that searched its cache of unique values with hashing was much faster. https://www.linuxjournal.com/article/8051 But, to be fair, I was surprised by how little memory datamash seemed to use. Maybe I screwed up. I checked max resident set size of the process during its lifetime with /usr/bin/time's "%M" specifier. Plus, plus, plus, I created a composite performance criteria of elapsed time * memory used (It's in the attached spread sheet.) That winner at ~1 GB? datamash! No matter whether the keys were unique or duplicated, "datamash rmdup 1" won! New files are attached. Humble suggestion: Don't worry about running out of memory. Hashing could be added to the "uniq" command as... (wait for it...) an option. So you could always omit it and use sort. For yours truly, the big gain is actually being able to ditch sort. Less is more. It's a UNIX thing. So it is said. So it is done. Sorting is great, but less is number one! ~K PS: Congratulations on datamash performing so well. On 07/10/2018 12:21, Assaf Gordon wrote: > tag 32099 notabug > severity 32099 wishlist > close 32099 > stop > > Hello Kingsley, > > On 09/07/18 10:29 PM, Kingsley G. Morse Jr. wrote: > > And I like your benchmarks. > > > > Mine are humbly attached. > > > > They compare sorting to hashing. > > > > At the moment, hashing seems to me to be about 70% > > faster. > > > > And to scale better. > > > > I'd still like uniq to be faster and free from > > sort. > > Thank you for taking the time to create and provide these, > including the scripts to reproduce it. > > I've marked this item as "closed / wishlist" - but only because it > is technically not a bug report. Discussion is welcomed to continue > by replying to this thread. > > Being "faster" alone is important but not the only criteria (as > mentioned in the previous email's examples). > > Your measurements are a good start towards stronger support to > hash-based uniq implementation (a working patch, btw, would be even > stronger). > > I would suggest several improvements to the measurements, to ensure > relevant information is conveyed: > > 1. > Specify exactly which versions of awk/sort you are using > (e.g. which versions, whether from your distribution or compiled from > source, if compiled than which compiler / optimization flags). > What CPUs is being used, how much memory does the computer have, etc. > > 2. > I would suggest adding "sort | uniq" to the charts, because that is the > real base-line you are trying to improve. > I would also consider adding "datamash rmdup" to the charts, because its > hash-based implementation could serve as a ball-park indication of how > a naive hash implementation would work in uniq. > > 3. > You input is very small (up to 90K lines of 10 characters each) - that > does not seem to stress-test any significant parts of the algorithms > (and for a typical user, waiting 0.05 seconds vs 0.15 seconds does not > matter). > > I would recommend much larger input files, with much longer lines - > trying to simulate various real-world scenarios. > > Here's a project of someone who tried to compare various hashing > functions: https://github.com/jhunt/hash/ > Under the "corpus" directory you'll find few demo data files. > Even the largest one (qnames) is only 84MB - not very big. > > Perhaps consider duplicating the content few times, then test it: > for i in $(seq 1 5);do cat qnames; done > input > > To get even closer to real-world input, try several input files > with different ratios of duplicated lines (your script create completely > random data - not very similar to real-world input files). > > For example, what happens with many lines share similar sub-strings? > depending on the hashing implementation, this could lead to lower > performance. > > 4. > It would be beneficial to see what's the memory requirements and limits > of a hash-based implementation. Currently, because 'sort' is not limited > by available RAM, there is no memory limit (though resorting to disk I/O > might make everything slow). > For example, is it possible to hash an 800M file on a machine with only 1GB > of RAM ? and without additional code, hashing files larger than available > memory is simply not possible - a very big disadvantage. > > 5. > To compare "sort' fairly against other options, > I would add to the measurements using "--parallel 1" and later "--parallel > N" (N being the number of cpu/cores you have). > Does that improve performance? > > The "awk" (or datamash) programs do not have a built-in memory limit, > while sort does. It would be useful to specify a large amount of > memory for sort (using "-S") to ensure sort did not revert to disk I/O. > > 6. > The reported time in your script is the elapsed time (aka "wall time"). > A more relevant option would be "user time" + "kernel time" > (optiosn %S and %U in "time -f") - the wall time can be affected by > factors that don't immediately relate to hashing/sorting performance. > > 7. > In your script you are providing a file-based input, > it might be useful to clear the kernel's cache before each run > to ensure these do not affect the results (especially when dealing with > large files). > See: https://www.tecmint.com/clear-ram-memory-cache-buffer-and-swap-space-on-linux/ > > > > > To conclude, > There is definitely merit in trying to optimize uniq's performance, > but it must be weighed against other factors (e.g. the ability to 'uniq' > a file larger than available memory, and the ease of using existing programs > to achieve the same effect). > > IMHO it is not a top-priority, so I don't want to give the impression > that if an amazing speed improvement is presented, uniq will be swiftly > rewritten. > > But of course, a working patch and strong pro arguments would go a long > way towards incorporating this feature. > > regards, > - assaf > > > -- Time is the fire in which we all burn. --3auohxm5ypw3cvru Content-Type: text/plain; charset=us-ascii Content-Description: updated benchmarking script Content-Disposition: attachment; filename=uniq_demo # Report heading. echo 'lines,line length,percent unique,algorithm,time(sec),memory(K)' # Benchmark with increasing lines of data... for data_lines in 1 10 100 1000 10000 100000 1000000 ; do # Benchmark with increasing line length.. for line_length in 1 10 100 1000 ; do # Synchronize cached writes to persistent storage sync # Generate a certain number of lines of random data of a certain length tr -cd '[[:alnum:]]' < /dev/urandom | fold -bw "$line_length" | head -n "$data_lines" > /tmp/data # Calculate the percentage of lines that are unique. number_of_unique_lines="$( sort -u /tmp/data | wc -l )" percent_unique="$( calc -dp "$number_of_unique_lines/$data_lines" )" # Benchmark sort with its unique option. /usr/bin/time -o /tmp/sort_time -f %e,%M sort -u /tmp/data > /dev/null echo "$data_lines,$line_length,$percent_unique,sort,$( cat /tmp/sort_time )" # Benchmark gawk hashing. /usr/bin/time -o /tmp/gawk_time -f %e,%M gawk '!seen[$0]++' /tmp/data > /dev/null echo "$data_lines,$line_length,$percent_unique,gawk,$( cat /tmp/gawk_time )" # Benchmark mawk hashing. /usr/bin/time -o /tmp/mawk_time -f %e,%M mawk '!seen[$0]++' /tmp/data > /dev/null echo "$data_lines,$line_length,$percent_unique,mawk,$( cat /tmp/mawk_time )" # Benchmark datamash. /usr/bin/time -o /tmp/datamash_time -f %e,%M cat /tmp/data | datamash rmdup 1 > /dev/null echo "$data_lines,$line_length,$percent_unique,datamash,$( cat /tmp/datamash_time )" # Benchmark a pipe of sort and unique. /usr/bin/time -o /tmp/sort_and_uniq_time -f %e,%M sort /tmp/data | uniq > /dev/null echo "$data_lines,$line_length,$percent_unique,sort and uniq,$( cat /tmp/sort_and_uniq_time )" done done --3auohxm5ypw3cvru Content-Type: application/gnumeric Content-Description: updated gnumeric spread sheet Content-Disposition: attachment; filename="hash_and_sort_benchmarks.2.gnumeric" Content-Transfer-Encoding: base64 H4sIAAAAAAAAA+3da2/bSJYG4O/9K7RqYDA72MiqKhYvno4H7sRJjHWcwHZ37/RiYSgSY3Mj iR6KzmV+/RYpWbRk1dE5fAnMTvf0LgYRRR6V+Iq3R0f0D3/5Opv2PqfFIsvnz/tqMOz30vk4 n2Tzm+f9n65ePYv7fzn67oeb+ezwl7z49CHPP/XcIvPFoZv0vH9blneHBwdfvnwZ3MzvZ2mR jQd5cXPwWQ0Hk3LSX837dZFtzPvF1HPp4VAd/Nfbs8vxbTobPcvmi3I0H6duqUV2uKgnnuXj UVmPzftSyeDrYtI/+q7Xq4f58/LN9E7u8vGte0v93tvR/+aF+5d2/8zm1T9N0u+9up9Oq3es 9MA9PFgvf1yWRfbhvkwX1aTtictpq6nz0Sw9elgtP2fpl8PDxW3+5fo2L7K/5/NyNL1ejIt8 Ov0wKn44WC/xuMTn0fQ+Pbq6+OlkOcPy8fKFD3a8covRuHTLbPz/YyzzvEyrSdfl6MPiHzKM SX49ui/z63E+u5um1UfrHzKMbHF9V7iVMS7TCTmAV8dnl6wRbE2qP70/5B8/ZuPUvemx22Lm 5bNZWo5W2+Tyqef9+2J+mI8W2aIeweKwHB/md+n8YZHDx3Mf1juI1TY9zeafdm3VKkmSg/rZ h1kn4/V8d/fFtJ5rMj5Ip2n1CosDtxEePMxbjZA7qGrex0PK83z9QtXsy0E/7GqCg+Xjfm/1 Zh7t9nR/tV5XT1WV12FMxoeTkVvJeqjiZ8PomVJXenio7KFRv/5w8PDsw9z1oMZFWu+2nm0v qJJD9/+BdQvumHGV7dYg1hM2YlzvsF6MpuP7aV3F7erm96PpReo2d7fO3Yo5mY8+TNPTMi1W u9F6f/h1PWHhpgzdfOsJV/nU/WtefTKGA7d/djvKaT4qL0aT7Ovzvl49fJndZKVb1ppHe87L 2zQtz11ep/NJ+vXRVrF+olePN5+6JbUN+/XDi/yLexhaa8L+0f08+9v1JJ3lg2l+M9DLz/R6 8eZj/vSl6hd6neZu1RTfer9kk7La+QeBe29v0uzmtnSDjZLt0S62R9l7mS3upqNvr/Ji5lbq ol6Jb7JJ+mta5OsHr4tssn7g3s+bdDRJi/UU95YeTVlVfHdfum0iXdQRrB5cfpt9cGvjx3Sa f9kx/WI5bjf952yRfcimWfntef/1+dvryzcnJ1fXP59env54enZ69dflP89O+r1qaG5E1VFu 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 --3auohxm5ypw3cvru Content-Type: text/plain; charset=us-ascii Content-Description: new benchmark results Content-Disposition: attachment; filename="uniq_demo.log.2" lines,line length,percent unique,algorithm,time(sec),memory(K) 1,1,1,sort,0.00,1848 1,1,1,gawk,0.00,3424 1,1,1,mawk,0.00,1780 1,1,1,datamash,0.00,1580 1,1,1,sort and uniq,0.00,1828 1,10,1,sort,0.00,1916 1,10,1,gawk,0.00,3352 1,10,1,mawk,0.00,1832 1,10,1,datamash,0.00,1560 1,10,1,sort and uniq,0.00,1828 1,100,1,sort,0.00,1940 1,100,1,gawk,0.00,3324 1,100,1,mawk,0.00,1680 1,100,1,datamash,0.00,1564 1,100,1,sort and uniq,0.00,1904 1,1000,1,sort,0.00,1788 1,1000,1,gawk,0.00,3312 1,1000,1,mawk,0.00,1740 1,1000,1,datamash,0.00,1704 1,1000,1,sort and uniq,0.00,1916 10,1,0.9,sort,0.00,1780 10,1,0.9,gawk,0.00,3412 10,1,0.9,mawk,0.00,1628 10,1,0.9,datamash,0.00,1584 10,1,0.9,sort and uniq,0.00,1840 10,10,1,sort,0.00,1864 10,10,1,gawk,0.00,3444 10,10,1,mawk,0.00,1792 10,10,1,datamash,0.00,1616 10,10,1,sort and uniq,0.00,1928 10,100,1,sort,0.00,1792 10,100,1,gawk,0.00,3252 10,100,1,mawk,0.00,1784 10,100,1,datamash,0.00,1620 10,100,1,sort and uniq,0.00,1964 10,1000,1,sort,0.00,1972 10,1000,1,gawk,0.00,3248 10,1000,1,mawk,0.00,1772 10,1000,1,datamash,0.00,1640 10,1000,1,sort and uniq,0.00,1948 100,1,0.49,sort,0.00,1920 100,1,0.49,gawk,0.00,3516 100,1,0.49,mawk,0.00,1636 100,1,0.49,datamash,0.00,1616 100,1,0.49,sort and uniq,0.00,1828 100,10,1,sort,0.00,1968 100,10,1,gawk,0.00,3548 100,10,1,mawk,0.00,1696 100,10,1,datamash,0.00,1668 100,10,1,sort and uniq,0.00,1924 100,100,1,sort,0.00,1916 100,100,1,gawk,0.00,3536 100,100,1,mawk,0.00,1776 100,100,1,datamash,0.00,1632 100,100,1,sort and uniq,0.00,1928 100,1000,1,sort,0.00,1868 100,1000,1,gawk,0.00,3544 100,1000,1,mawk,0.00,1852 100,1000,1,datamash,0.00,1664 100,1000,1,sort and uniq,0.00,1784 1000,1,0.064,sort,0.00,1796 1000,1,0.064,gawk,0.00,3464 1000,1,0.064,mawk,0.00,1688 1000,1,0.064,datamash,0.00,1564 1000,1,0.064,sort and uniq,0.00,1920 1000,10,1,sort,0.00,1876 1000,10,1,gawk,0.00,3476 1000,10,1,mawk,0.00,1816 1000,10,1,datamash,0.00,1708 1000,10,1,sort and uniq,0.00,1804 1000,100,1,sort,0.00,2020 1000,100,1,gawk,0.00,3488 1000,100,1,mawk,0.00,1984 1000,100,1,datamash,0.00,1644 1000,100,1,sort and uniq,0.00,1948 1000,1000,1,sort,0.00,2724 1000,1000,1,gawk,0.00,4620 1000,1000,1,mawk,0.00,2876 1000,1000,1,datamash,0.01,1568 1000,1000,1,sort and uniq,0.01,2836 10000,1,0.0064,sort,0.01,1880 10000,1,0.0064,gawk,0.00,3564 10000,1,0.0064,mawk,0.00,1628 10000,1,0.0064,datamash,0.00,1616 10000,1,0.0064,sort and uniq,0.01,1876 10000,10,1,sort,0.03,1944 10000,10,1,gawk,0.02,4904 10000,10,1,mawk,0.00,2484 10000,10,1,datamash,0.01,1664 10000,10,1,sort and uniq,0.02,1884 10000,100,1,sort,0.02,3076 10000,100,1,gawk,0.01,5636 10000,100,1,mawk,0.00,3352 10000,100,1,datamash,0.02,1564 10000,100,1,sort and uniq,0.03,3036 10000,1000,1,sort,0.05,11644 10000,1000,1,gawk,0.06,14328 10000,1000,1,mawk,0.03,12232 10000,1000,1,datamash,0.09,1728 10000,1000,1,sort and uniq,0.10,11772 100000,1,0.00064,sort,0.20,4252 100000,1,0.00064,gawk,0.04,3332 100000,1,0.00064,mawk,0.01,1756 100000,1,0.00064,datamash,0.01,1728 100000,1,0.00064,sort and uniq,0.21,4252 100000,10,1,sort,0.29,5192 100000,10,1,gawk,0.14,17040 100000,10,1,mawk,0.13,8284 100000,10,1,datamash,0.04,1520 100000,10,1,sort and uniq,0.27,5188 100000,100,1,sort,0.34,13904 100000,100,1,gawk,0.18,26404 100000,100,1,mawk,0.15,17348 100000,100,1,datamash,0.10,1708 100000,100,1,sort and uniq,0.34,13836 100000,1000,1,sort,0.58,101788 100000,1000,1,gawk,0.62,113672 100000,1000,1,mawk,0.42,105888 100000,1000,1,datamash,0.73,1564 100000,1000,1,sort and uniq,0.84,101720 1000000,1,0.000064,sort,1.29,34940 1000000,1,0.000064,gawk,0.44,3304 1000000,1,0.000064,mawk,0.15,1752 1000000,1,0.000064,datamash,0.10,1568 1000000,1,0.000064,sort and uniq,1.33,35088 1000000,10,1,sort,2.66,43728 1000000,10,1,gawk,1.65,138700 1000000,10,1,mawk,1.79,65772 1000000,10,1,datamash,0.44,1620 1000000,10,1,sort and uniq,2.37,44008 1000000,100,1,sort,2.91,131600 1000000,100,1,gawk,2.10,232412 1000000,100,1,mawk,2.32,157876 1000000,100,1,datamash,1.23,1704 1000000,100,1,sort and uniq,3.64,131592 1000000,1000,1,sort,5.36,1010664 1000000,1000,1,gawk,6.53,1107508 1000000,1000,1,mawk,5.23,1042296 1000000,1000,1,datamash,7.79,1620 1000000,1000,1,sort and uniq,7.76,1010804 --3auohxm5ypw3cvru--
X-Loop: help-debbugs@HIDDEN Subject: bug#32099: Benchmarks: Hashing ~70% faster (Was: New uniq option for speed) Resent-From: Bernhard Voelker <mail@HIDDEN> Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> Resent-CC: bug-coreutils@HIDDEN Resent-Date: Thu, 12 Jul 2018 06:45:02 +0000 Resent-Message-ID: <handler.32099.B32099.153137786218466 <at> debbugs.gnu.org> Resent-Sender: help-debbugs@HIDDEN X-GNU-PR-Message: followup 32099 X-GNU-PR-Package: coreutils X-GNU-PR-Keywords: To: Assaf Gordon <assafgordon@HIDDEN>, "Kingsley G. Morse Jr." <kingsley@HIDDEN> Cc: 32099 <at> debbugs.gnu.org, Paul Eggert <eggert@HIDDEN> Received: via spool by 32099-submit <at> debbugs.gnu.org id=B32099.153137786218466 (code B ref 32099); Thu, 12 Jul 2018 06:45:02 +0000 Received: (at 32099) by debbugs.gnu.org; 12 Jul 2018 06:44:22 +0000 Received: from localhost ([127.0.0.1]:56256 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1fdVKv-0004nl-L1 for submit <at> debbugs.gnu.org; Thu, 12 Jul 2018 02:44:21 -0400 Received: from mout.kundenserver.de ([217.72.192.73]:53115) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <mail@HIDDEN>) id 1fdVKt-0004nW-TX for 32099 <at> debbugs.gnu.org; Thu, 12 Jul 2018 02:44:20 -0400 Received: from [192.168.101.10] ([91.1.213.175]) by mrelayeu.kundenserver.de (mreue104 [212.227.15.183]) with ESMTPSA (Nemesis) id 0MLyNI-1fiyyd0Giq-007i8f; Thu, 12 Jul 2018 08:44:03 +0200 References: <20180708210356.c5fwiocbvdndkgxh@HIDDEN> <a499a8ae-df6d-8342-8d89-e105f6b2bc62@HIDDEN> <20180710042953.2w46nfztrxrg6gmi@HIDDEN> <12517fed-acc1-7935-403a-f0a6be3444a3@HIDDEN> From: Bernhard Voelker <mail@HIDDEN> Openpgp: preference=signencrypt Autocrypt: addr=mail@HIDDEN; prefer-encrypt=mutual; keydata= xsBNBFPirzMBCACyzYldTjQ4ufFOkByY5Nn5USb5GFoL48nWBwNHjd9KUbtRRNlQiPNKd6hK Gvd3BGi5aoFKA4ytfRk6jbAbW3jVb3R8wYaV08mOy4KVEKxqN4bxsXlMjNChXVR+rtKDmfI+ oPTL+cPH2X6gW4W02IRbVw0uUhNm6zEedC/gNrY/mTlf1enZ46jxZ7BTUZaG+kx38UMISIMB zSzLRtdkwgmHj4jS3p1fF2cwRqLclIfMjKGpbNFPEXeXKWrCLcqHw78795eAR9q0YvrDkfIn GdDBwfb3VM4NdulwIFzvYZMSXvSbbyPLB5YkHU5aAWQHUse4WlfT5ccDpbzUYldRAvF9ABEB AAHNK0Jlcm5oYXJkIFZvZWxrZXIgPG1haWxAYmVybmhhcmQtdm9lbGtlci5kZT7CwHkEEwEC ACMFAlPirzMCGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRBGUC73lpFxle5wCACC dbs0QaJ0vR3Sff2cKdTk41rUq3YfWngsR///IOU0C5DdkePmCnJE/lUsUy0LRTxcUDLxQR+x QHU8ssRT0JUO9726dI3miy36UdsgmBYaOtLvQcidGmW1R7o0PYYf04+TFtyqKgngOUBPpMgR 6o4UsQxy/OD4bN1WDqOgIjL+D/qJpkKmgp6L6+hhaBCpiOFKRmmV7YyQ3SqVlfQNiHs5ZtkR nXpIjgZARV+GllKucI17bO0CGmTJZ1tstVy0+W3DQT1lbBkTTc++5LONM99D3jjn23l1ocOp folR53F7I4cb2RNfT23v1I59RH37lB9wMOqrKj0UjYAC2YoPGQ3BzsBNBFPirzMBCADXLWWp QihBldY6reca8ZKdc3T9qXEOa3akE3DWKztIBmNJhtYOjmpLYajQTkGa7UoJTnbmZE2Rn6ZE oNnvb0gcFNAIcY95KOI+bjOR8HEgh4cx2REXh6L6olIgyXqt/KFusE4wtVZAFxZl+30HzN6n D+1HvrjXxPJRX6MsIYOYyyX9/6OofwJK6QHODYGp8WL2olHDnmsXg4AT6Wlr7qKpKrQELlcF R4xkvdmgL/Ghw/tK0yJTxMIcewCCZWLPOXRmFRbvAadZWPAgVsJ63siNyUlVnVMSzDgTJl+s l/DMabXpqrJQx3/1Yy6mTaDs3XZT/wmBKaTLXx/LByaPxQQ7ABEBAAHCwF8EGAECAAkFAlPi rzMCGwwACgkQRlAu95aRcZWVPwgAqZT6iTXkoP37wYb41323RzhBcJ8JSk4cyBDBUXX0lMrM 3qhiClKG7phpxVdu817Gwc6Hsecg7FfjQAV8MHQ0ZFeEFdk3b2rKBqfsStc+h49/xF3Fb+if CzR9qeQF82fMSxkg18++7hMcHCMO/hPZ/Q0xRi+lrSr2QKDJQuLzSyVU14TxrCkevZjEhtma VNvcJlJzCbiBXee9Fpc5jITUXPFG8E8dxqo1n+duOyIMgozrAnzP7X5V/Ob/Ozf/aGGX9+Jd inyfCX18nWcHALKMU/36Eua/ylalf/2c2YkBp9KCLVmGgPkUgW52EeRPgroIsiwu+rwCSV6Z UyCJ+OymCg== Message-ID: <673eaa7f-a94f-7ded-f349-35a56ad3c3f8@HIDDEN> Date: Thu, 12 Jul 2018 08:43:59 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.0 MIME-Version: 1.0 In-Reply-To: <12517fed-acc1-7935-403a-f0a6be3444a3@HIDDEN> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit X-Provags-ID: V03:K1:vPiac2B3cGEqdoQsIymHUy3lxmqSF2B4WoRnjZoUJeAnOnGQ/jC B5+7wfEO90ojUTI2Sh4I2eZ076RL52E/uKrATuby2JNFdesFV9H8G/wN5+C3c9dhkahb4M8 olnzhgxYX4UQRHFNS1Fo5D8vc0h0bQR71K3tpUKPdyQBMCSuc5vJ1DqtOyUM1rRQp+1XaPm SOMCMWVVac65XWFX78HuQ== X-UI-Out-Filterresults: notjunk:1;V01:K0:V8uB0LtrHHY=:RhRUY/NFZLEbmITQuAv+xa DC5h41QgiZSr9ESTsR+v9iK8Kw2yqEKd80UkzYLank8yzqaUH3CUX9AOcBuXSvdm4s5gb6nSn kftVy+vZSfOIHqmFDpmsHCFDn8toGeDRkHpPW+O373R5DW7FcdDwPiKJBRVuys/gxLo84nJU9 BJBDzcRvUu83+mBWcnkthjyOlsFybY9NmBmoap/DTwy/ul4sP490ByAxLH/YRrAyFQqarhsA2 sk9gXtdWVRdAmY3FBI+nhoLXW813v4VShsinnPRWPPP6cGd8Nq6dUGb3tQ462uh4EQDyawQJ/ k32e+gL2DEsonROV43Jf3rrnMrtaynFZt2XJPIcTrS3yV6k5iWhUlsqIzT2P+1QjP0jCYR95Y eSwoNuJvvAgond9t/dwKgry32/2ZMiWaM+uI3kPkwxdJepiSorAX4rqzWtpnO/dVVZeIa5TmK qmhatoPq1IYQK0AQNqMYteCzivolpJeCGVkgi8BRV47bgax5xVWVebLryLGvM+jmXNDpjFAsi PQOhr63if2WkHQaPYHMx+IjfKCVkM9F5QC8wLpiBQF5XwvW1b9tva9CxCk7rNyX2sC5//ldPu yJfoBHZtGU4vEji8ALkIKQk/IZeHSXITdl05qSsiRxly9ArzFd+uFRwyrL2Iz7ZiAIpCX71jW RQVqZetinrZJID3GZiuRENy7e2YJwO93e/5EfEkXH4fSaqmh+cwl9ewn2uaEiZlN5ylSFZvLC Y8BHHnRClEwfI1wX X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) On 07/10/2018 08:21 PM, Assaf Gordon wrote: > I would suggest several improvements to the measurements, to ensure > relevant information is conveyed: > > 1. > [...] great summary. With the risk of mentioning already said aspects: 7. Consider all the existing options, i.e. processing modes, of 'uniq' as well. This means, it has to be considered (upfront!) whether introducing an alternate way to do things - in this case hashing - only serves for the trivial case, or whether this would slow down or even contradict the processing with other options, currently: -c, --count prefix lines by the number of occurrences -d, --repeated only print duplicate lines, one for each group -D print all duplicate lines --all-repeated[=METHOD] like -D, but allow separating groups with an empty line; METHOD={none(default),prepend,separate} -f, --skip-fields=N avoid comparing the first N fields --group[=METHOD] show all items, separating groups with an empty line; METHOD={separate(default),prepend,append,both} -i, --ignore-case ignore differences in case when comparing -s, --skip-chars=N avoid comparing the first N characters -u, --unique only print unique lines -z, --zero-terminated line delimiter is NUL, not newline -w, --check-chars=N compare no more than N characters in lines Without deeper thinking about it, especially the combinations with the --group, --repeated and --unique options might be problematic. 8. Standards. POSIX says: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uniq.html The uniq utility shall read an input file comparing adjacent lines, and write one copy of each input line on the output. The second and succeeding copies of repeated adjacent input lines shall not be written. This makes an assumption both on the input and output. Regarding the input, this means that the processing just has to remember the previous line in order to decide whether to print/discard it in the output. Therefore, arbitrary input size is fine. Hashing most probably will have issues with arbitrary input size; I do not talk about 1GB files, but _much_ larger files (yes, we are in 2018 where 1GB is like nothing). Regarding the output, this means that the output is implicitly in sort order as well. Like the input, uniq can discard the already written data from memory because it is sure that uniq doesn't need to consider it anymore. Thus said, a successful optimization idea does not only have to show that it is faster or needs less resources in _some_ cases, but also must prove that it does not tear down many cases including extreme ones. The current implementation might be as-is for a good reason. If it turns out that the optimization idea screws up a single of the above use cases, then the dilemma is whether 2 implementations are warranted to be kept (maintenance!), and whether it is possible to detect the extreme cases early enough to switch from the default to the other processing strategy. https://en.wikipedia.org/wiki/Perfect_is_the_enemy_of_good or D. Knuth: "premature optimization is the root of all evil (or at least most of it) in programming" As Assaf said, a patch with a proof of concept would be helpful ... even if it's just helpful to proof that the current implementation is fine. Have a nice day, Berny
X-Loop: help-debbugs@HIDDEN Subject: bug#32099: Testing with other options (Was: Benchmarks: Hashing ~70% faster ) Resent-From: "Kingsley G. Morse Jr." <kingsley@HIDDEN> Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> Resent-CC: bug-coreutils@HIDDEN Resent-Date: Sat, 14 Jul 2018 03:04:02 +0000 Resent-Message-ID: <handler.32099.B32099.153153739725578 <at> debbugs.gnu.org> Resent-Sender: help-debbugs@HIDDEN X-GNU-PR-Message: followup 32099 X-GNU-PR-Package: coreutils X-GNU-PR-Keywords: To: Bernhard Voelker <mail@HIDDEN> Cc: 32099 <at> debbugs.gnu.org, Assaf Gordon <assafgordon@HIDDEN>, Paul Eggert <eggert@HIDDEN> Received: via spool by 32099-submit <at> debbugs.gnu.org id=B32099.153153739725578 (code B ref 32099); Sat, 14 Jul 2018 03:04:02 +0000 Received: (at 32099) by debbugs.gnu.org; 14 Jul 2018 03:03:17 +0000 Received: from localhost ([127.0.0.1]:59374 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1feAq5-0006eU-67 for submit <at> debbugs.gnu.org; Fri, 13 Jul 2018 23:03:17 -0400 Received: from outbound-smtp02.blacknight.com ([81.17.249.8]:57091) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <kingsley@HIDDEN>) id 1feAq3-0006eD-Dc for 32099 <at> debbugs.gnu.org; Fri, 13 Jul 2018 23:03:16 -0400 Received: from mail.blacknight.com (pemlinmail06.blacknight.ie [81.17.255.152]) by outbound-smtp02.blacknight.com (Postfix) with ESMTPS id 8EA2D98B40 for <32099 <at> debbugs.gnu.org>; Sat, 14 Jul 2018 03:03:09 +0000 (UTC) Received: (qmail 28522 invoked from network); 14 Jul 2018 03:03:09 -0000 Received: from unknown (HELO debian1.loaner.com) (kingsley@HIDDEN@[97.113.25.140]) by 81.17.254.9 with ESMTPSA (AES256-SHA encrypted, authenticated); 14 Jul 2018 03:03:09 -0000 Received: from kingsley by debian1.loaner.com with local (Exim 4.90_1) (envelope-from <kingsley@HIDDEN>) id 1feApp-00057M-JI; Fri, 13 Jul 2018 20:03:01 -0700 Date: Fri, 13 Jul 2018 20:03:01 -0700 From: "Kingsley G. Morse Jr." <kingsley@HIDDEN> Message-ID: <20180714030301.nfye24f77u5nnhmz@HIDDEN> References: <20180708210356.c5fwiocbvdndkgxh@HIDDEN> <a499a8ae-df6d-8342-8d89-e105f6b2bc62@HIDDEN> <20180710042953.2w46nfztrxrg6gmi@HIDDEN> <12517fed-acc1-7935-403a-f0a6be3444a3@HIDDEN> <673eaa7f-a94f-7ded-f349-35a56ad3c3f8@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <673eaa7f-a94f-7ded-f349-35a56ad3c3f8@HIDDEN> User-Agent: NeoMutt/20170306 (1.8.0) X-Spam-Score: -0.7 (/) X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.7 (-) Hey Berny, I like your suggestion of testing whether hashing interferes with any other option. I was glad to see the POSIX standard doesn't explicitly require sorted input or output. If someone writes the patch, I should be able to test it, at least on up to 1 GB of input. So, Kingsley On 07/12/2018 08:43, Bernhard Voelker wrote: > On 07/10/2018 08:21 PM, Assaf Gordon wrote: > > I would suggest several improvements to the measurements, to ensure > > relevant information is conveyed: > > > > 1. > > [...] > > great summary. With the risk of mentioning already said aspects: > > 7. Consider all the existing options, i.e. processing modes, of 'uniq' as well. > This means, it has to be considered (upfront!) whether introducing an alternate > way to do things - in this case hashing - only serves for the trivial case, > or whether this would slow down or even contradict the processing with other > options, currently: > > -c, --count prefix lines by the number of occurrences > -d, --repeated only print duplicate lines, one for each group > -D print all duplicate lines > --all-repeated[=METHOD] like -D, but allow separating groups > with an empty line; > METHOD={none(default),prepend,separate} > -f, --skip-fields=N avoid comparing the first N fields > --group[=METHOD] show all items, separating groups with an empty line; > METHOD={separate(default),prepend,append,both} > -i, --ignore-case ignore differences in case when comparing > -s, --skip-chars=N avoid comparing the first N characters > -u, --unique only print unique lines > -z, --zero-terminated line delimiter is NUL, not newline > -w, --check-chars=N compare no more than N characters in lines > > Without deeper thinking about it, especially the combinations with > the --group, --repeated and --unique options might be problematic. > > 8. Standards. POSIX says: > http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uniq.html > > The uniq utility shall read an input file comparing adjacent lines, > and write one copy of each input line on the output. The second and > succeeding copies of repeated adjacent input lines shall not be written. > > This makes an assumption both on the input and output. > > Regarding the input, this means that the processing just has to remember > the previous line in order to decide whether to print/discard it in the > output. Therefore, arbitrary input size is fine. > Hashing most probably will have issues with arbitrary input size; > I do not talk about 1GB files, but _much_ larger files (yes, we > are in 2018 where 1GB is like nothing). > > Regarding the output, this means that the output is implicitly in > sort order as well. Like the input, uniq can discard the already > written data from memory because it is sure that uniq doesn't need > to consider it anymore. > > > Thus said, a successful optimization idea does not only have to show > that it is faster or needs less resources in _some_ cases, but also > must prove that it does not tear down many cases including extreme > ones. The current implementation might be as-is for a good reason. > If it turns out that the optimization idea screws up a single > of the above use cases, then the dilemma is whether 2 implementations > are warranted to be kept (maintenance!), and whether it is possible > to detect the extreme cases early enough to switch from the default > to the other processing strategy. > > https://en.wikipedia.org/wiki/Perfect_is_the_enemy_of_good > or D. Knuth: > "premature optimization is the root of all evil > (or at least most of it) in programming" > > As Assaf said, a patch with a proof of concept would be helpful ... even > if it's just helpful to proof that the current implementation is fine. > > Have a nice day, > Berny -- Time is the fire in which we all burn.
Received: (at control) by debbugs.gnu.org; 30 Oct 2018 03:31:45 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Oct 29 23:31:45 2018 Received: from localhost ([127.0.0.1]:52811 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1gHKkr-0006cL-Aa for submit <at> debbugs.gnu.org; Mon, 29 Oct 2018 23:31:45 -0400 Received: from mail-pl1-f181.google.com ([209.85.214.181]:43141) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <assafgordon@HIDDEN>) id 1gHKkp-0006XL-Vq for control <at> debbugs.gnu.org; Mon, 29 Oct 2018 23:31:44 -0400 Received: by mail-pl1-f181.google.com with SMTP id g59-v6so788075plb.10 for <control <at> debbugs.gnu.org>; Mon, 29 Oct 2018 20:31:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:message-id:date:user-agent:mime-version:content-language :content-transfer-encoding; bh=7zMes3g9vAyaUzTBDR9x4TLxhVodOG8UP7aexrJ0R5k=; b=ORAZ13rSTFe70PV8HPyPN+boINVzAwkuqZs/x2RQKuMFTNjvAO2nVtkDx7Zl9m0q2o fHJptv371zIxVyX7Ui+YL9BwXy7rSSUzXX4gGodQwk89WFGL8RAn0Hkpd4zw7V4M4gH4 IEHOxvvYC1PxbDYraMERcVJbod5MbjfGAQVbTEmSTY+I6UepjIOEUsGSy2hYD2jedWRJ pWvb+xOPmhwOsaazVqEYL2Z9jE49m6eQlTArdDSTYaQeAtXX2JLrnFDwD/lXn0pOgaf9 4MxGD9VE5KnaWn4bW6BLV1c8c6iRHt+wD5bdM5rQFZz4qKnysImTJlyxxaxWO92oU+pn jRmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:message-id:date:user-agent:mime-version :content-language:content-transfer-encoding; bh=7zMes3g9vAyaUzTBDR9x4TLxhVodOG8UP7aexrJ0R5k=; b=kjiZCKHfR2COlyMB9sh2hgHd2Q5U1oozD3pkX1i5YPbEZzNZHyehtXikWsn4FjbJN8 VqHxeSKwKPmGyUs6qaZD4r6qyH6lECQppOg6WCvEQ9Nf1TSRmAfzgvWT/QFfqfGtOVbt i+8JCW11sjfckM5HVY8Cb746Kq96hMVZPYEMuxjcWPlydux48FEL9dt0zl0BadsYnszb j1fO/B0cuEAuyCVl3dxKKwO8ENlGXZURh771ZIRX46SPoxGy2hI7/+CUahIfmqTy6hbq rSB1vont0EZWnlzV7u1m4WOCB+DQz3PsmKCKLm3beoW+4NtVyB8m6ehcR0fygg/rBjih /q6Q== X-Gm-Message-State: AGRZ1gJ2Emqo2kqhJAD7lTGsnLcfIHFqHTN9XzGznvnXhjEnM+oTugQj /3oelmJwxA+gmx/SCu94n51d7aNmCiA= X-Google-Smtp-Source: AJdET5diyrye1DXcellVAaVmLOc40KeJqGhcnUFVPSpZ5fXGjrIK38KYDuVaL3uL68FCowX/120Pfg== X-Received: by 2002:a17:902:aa:: with SMTP id a39-v6mr13433868pla.296.1540870297650; Mon, 29 Oct 2018 20:31:37 -0700 (PDT) Received: from tomato.housegordon.com (moose.housegordon.com. [184.68.105.38]) by smtp.googlemail.com with ESMTPSA id m11-v6sm28329126pgn.39.2018.10.29.20.31.36 for <control <at> debbugs.gnu.org> (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 29 Oct 2018 20:31:36 -0700 (PDT) To: control <at> debbugs.gnu.org From: Assaf Gordon <assafgordon@HIDDEN> Message-ID: <d6577a58-e564-8253-7c78-ffb84cd32476@HIDDEN> Date: Mon, 29 Oct 2018 21:31:35 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: tags 32099 notabug severity 32099 wishlist close 32099 [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (assafgordon[at]gmail.com) -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.214.181 listed in list.dnswl.org] 1.8 MISSING_SUBJECT Missing Subject: header 0.2 NO_SUBJECT Extra score for no subject X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.0 (+) tags 32099 notabug severity 32099 wishlist close 32099
Received: (at control) by debbugs.gnu.org; 30 Oct 2018 03:31:45 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Oct 29 23:31:45 2018 Received: from localhost ([127.0.0.1]:52811 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1gHKkr-0006cL-Aa for submit <at> debbugs.gnu.org; Mon, 29 Oct 2018 23:31:45 -0400 Received: from mail-pl1-f181.google.com ([209.85.214.181]:43141) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <assafgordon@HIDDEN>) id 1gHKkp-0006XL-Vq for control <at> debbugs.gnu.org; Mon, 29 Oct 2018 23:31:44 -0400 Received: by mail-pl1-f181.google.com with SMTP id g59-v6so788075plb.10 for <control <at> debbugs.gnu.org>; Mon, 29 Oct 2018 20:31:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:message-id:date:user-agent:mime-version:content-language :content-transfer-encoding; bh=7zMes3g9vAyaUzTBDR9x4TLxhVodOG8UP7aexrJ0R5k=; b=ORAZ13rSTFe70PV8HPyPN+boINVzAwkuqZs/x2RQKuMFTNjvAO2nVtkDx7Zl9m0q2o fHJptv371zIxVyX7Ui+YL9BwXy7rSSUzXX4gGodQwk89WFGL8RAn0Hkpd4zw7V4M4gH4 IEHOxvvYC1PxbDYraMERcVJbod5MbjfGAQVbTEmSTY+I6UepjIOEUsGSy2hYD2jedWRJ pWvb+xOPmhwOsaazVqEYL2Z9jE49m6eQlTArdDSTYaQeAtXX2JLrnFDwD/lXn0pOgaf9 4MxGD9VE5KnaWn4bW6BLV1c8c6iRHt+wD5bdM5rQFZz4qKnysImTJlyxxaxWO92oU+pn jRmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:message-id:date:user-agent:mime-version :content-language:content-transfer-encoding; bh=7zMes3g9vAyaUzTBDR9x4TLxhVodOG8UP7aexrJ0R5k=; b=kjiZCKHfR2COlyMB9sh2hgHd2Q5U1oozD3pkX1i5YPbEZzNZHyehtXikWsn4FjbJN8 VqHxeSKwKPmGyUs6qaZD4r6qyH6lECQppOg6WCvEQ9Nf1TSRmAfzgvWT/QFfqfGtOVbt i+8JCW11sjfckM5HVY8Cb746Kq96hMVZPYEMuxjcWPlydux48FEL9dt0zl0BadsYnszb j1fO/B0cuEAuyCVl3dxKKwO8ENlGXZURh771ZIRX46SPoxGy2hI7/+CUahIfmqTy6hbq rSB1vont0EZWnlzV7u1m4WOCB+DQz3PsmKCKLm3beoW+4NtVyB8m6ehcR0fygg/rBjih /q6Q== X-Gm-Message-State: AGRZ1gJ2Emqo2kqhJAD7lTGsnLcfIHFqHTN9XzGznvnXhjEnM+oTugQj /3oelmJwxA+gmx/SCu94n51d7aNmCiA= X-Google-Smtp-Source: AJdET5diyrye1DXcellVAaVmLOc40KeJqGhcnUFVPSpZ5fXGjrIK38KYDuVaL3uL68FCowX/120Pfg== X-Received: by 2002:a17:902:aa:: with SMTP id a39-v6mr13433868pla.296.1540870297650; Mon, 29 Oct 2018 20:31:37 -0700 (PDT) Received: from tomato.housegordon.com (moose.housegordon.com. [184.68.105.38]) by smtp.googlemail.com with ESMTPSA id m11-v6sm28329126pgn.39.2018.10.29.20.31.36 for <control <at> debbugs.gnu.org> (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 29 Oct 2018 20:31:36 -0700 (PDT) To: control <at> debbugs.gnu.org From: Assaf Gordon <assafgordon@HIDDEN> Message-ID: <d6577a58-e564-8253-7c78-ffb84cd32476@HIDDEN> Date: Mon, 29 Oct 2018 21:31:35 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: tags 32099 notabug severity 32099 wishlist close 32099 [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (assafgordon[at]gmail.com) -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.214.181 listed in list.dnswl.org] 1.8 MISSING_SUBJECT Missing Subject: header 0.2 NO_SUBJECT Extra score for no subject X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.0 (+) tags 32099 notabug severity 32099 wishlist close 32099
Received: (at control) by debbugs.gnu.org; 30 Oct 2018 03:31:45 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Oct 29 23:31:45 2018 Received: from localhost ([127.0.0.1]:52811 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1gHKkr-0006cL-Aa for submit <at> debbugs.gnu.org; Mon, 29 Oct 2018 23:31:45 -0400 Received: from mail-pl1-f181.google.com ([209.85.214.181]:43141) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <assafgordon@HIDDEN>) id 1gHKkp-0006XL-Vq for control <at> debbugs.gnu.org; Mon, 29 Oct 2018 23:31:44 -0400 Received: by mail-pl1-f181.google.com with SMTP id g59-v6so788075plb.10 for <control <at> debbugs.gnu.org>; Mon, 29 Oct 2018 20:31:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:message-id:date:user-agent:mime-version:content-language :content-transfer-encoding; bh=7zMes3g9vAyaUzTBDR9x4TLxhVodOG8UP7aexrJ0R5k=; b=ORAZ13rSTFe70PV8HPyPN+boINVzAwkuqZs/x2RQKuMFTNjvAO2nVtkDx7Zl9m0q2o fHJptv371zIxVyX7Ui+YL9BwXy7rSSUzXX4gGodQwk89WFGL8RAn0Hkpd4zw7V4M4gH4 IEHOxvvYC1PxbDYraMERcVJbod5MbjfGAQVbTEmSTY+I6UepjIOEUsGSy2hYD2jedWRJ pWvb+xOPmhwOsaazVqEYL2Z9jE49m6eQlTArdDSTYaQeAtXX2JLrnFDwD/lXn0pOgaf9 4MxGD9VE5KnaWn4bW6BLV1c8c6iRHt+wD5bdM5rQFZz4qKnysImTJlyxxaxWO92oU+pn jRmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:message-id:date:user-agent:mime-version :content-language:content-transfer-encoding; bh=7zMes3g9vAyaUzTBDR9x4TLxhVodOG8UP7aexrJ0R5k=; b=kjiZCKHfR2COlyMB9sh2hgHd2Q5U1oozD3pkX1i5YPbEZzNZHyehtXikWsn4FjbJN8 VqHxeSKwKPmGyUs6qaZD4r6qyH6lECQppOg6WCvEQ9Nf1TSRmAfzgvWT/QFfqfGtOVbt i+8JCW11sjfckM5HVY8Cb746Kq96hMVZPYEMuxjcWPlydux48FEL9dt0zl0BadsYnszb j1fO/B0cuEAuyCVl3dxKKwO8ENlGXZURh771ZIRX46SPoxGy2hI7/+CUahIfmqTy6hbq rSB1vont0EZWnlzV7u1m4WOCB+DQz3PsmKCKLm3beoW+4NtVyB8m6ehcR0fygg/rBjih /q6Q== X-Gm-Message-State: AGRZ1gJ2Emqo2kqhJAD7lTGsnLcfIHFqHTN9XzGznvnXhjEnM+oTugQj /3oelmJwxA+gmx/SCu94n51d7aNmCiA= X-Google-Smtp-Source: AJdET5diyrye1DXcellVAaVmLOc40KeJqGhcnUFVPSpZ5fXGjrIK38KYDuVaL3uL68FCowX/120Pfg== X-Received: by 2002:a17:902:aa:: with SMTP id a39-v6mr13433868pla.296.1540870297650; Mon, 29 Oct 2018 20:31:37 -0700 (PDT) Received: from tomato.housegordon.com (moose.housegordon.com. [184.68.105.38]) by smtp.googlemail.com with ESMTPSA id m11-v6sm28329126pgn.39.2018.10.29.20.31.36 for <control <at> debbugs.gnu.org> (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 29 Oct 2018 20:31:36 -0700 (PDT) To: control <at> debbugs.gnu.org From: Assaf Gordon <assafgordon@HIDDEN> Message-ID: <d6577a58-e564-8253-7c78-ffb84cd32476@HIDDEN> Date: Mon, 29 Oct 2018 21:31:35 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: tags 32099 notabug severity 32099 wishlist close 32099 [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (assafgordon[at]gmail.com) -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.214.181 listed in list.dnswl.org] 1.8 MISSING_SUBJECT Missing Subject: header 0.2 NO_SUBJECT Extra score for no subject X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.0 (+) tags 32099 notabug severity 32099 wishlist close 32099
Received: (at control) by debbugs.gnu.org; 30 Oct 2018 03:32:26 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Oct 29 23:32:26 2018 Received: from localhost ([127.0.0.1]:52817 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1gHKlW-00075I-Ik for submit <at> debbugs.gnu.org; Mon, 29 Oct 2018 23:32:26 -0400 Received: from mail-pg1-f175.google.com ([209.85.215.175]:46020) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <assafgordon@HIDDEN>) id 1gHKlU-00070c-GT for control <at> debbugs.gnu.org; Mon, 29 Oct 2018 23:32:24 -0400 Received: by mail-pg1-f175.google.com with SMTP id s3-v6so4900990pga.12 for <control <at> debbugs.gnu.org>; Mon, 29 Oct 2018 20:32:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:message-id:date:user-agent:mime-version:content-language :content-transfer-encoding; bh=eKBUMexgTKwZWcTtyLQPf0UgcvSPTeHswYbb/yN04Gk=; b=XB4bdVEBKEiup50FKYbS0/+Dd/eCf+VSh9ZuBhR1MR1m0KPnSNueTjcbdQgRzUi5j/ O6Q3vBf8f1vAR2Ke39EURM2tUE+eyMPfDf64ahVl6JQ0QDyh1cu1rkau/9PlU1oIn2om Bsd+QTv7NbepIR6wVt7+QVzRQCfhoRHQ/v1PvR58bMf8jX/h3pD5JKsQBKa4rtnVFEbs 7lIDl+sv2q2Dm0HLU/AeXXqGGdDZYoYmJZ1vqevHCUXJNJwkFemGZDGgMh7dSR62ZtGy h6SFrzCv+TwbLxVxSzHcDw/TY5kAgYw9RNBDBLT7jumPa7QXmQhK+8U0SXNSOb9NmCYq 3r9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:message-id:date:user-agent:mime-version :content-language:content-transfer-encoding; bh=eKBUMexgTKwZWcTtyLQPf0UgcvSPTeHswYbb/yN04Gk=; b=ArldGz1JSeD+QYWX1ZAk+1eHxIly/aq7KWXXERFMU6+JTwDA6JMbtbIrLnKXTQ0x3c HofXDoWUoCbkei1Zgy+X74GFC0SEdrVj4RClSzQXyKGvKJPjZnC6v1Rau0yZQU0HxEHC zOudaXRgEUYeLUCcKjbccwKVacdv0EGKOg5F9/FSeajQMKS9bGHpeUD53ZH6khMjmxi4 yumf2WwyCzeP2FynrH1Qwu4My4VeCMzfc/SiJFHpOq59gXgXSlNMi3MBUr7F7RFZi8DU hvocM65KwsNcKo6mXqPgydGK5DukLmsxEEka5zenMdWyMQMcoEKjE/Bq91bSMJYcB8LM Q8YA== X-Gm-Message-State: AGRZ1gKCOvewwzfWPHR7FAVJzIOkkqP9ESVq5FvgORRL/tdybJ/U71cg gubVNDHzbNhV66jyO5QvYpnYFVrM5fU= X-Google-Smtp-Source: AJdET5dVqJRKMVoex+plCp4rtg4xcGJmz/eUNIBV8UQMQze4oOqFJod3+Q9lTyfStfPWaj1b8qS41A== X-Received: by 2002:a62:6dc3:: with SMTP id i186-v6mr1196455pfc.218.1540870338192; Mon, 29 Oct 2018 20:32:18 -0700 (PDT) Received: from tomato.housegordon.com (moose.housegordon.com. [184.68.105.38]) by smtp.googlemail.com with ESMTPSA id g14-v6sm22785335pfb.130.2018.10.29.20.32.15 for <control <at> debbugs.gnu.org> (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 29 Oct 2018 20:32:16 -0700 (PDT) To: control <at> debbugs.gnu.org From: Assaf Gordon <assafgordon@HIDDEN> Message-ID: <cf7fbe87-017d-5ea7-c10c-6fc7b03f50ba@HIDDEN> Date: Mon, 29 Oct 2018 21:32:15 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: forcemerge 32101 32099 [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.215.175 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (assafgordon[at]gmail.com) -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.215.175 listed in wl.mailspike.net] 1.8 MISSING_SUBJECT Missing Subject: header 0.2 NO_SUBJECT Extra score for no subject X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.0 (+) forcemerge 32101 32099
Received: (at control) by debbugs.gnu.org; 30 Oct 2018 09:09:10 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Oct 30 05:09:10 2018 Received: from localhost ([127.0.0.1]:53313 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1gHQ1N-0005Dd-Rs for submit <at> debbugs.gnu.org; Tue, 30 Oct 2018 05:09:09 -0400 Received: from mail-pg1-f177.google.com ([209.85.215.177]:33658) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <assafgordon@HIDDEN>) id 1gHQ1L-0005DP-OZ for control <at> debbugs.gnu.org; Tue, 30 Oct 2018 05:09:08 -0400 Received: by mail-pg1-f177.google.com with SMTP id q5-v6so1622230pgv.0 for <control <at> debbugs.gnu.org>; Tue, 30 Oct 2018 02:09:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:message-id:date:user-agent:mime-version:content-language :content-transfer-encoding; bh=2Fvytln3NPXOFqUcwPcIq0sx4mLWc0x4+HcuDsiuwIY=; b=K37FcZ3zIWiGWRVkjHVcnXAUaECM/B+b/5erQVK7767gqt4PT6G79DNV2dLHUSb+Jf nbjyMFpC+CqkCI5kDRP7fttPNEcqDG7MTwJ6lCM800nI8ecFadMVj/WAOt4iIHQxhbxr +dF4FChgJvL9hcgkTv8vOROr8Fm3PTM7gm0FCgoZ5zV6px5GjmezcdzgpUkfB/b1C3s9 rqwFJaiMBAP8ZDcSl6UA1lWZM4iVBTvtnBhJbCm4XboEF0yP4OlNiJgbweMNrBO9N/da QoK7I4Ze6YuTNZ8s0tBBrUvJgU5H35wgD8Fn+osfGM8cRMhFreeSGfxlcgor6iWwWhXx EVxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:message-id:date:user-agent:mime-version :content-language:content-transfer-encoding; bh=2Fvytln3NPXOFqUcwPcIq0sx4mLWc0x4+HcuDsiuwIY=; b=g3l+APZUPA28r3oNXHBwSbccAf48tKmVj8/t55KUSkQmm2PJ47qnNHk75ZahGwuFyr KeKLTpUSQEExSsYj85VnQPdaFir8+JFky6Dl5lQZd4wA2PKA9Bw3aPhgzD23Dn9CT3+K oRyzwx6b+dOsW94NNxChc16WLl6AImiralYOqsM2N6lS0hX7/NN5IUUbtDIeih6Bjwei lYk5GYyMYBP3tHCwpc/8saLA6ydLCp/HuMiswA0u3SyjdYbEQqRtyGMVoR35knHCrSEf YCRp6ulX/6PGFgK5xXJwzXq1up7FfOBuNpVsk2KJ94UqCa4LrTueeLeX9BIQeQYYDrA+ xNqQ== X-Gm-Message-State: AGRZ1gJVZ0d7jG2JkU9qByoFYTsRduJA9PLfOFX07vaLfTMEjy1c2XHs yYCX/12ScxmCKcQDvqtzvVP4hMK0E6c= X-Google-Smtp-Source: AJdET5dkLxrEnVUOJn2i3aYeQIu2WQteboZ8PBw4ewB4mr46K21/PG33DLGYJ27813RyTDp1M6Cojg== X-Received: by 2002:a63:8f09:: with SMTP id n9-v6mr16985458pgd.222.1540890540790; Tue, 30 Oct 2018 02:09:00 -0700 (PDT) Received: from tomato.housegordon.com (moose.housegordon.com. [184.68.105.38]) by smtp.googlemail.com with ESMTPSA id h21-v6sm180124pfn.80.2018.10.30.02.08.58 for <control <at> debbugs.gnu.org> (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 30 Oct 2018 02:08:59 -0700 (PDT) To: control <at> debbugs.gnu.org From: Assaf Gordon <assafgordon@HIDDEN> Message-ID: <9c8db5fe-af8f-4f77-4b4e-cb73b55fe519@HIDDEN> Date: Tue, 30 Oct 2018 03:08:52 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: severity 32099 wishlist retitle 32099 uniq: add hash-based implementation [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.215.177 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (assafgordon[at]gmail.com) 1.8 MISSING_SUBJECT Missing Subject: header 0.2 NO_SUBJECT Extra score for no subject X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.0 (+) severity 32099 wishlist retitle 32099 uniq: add hash-based implementation
Received: (at control) by debbugs.gnu.org; 30 Oct 2018 09:09:10 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Oct 30 05:09:10 2018 Received: from localhost ([127.0.0.1]:53313 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1gHQ1N-0005Dd-Rs for submit <at> debbugs.gnu.org; Tue, 30 Oct 2018 05:09:09 -0400 Received: from mail-pg1-f177.google.com ([209.85.215.177]:33658) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <assafgordon@HIDDEN>) id 1gHQ1L-0005DP-OZ for control <at> debbugs.gnu.org; Tue, 30 Oct 2018 05:09:08 -0400 Received: by mail-pg1-f177.google.com with SMTP id q5-v6so1622230pgv.0 for <control <at> debbugs.gnu.org>; Tue, 30 Oct 2018 02:09:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:message-id:date:user-agent:mime-version:content-language :content-transfer-encoding; bh=2Fvytln3NPXOFqUcwPcIq0sx4mLWc0x4+HcuDsiuwIY=; b=K37FcZ3zIWiGWRVkjHVcnXAUaECM/B+b/5erQVK7767gqt4PT6G79DNV2dLHUSb+Jf nbjyMFpC+CqkCI5kDRP7fttPNEcqDG7MTwJ6lCM800nI8ecFadMVj/WAOt4iIHQxhbxr +dF4FChgJvL9hcgkTv8vOROr8Fm3PTM7gm0FCgoZ5zV6px5GjmezcdzgpUkfB/b1C3s9 rqwFJaiMBAP8ZDcSl6UA1lWZM4iVBTvtnBhJbCm4XboEF0yP4OlNiJgbweMNrBO9N/da QoK7I4Ze6YuTNZ8s0tBBrUvJgU5H35wgD8Fn+osfGM8cRMhFreeSGfxlcgor6iWwWhXx EVxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:message-id:date:user-agent:mime-version :content-language:content-transfer-encoding; bh=2Fvytln3NPXOFqUcwPcIq0sx4mLWc0x4+HcuDsiuwIY=; b=g3l+APZUPA28r3oNXHBwSbccAf48tKmVj8/t55KUSkQmm2PJ47qnNHk75ZahGwuFyr KeKLTpUSQEExSsYj85VnQPdaFir8+JFky6Dl5lQZd4wA2PKA9Bw3aPhgzD23Dn9CT3+K oRyzwx6b+dOsW94NNxChc16WLl6AImiralYOqsM2N6lS0hX7/NN5IUUbtDIeih6Bjwei lYk5GYyMYBP3tHCwpc/8saLA6ydLCp/HuMiswA0u3SyjdYbEQqRtyGMVoR35knHCrSEf YCRp6ulX/6PGFgK5xXJwzXq1up7FfOBuNpVsk2KJ94UqCa4LrTueeLeX9BIQeQYYDrA+ xNqQ== X-Gm-Message-State: AGRZ1gJVZ0d7jG2JkU9qByoFYTsRduJA9PLfOFX07vaLfTMEjy1c2XHs yYCX/12ScxmCKcQDvqtzvVP4hMK0E6c= X-Google-Smtp-Source: AJdET5dkLxrEnVUOJn2i3aYeQIu2WQteboZ8PBw4ewB4mr46K21/PG33DLGYJ27813RyTDp1M6Cojg== X-Received: by 2002:a63:8f09:: with SMTP id n9-v6mr16985458pgd.222.1540890540790; Tue, 30 Oct 2018 02:09:00 -0700 (PDT) Received: from tomato.housegordon.com (moose.housegordon.com. [184.68.105.38]) by smtp.googlemail.com with ESMTPSA id h21-v6sm180124pfn.80.2018.10.30.02.08.58 for <control <at> debbugs.gnu.org> (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 30 Oct 2018 02:08:59 -0700 (PDT) To: control <at> debbugs.gnu.org From: Assaf Gordon <assafgordon@HIDDEN> Message-ID: <9c8db5fe-af8f-4f77-4b4e-cb73b55fe519@HIDDEN> Date: Tue, 30 Oct 2018 03:08:52 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: severity 32099 wishlist retitle 32099 uniq: add hash-based implementation [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.215.177 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (assafgordon[at]gmail.com) 1.8 MISSING_SUBJECT Missing Subject: header 0.2 NO_SUBJECT Extra score for no subject X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.0 (+) severity 32099 wishlist retitle 32099 uniq: add hash-based implementation
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997 nCipher Corporation Ltd,
1994-97 Ian Jackson.