Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vwkSU-00AWMl-05 for pgsql-hackers@arkaria.postgresql.org; Sun, 01 Mar 2026 17:19:58 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vwkSS-00DwxL-2O for pgsql-hackers@arkaria.postgresql.org; Sun, 01 Mar 2026 17:19:56 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vwkSS-00DwxD-0x for pgsql-hackers@lists.postgresql.org; Sun, 01 Mar 2026 17:19:56 +0000 Received: from mail-wr1-x433.google.com ([2a00:1450:4864:20::433]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vwkSO-00000001xjl-2jk2 for pgsql-hackers@lists.postgresql.org; Sun, 01 Mar 2026 17:19:55 +0000 Received: by mail-wr1-x433.google.com with SMTP id ffacd0b85a97d-4398f8e2837so3230608f8f.1 for ; Sun, 01 Mar 2026 09:19:53 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1772385591; cv=none; d=google.com; s=arc-20240605; b=RajcRXDV7SA36/FQeXEcAQNMBvQUuF/ZQBsZ3jiih2qi1g72LGT+U45akp+C+97FxX sik4hBpw8iW7sGegK4UMADgPSsCcPzUislpkeZ27aNj5R9mgw6Iff/9KXH0b7XbWwG3Y YqY3eB2tFUIdDLGb/pHA6HETeB7okhI2XzXcPxs9bAhR1Spgf2zBUsvHdhI+Lnv443+q 5csTDiZCdJKfjVUnEiELKV/dDlVk45ZwGPfJdRZ2CM1VLhqux5q6qmWisQJ3yCMQhFj5 DP9sHvoygOu1li4mtmN9Bgk7+kvuLTpH3XCxHXcEyRenqMWg2tektHwkKfRsvKEITq+p e0Gg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=QUyGO4ERob4gK34eWPIWo8xQ5QeVh6rFN+Iyi87pC+E=; fh=hBP7RcD0+t816pqE3jxoWOJjw9ZlfF9wd8GdGGA8CLo=; b=MBJaFTpI3G9PePyN92MKkkoBX8WWJHipEN/+bsV/e/LGVDdjvP8rvUDEKBba4L1KTq JkUX79T25RdcXfhLKs+uZn6GQ50ZH8ZuOrT6i7oZKm7WCIEGorXlO9QtyQd6wLxeinRP eTq9GXwtWu5N4T2ToeAg4rjU1+EorRcDc31Oanx7ZmXvoNHDeUwcELZX5b3r5Ww7lKUT 1OZ/aDgM7+91wl8m5kTjEiRqwimzfwDLBEAILvOGjGzNIWS7XK+Yxna3+2rf3hXrt5Gk HneOkl87vwV+rIPIGd353KYMg7WRvccx6/P8+ik+2n9rMRlbzQnXEosF0ClKsbbK/hjy JMIQ==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cybertec.at; s=google; t=1772385591; x=1772990391; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=QUyGO4ERob4gK34eWPIWo8xQ5QeVh6rFN+Iyi87pC+E=; b=dHuYC4bvTJJ/mK/Pfo7KpSLkRJ0SP2zdoJ7WB8c5Di5+8aHA94cSJ6ckXMv7p98y/n rSssUleJvyrsOm+yDHcLJ+c2lX9P+os0jkwpASJZnMrLSBKgcvnr+ktCyTnH/sbGi14P qBlEnLgnjTFsA/YD1JK1B6MuB7C5Y0Q1dLkK4LMTdAtiavtua1tda3b+zB1gix+RkxXQ hdomlYh1+SqBe35oGTuBAu1q+KPvOwxoz/VXnm5BQ3P/dEQUIWi2zm8RhqgjxZhNbisk koacByVTPNwKe/QlYHDyZj1ihBbZwRne9nwf47ZOcCeYVv8hLFOxkdozf7nCBvFoJqSu tB0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772385591; x=1772990391; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=QUyGO4ERob4gK34eWPIWo8xQ5QeVh6rFN+Iyi87pC+E=; b=WT1BA/A81eZ52xE+JpA/N5DqKkWD3n8pN/+R/mFE7YnyPmiXfoEzp5ciqhNXZsoYy3 Cx7ZTKfMFbrLxLmjaM+kTkN2twY2k6XC/ZnzGE3hglknvBcypmqr9V4ll8LMhaxmP1UZ L1d+xDilmIIqXzuYfYIXABAXrc5ZHrzSCx9MSYNxaPc2UDUi5D1bk+Lwa6B3hvxyjKiu cc62ad0/AWCVFw8jewFR6iiwob/5f8HdKQb+HavRA1MCE+HNkXALQFynwBtD3ZL4AMGz oLAjFZGCLHVdSfR89P3KZKxe95f+mY/78zirFT72o4HJ245jSB0gAhFaQCZHmgQfDulC 2lMw== X-Forwarded-Encrypted: i=1; AJvYcCVlP+ARO5Ze0jp2u/V+AFqHinh37JsTQivKAqnmzDqf3oQv2My5SHR7rkvjvKNylEvv5ejAC1Pspwf0S1f7@lists.postgresql.org X-Gm-Message-State: AOJu0YwbMez9rJ+uVFPAsbWxpEQSDjat4SteDlgblvEtfy1o5hSb69nf B+nDx7X2JdAf9Ob5djDwEJKzKU7b5gvjkX4jG4dzHucvzPbm8tl8xebOQRvWw//u/B5agu0lpLG fpdWqUjgvRtTn19HyjoR/RvnHsKLabKidHmEcBMev1w== X-Gm-Gg: ATEYQzw2gEDE9b75DIw5jSi1iAIoKMhfTtkgRanKMueASLaVsIxjrkeIQP4Sv/O5nb4 3caKOpn3mfuoNos5StG7/JyklPKXeQqHlQm5D/6BknrDiDiv2whBYbqEoj2JyceKidxnaIJauZm hmgB/7ePaYXVciW9LYr0RI9H841g6VbhoOpqEhH53Ba/HDE55u2WS6UmRi8lGoeTkxb3VRSL6R4 V1zIerY5QZo08rQHHfOFXRdl99FxHMUxaz7QWACmiQCvnLzsLQR5kZQlV2Ie05of/MaHMBcH50T uxxy+wdA X-Received: by 2002:a05:6000:24c5:b0:439:b3c5:ea1f with SMTP id ffacd0b85a97d-439b3c5eb5fmr3712931f8f.16.1772385590740; Sun, 01 Mar 2026 09:19:50 -0800 (PST) MIME-Version: 1.0 References: <5pbulw5plv5owcg5iothxfg5xf6vj6ayfltppsg573kllpnx24@vd2iaqxnkasy> In-Reply-To: From: Ants Aasma Date: Sun, 1 Mar 2026 19:19:38 +0200 X-Gm-Features: AaiRm50JlhgCDsfFWuMY47DW_-UdhkW3GWYRFZG8ydVc_V8uw-SBtMfdcSdqIIY Message-ID: Subject: Re: Hash aggregate collisions cause excessive spilling To: Andres Freund Cc: Tomas Vondra , PostgreSQL Hackers Content-Type: multipart/mixed; boundary="0000000000008abd19064bf9add8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000008abd19064bf9add8 Content-Type: text/plain; charset="UTF-8" On Sat, 28 Feb 2026 at 22:03, Andres Freund wrote: > > This problem should only affect cases where multiple hash tables worth > > of tuples are trying to fit into one. > > Is that entirely true? If we are feeding one hash table from other hash table, > 1:1, and the initial size of the target table is wrong, we probably also won't > handle it in the best way. > > That could happen with a group by over a group by (with perhaps some joins > above the first group by). Probably not that common, but ... > > I guess another case could be a CTAS of a group by query that is then grouped > by again. With 1:1 tables, if the target table is smaller there is going to be a ton of collisions which should quite quickly trigger growth via SH_GROW_MAX_MOVE (150). But once the target table is the same size as source the growth will stop. I think this ends up being slightly more efficient in the correlated case because the table will be growing at 10% fill factor, having less entries to move around. And the access to the target hash table will be more correlated over time for better cache efficiency. However I think it might be possible to have different hash table size limits in a single plan. At least setting hash_mem_multiplier on a function would do it. But I wasn't able to trigger any bad behavior with this for some reason. I will experiment some more. > > I think right now that limits it to hash aggregates with parallel > > query. ExecBuildHash32FromAttrs comment says that we should be using > > non-zero init_value only when needed for a marginal performance gain. So I > > limited the plan node id inclusion to use_variable_hash_iv, but made it > > unconditional for aggregates. > > That's an argument... I guess we could mostly avoid that though, by just > always combining in EEOP_HASHDATUM_FIRST. I think that makes it exactly the same as EEOP_HASHDATUM_NEXT32, making the special op code pointless. I assume David observed some speedup there to go through the effort to include it. >> > I used hash_combine to smear together the bits of the two. I think > > that should be good enough. Alternatively a xor of murmurhash32 of the > > two should be better. > > Probably it's good enough, but i'd probably still go for > hash_combine(murmurhash32(ParallelWorkerNumber), > murmurhash32(parent->plan->plan_node_id)) > or such. Used this approach. > > There is also a call to ExecBuildHash32FromAttrs from ExecInitSubPlan > > that specifies a hash_iv for a hashed sub plan execution. > > When you're saying it specifies a hash IV you mean the 0 it passes, not some > more complicated value, right? Right. > > > This must match the value BuildTupleHashTable decides on. Worth adding a > > comment? > > Yes, I think so. Done. > > */ > > if (use_variable_hash_iv) > > - hash_iv = murmurhash32(ParallelWorkerNumber); > > + hash_iv = hash_combine(ParallelWorkerNumber, parent->plan->plan_node_id); > > > > hashtable->hashtab = tuplehash_create(metacxt, nbuckets, hashtable); > > I think some of the reasoning from your commit messages needs to be in a > comment somewhere too, otherwise the next person tackling this code will have > a hell of a time. I gave it a shot. > > diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c > > index 7d487a165fa..5c947fd151f 100644 > > --- a/src/backend/executor/nodeAgg.c > > +++ b/src/backend/executor/nodeAgg.c > > @@ -1535,7 +1535,7 @@ build_hash_table(AggState *aggstate, int setno, double nbuckets) > > metacxt, > > tuplescxt, > > tmpcxt, > > - DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit)); > > + true); > > } > > Hm, won't that mean we'll now always use the slower path? I think there are > non-partial cases that could be problematic, but if we do this we probaly > should do the optimization of the hash expression stuff I mentioned above. If you mean EEOP_HASHDATUM_FIRST, then I think that would just be removing an optimization. I think getting rid of the quicker growth and correlated table filling in the 1:1 case might be more significant than the slightly slower hash calculation. However the downside of the bad case is pretty nasty. Do you think it's worth the effort of trying to figure out if we are in a dangerous looking structure? Decorrelating the hash tables still doesn't fix the terrible edge case of hash aggregate exceeding memory limit with hash table alone. Just makes it exceedingly improbable to hit with non-antagonistic workloads. Would it be a good idea to fix that too? A simple answer would be to always allow hash aggregate to use some fraction like 25% of allowed memory for tuples, even if the hash table is too big. Regards, Ants Aasma --0000000000008abd19064bf9add8 Content-Type: text/x-patch; charset="US-ASCII"; name="v2-0001-Decorrelate-nested-hash-tables.patch" Content-Disposition: attachment; filename="v2-0001-Decorrelate-nested-hash-tables.patch" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_mm80lkej0 RnJvbSA3YTJhYzlkZjQ3MTdlOTU0NzVlMTBlNjYwMjY0ZGJhNTUwZDViZWU2IE1vbiBTZXAgMTcg MDA6MDA6MDAgMjAwMQpGcm9tOiBBbnRzIEFhc21hIDxhbnRzQGN5YmVydGVjLmF0PgpEYXRlOiBT YXQsIDI4IEZlYiAyMDI2IDE1OjA4OjUwICswMjAwClN1YmplY3Q6IFtQQVRDSCB2Ml0gRGVjb3Jy ZWxhdGUgbmVzdGVkIGhhc2ggdGFibGVzCgpCZWNhdXNlIGhhc2ggdGFibGVzIGFyZSBpdGVyYXRl ZCBpbiBoYXNoIG9yZGVyLCB1c2luZyB0aGUgc2FtZSBoYXNoCmZ1bmN0aW9uIGluIG5lc3RlZCBo YXNoIHRhYmxlcyBjYW4gbGVhZCB0byBleGNlc3NpdmUgY29sbGlzaW9ucy4gSWYgdGhlCnBhcmVu dCBoYXNoIHRhYmxlIGNhbiBiZSB0aGUgc2FtZSBzaXplIGFzIHRoZSBjaGlsZCBoYXNoIHRhYmxl cyBpdCBpcwpub3QgYSBwcm9ibGVtIGFzIHRoZSBwYXJlbnQgd2lsbCBxdWlja2x5IGdyb3cgdG8g dGhlIHNhbWUgc2l6ZSBhcyB0aGUKY2hpbGQsIGVsaW1pbmF0aW5nIGZ1cnRoZXIgY29sbGlzaW9u cy4gQnV0IGlmIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lCmNoaWxkIHRoZSBjb2xsaXNpb25zIGNh biBjYXVzZSB0aGUgdGFibGUgdG8gcXVpY2tseSBncm93IHVudGlsIGl0IGlzCmJlbG93IDEwJSBm aWxsZmFjdG9yLgoKVGhlIHByb2JsZW0gaXMgbWFkZSB3b3JzZSBieSBub2RlQWdnIGRldm9sdmlu ZyBpbnRvIGJ1aWxkaW5nIHNpbmdsZQplbnRyeSBiYXRjaGVzIG9uY2UgaGFzaCB0YWJsZSBzaXpl IGV4Y2VlZHMgd29ya2luZyBtZW1vcnkuCgpUbyBoaXQgdGhlIHByb2JsZW0gYW4gYWdncmVnYXRl IG5vZGUgd2l0aG91dCBhIGZpbmFsIGZ1bmN0aW9uIGFib3ZlCm11bHRpcGxlIG90aGVyIGFnZ3Jl Z2F0ZSBub2RlcyBpcyBuZWVkZWQuIEJlY2F1c2UgaGFzaCBpdiBpcyBhbHJlYWR5CmluaXRpYWxp emVkIHVzaW5nIHBhcmFsbGVsIHdvcmtlciBudW1iZXIgd2hlbiB0aGVyZSBpcyBubyBmaW5hbCBm bgp0aGUgdHlwaWNhbCBjYXNlcyBkbyBub3QgaGl0IHRoaXMgcHJvYmxlbS4gQSBoYXNoIGFnZ3Jl Z2F0ZSBpbXBsZW1lbnRpbmcKRElTVElOQ1QgYWJvdmUgbXVsdGlwbGUgcGFyYWxsZWwgd29ya2Vy cyB3aXRoIG1vcmUgZ3JvdXBzIHRoYW4gZml0IGludG8KbWVtb3J5IGlzIG5lZWRlZC4KCkluaXRp YWxpemluZyB0aGUgaGFzaCBmdW5jdGlvbiBiYXNlZCBvbiBwbGFuIG5vZGUgaWQgZGVjb3JyZWxh dGVzIGhhc2gKdGFibGVzIHdpdGhpbiBhIHBsYW4gd2hpbGUgc3RpbGwga2VlcGluZyBiZWhhdmlv ciBkZXRlcm1pbmlzdGljLgoKQXV0aG9yOiBBbnRzIEFhc21hIDxhbnRzLmFhc21hQGN5YmVydGVj LmF0PgpEaXNjdXNzaW9uOiBodHRwczovL3Bvc3Rnci5lcy9tL0NBTndLaGtQT1p1cHUzUFlRVmRr TW1ZanF1WVZxRzJ2OFhtQ0F1dVZNOUV1MTMtWnczZyU0MG1haWwuZ21haWwuY29tCi0tLQogc3Jj L2JhY2tlbmQvZXhlY3V0b3IvZXhlY0dyb3VwaW5nLmMgfCAxNiArKysrKysrKysrKy0tLS0tCiBz cmMvYmFja2VuZC9leGVjdXRvci9ub2RlQWdnLmMgICAgICB8ICAyICstCiBzcmMvdGVzdC9yZWdy ZXNzL2V4cGVjdGVkL3VuaW9uLm91dCB8ICAyICstCiAzIGZpbGVzIGNoYW5nZWQsIDEzIGluc2Vy dGlvbnMoKyksIDcgZGVsZXRpb25zKC0pCgpkaWZmIC0tZ2l0IGEvc3JjL2JhY2tlbmQvZXhlY3V0 b3IvZXhlY0dyb3VwaW5nLmMgYi9zcmMvYmFja2VuZC9leGVjdXRvci9leGVjR3JvdXBpbmcuYwpp bmRleCBjMTA3NTE0YTg1ZC4uYmZkY2FjYTRlN2QgMTAwNjQ0Ci0tLSBhL3NyYy9iYWNrZW5kL2V4 ZWN1dG9yL2V4ZWNHcm91cGluZy5jCisrKyBiL3NyYy9iYWNrZW5kL2V4ZWN1dG9yL2V4ZWNHcm91 cGluZy5jCkBAIC0xOTksNiArMTk5LDEwIEBAIEJ1aWxkVHVwbGVIYXNoVGFibGUoUGxhblN0YXRl ICpwYXJlbnQsCiAJVHVwbGVIYXNoVGFibGUgaGFzaHRhYmxlOwogCXVpbnQzMgkJbmJ1Y2tldHM7 CiAJTWVtb3J5Q29udGV4dCBvbGRjb250ZXh0OworCS8qCisJICogVGhlIHZhbHVlIGhlcmUgbXVz dCBtYXRjaCB3aGF0IEV4ZWNJbml0U3ViUGxhbiBwYXNzZXMgdG8KKwkgKiBFeGVjQnVpbGRIYXNo MzJGcm9tQXR0cnMuCisJICovCiAJdWludDMyCQloYXNoX2l2ID0gMDsKIAogCS8qCkBAIC0yNDAs MTMgKzI0NCwxNSBAQCBCdWlsZFR1cGxlSGFzaFRhYmxlKFBsYW5TdGF0ZSAqcGFyZW50LAogCS8q CiAJICogSWYgcGFyYWxsZWxpc20gaXMgaW4gdXNlLCBldmVuIGlmIHRoZSBsZWFkZXIgYmFja2Vu ZCBpcyBwZXJmb3JtaW5nIHRoZQogCSAqIHNjYW4gaXRzZWxmLCB3ZSBkb24ndCB3YW50IHRvIGNy ZWF0ZSB0aGUgaGFzaHRhYmxlIGV4YWN0bHkgdGhlIHNhbWUgd2F5Ci0JICogaW4gYWxsIHdvcmtl cnMuIEFzIGhhc2h0YWJsZXMgYXJlIGl0ZXJhdGVkIG92ZXIgaW4ga2V5c3BhY2Utb3JkZXIsCi0J ICogZG9pbmcgc28gaW4gYWxsIHByb2Nlc3NlcyBpbiB0aGUgc2FtZSB3YXkgaXMgbGlrZWx5IHRv IGxlYWQgdG8KLQkgKiAidW5iYWxhbmNlZCIgaGFzaHRhYmxlcyB3aGVuIHRoZSB0YWJsZSBzaXpl IGluaXRpYWxseSBpcwotCSAqIHVuZGVyZXN0aW1hdGVkLgorCSAqIGluIGFsbCB3b3JrZXJzLiBB cyBoYXNodGFibGVzIGFyZSBpdGVyYXRlZCBvdmVyIGluIGhhc2ggdmFsdWUgb3JkZXIsCisJICog aW5zZXJ0aW5nIGludG8gYSBzbWFsbGVyIHRhYmxlIG9yIGZyb20gbXVsdGlwbGUgdGFibGVzIGlz IGdvaW5nIHRvCisJICogY2F1c2UgY29sbGlzaW9ucyB3aGljaCB0cmlnZ2VycyBoYXNoIHRhYmxl IGdyb3d0aC4gSW4gaGFzaCBhZ2dyZWdhdGVzCisJICogYSB0b28gbGFyZ2UgaGFzaCB0YWJsZSBj YXVzZXMgZXhjZXNzaXZlIHNwaWxsaW5nIGFzIHRoZXJlIGlzIG5vIG1lbW9yeQorCSAqIGxlZnQg b3ZlciBmb3IgdHVwbGVzLgogCSAqLwogCWlmICh1c2VfdmFyaWFibGVfaGFzaF9pdikKLQkJaGFz aF9pdiA9IG11cm11cmhhc2gzMihQYXJhbGxlbFdvcmtlck51bWJlcik7CisJCWhhc2hfaXYgPSBo YXNoX2NvbWJpbmUobXVybXVyaGFzaDMyKFBhcmFsbGVsV29ya2VyTnVtYmVyKSwKKwkJCQkJCQkg ICBtdXJtdXJoYXNoMzIocGFyZW50LT5wbGFuLT5wbGFuX25vZGVfaWQpKTsKIAogCWhhc2h0YWJs ZS0+aGFzaHRhYiA9IHR1cGxlaGFzaF9jcmVhdGUobWV0YWN4dCwgbmJ1Y2tldHMsIGhhc2h0YWJs ZSk7CiAKZGlmZiAtLWdpdCBhL3NyYy9iYWNrZW5kL2V4ZWN1dG9yL25vZGVBZ2cuYyBiL3NyYy9i YWNrZW5kL2V4ZWN1dG9yL25vZGVBZ2cuYwppbmRleCA3ZDQ4N2ExNjVmYS4uNWM5NDdmZDE1MWYg MTAwNjQ0Ci0tLSBhL3NyYy9iYWNrZW5kL2V4ZWN1dG9yL25vZGVBZ2cuYworKysgYi9zcmMvYmFj a2VuZC9leGVjdXRvci9ub2RlQWdnLmMKQEAgLTE1MzUsNyArMTUzNSw3IEBAIGJ1aWxkX2hhc2hf dGFibGUoQWdnU3RhdGUgKmFnZ3N0YXRlLCBpbnQgc2V0bm8sIGRvdWJsZSBuYnVja2V0cykKIAkJ CQkJCQkJCQkJIG1ldGFjeHQsCiAJCQkJCQkJCQkJCSB0dXBsZXNjeHQsCiAJCQkJCQkJCQkJCSB0 bXBjeHQsCi0JCQkJCQkJCQkJCSBET19BR0dTUExJVF9TS0lQRklOQUwoYWdnc3RhdGUtPmFnZ3Nw bGl0KSk7CisJCQkJCQkJCQkJCSB0cnVlKTsKIH0KIAogLyoKZGlmZiAtLWdpdCBhL3NyYy90ZXN0 L3JlZ3Jlc3MvZXhwZWN0ZWQvdW5pb24ub3V0IGIvc3JjL3Rlc3QvcmVncmVzcy9leHBlY3RlZC91 bmlvbi5vdXQKaW5kZXggNzA5Yzg1ZjIyOTQuLmZhZDIyYzBlZDJkIDEwMDY0NAotLS0gYS9zcmMv dGVzdC9yZWdyZXNzL2V4cGVjdGVkL3VuaW9uLm91dAorKysgYi9zcmMvdGVzdC9yZWdyZXNzL2V4 cGVjdGVkL3VuaW9uLm91dApAQCAtNTUxLDggKzU1MSw4IEBAIHNlbGVjdCB4IGZyb20gKHZhbHVl cyAoYXJyYXlbMSwgMl0pLCAoYXJyYXlbMSwgM10pKSBfKHgpIHVuaW9uIHNlbGVjdCB4IGZyb20g KHZhCiAgICB4ICAgCiAtLS0tLS0tCiAgezEsNH0KLSB7MSwyfQogIHsxLDN9CisgezEsMn0KICgz IHJvd3MpCiAKIGV4cGxhaW4gKGNvc3RzIG9mZikKLS0gCjIuNTEuMAoK --0000000000008abd19064bf9add8--