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.94.2) (envelope-from ) id 1ulTOm-001AZ6-DI for pgsql-hackers@arkaria.postgresql.org; Mon, 11 Aug 2025 14:21:16 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1ulTOk-001KmK-Vq for pgsql-hackers@arkaria.postgresql.org; Mon, 11 Aug 2025 14:21:15 +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.94.2) (envelope-from ) id 1ulTOk-001Klk-Fz for pgsql-hackers@lists.postgresql.org; Mon, 11 Aug 2025 14:21:14 +0000 Received: from mail-lf1-x133.google.com ([2a00:1450:4864:20::133]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1ulTOe-000206-1y for pgsql-hackers@postgresql.org; Mon, 11 Aug 2025 14:21:13 +0000 Received: by mail-lf1-x133.google.com with SMTP id 2adb3069b0e04-55b85d01b79so4600857e87.3 for ; Mon, 11 Aug 2025 07:21:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1754922066; x=1755526866; darn=postgresql.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:to:subject:user-agent:mime-version:date:message-id:from :to:cc:subject:date:message-id:reply-to; bh=DcJweTDEaAWD7Nc/HL7fqeOrZvrRMgtKVmApWSeywMU=; b=X3CT3K0si2RkDdXMHiOnhDVuXWOxKUf/wOAm5xMFO/Dk1lMLDzSdZ8UL52FM9vMo6J xFGJTIw6hyqJXhSkzVAncPuiv3rlVesJgBwf0e2nzH2R0DEMKenPrX5kiH8SbufLNpTi yMRB3Y2NwPT2PwomLC4Z0GVtF7zDHKNtjjCiOlYmInfIEBxlww5iWoCB0tJOQ8BO9JFy m/3Yi44lhxKkll7bdKsziUT3l9xgr/tPZT7Ga1DtXr+l6HWKexBvBr9PgeSeo7N9OrYj MeWDrf55SbrwmU1NucyYCkmn4TaquR1jzRG2lgqvVyrYWz0rlxFT6viET2ya1ct6Sq+X 7OsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754922066; x=1755526866; h=content-transfer-encoding:in-reply-to:from:content-language :references:to:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=DcJweTDEaAWD7Nc/HL7fqeOrZvrRMgtKVmApWSeywMU=; b=clPKMk4XL3JZbSIkZZP5f9KQ3bPph+a6D1tzq40GKLM5RIZ1byRddsLzGRqauh7b55 ig1LR0oBjJJjkXRg2ovpHuAqO6Y3FTKzo3fRAc+Zke4pAJbjK0bwE9/gtAEpFE8TV0/1 TqODxpQpEIM8gh2o16uOfbwbgZfesaDYS7KydnuRZyCVbZx4qnsxgdhos/hdMZIP3OLz 1wN61Z3nXzcnOJ87oAmBG1D4Y3I1QjpiIi9639Q9HZ785uhs0evvoqeI+lhdO8UDwSvH cXDxDVYsvXp6heTNwwxHeELHZoHYlS+CIrz1umE+T4E1Oku29NrS3fv1P7ZnNDxwEXdT 7JBg== X-Forwarded-Encrypted: i=1; AJvYcCV1rejn5XUG7V0l9FkM67DuJxl7ibADzQJUvDd8tpfyXanU8aRY0HHxmj4avv/Cl64/YjswApp+mm0SV6RI@postgresql.org X-Gm-Message-State: AOJu0YyCeSTMhz80cCGY1ZdRWl/b+rNgD209FhO9jj0frw6RQwhG+6Ww 9Cja1eDfdEEMeA4rNbUtVXjWPdRualq+vCiILQYxp0yiA/VJKA9aoyjK25Tq10TP X-Gm-Gg: ASbGncvWLk9nICswEJoxnpPAb/REydebipp/+hbZx0D7zEzo40+o0T4cYguxYTYCVaC VDwqNy+9KmocXAL8Je4HRZFHAyljuSkn9CqX/DtuMacrVq4T1mcWHr17JZbt/qoHhxtOb7bUTve pGIFzNxP3L4UBr+aVxk+ydH4pIKHeYbX1F9RYu2eVHy4FTnoYU5RaDjgysMoZquG/m4pdg6ZNlO uHNgFIpJiikCm8deIx8mI7Lvnng7iiz0vrDUVA9gqSR7GoQioaQ/HHxokvAce4YYx3Pvtspa27w Jyln9UqEDGkZNAlGX29jPAx+aB/JLsaEyzQSfRr0v0OXc1i0BfgHljLlYkpKtaOOYpdibpjg134 vnzqK/gGf3Qmo+Fce7ZRMbnXlyqKlNn6Lwe6Ul5ESs3NU1gP5vrW0Fyta9usOGOdtRImoPLVaTm aulrWQLZegaPThzP2XieU= X-Google-Smtp-Source: AGHT+IEWtAjhvVjz5+5z2yLy7hA3qfSqkEJdagz3fA1rTwij1PtnKp24/xXSDIUqBYKmd8UF1H/cfA== X-Received: by 2002:a05:6512:2396:b0:55b:8d6a:be86 with SMTP id 2adb3069b0e04-55cd7498715mr22665e87.0.1754922065162; Mon, 11 Aug 2025 07:21:05 -0700 (PDT) Received: from [192.168.50.127] (broadband-5-228-116-129.ip.moscow.rt.ru. [5.228.116.129]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-55cca00f74esm1153882e87.65.2025.08.11.07.21.04 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 11 Aug 2025 07:21:04 -0700 (PDT) Message-ID: Date: Mon, 11 Aug 2025 17:21:04 +0300 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Improve the performance of Unicode Normalization Forms. To: Jeff Davis , PostgreSQL Hackers References: <844d3dd7-2955-4794-95d1-7f4c13cb89fc@gmail.com> <4211ffd7fe154c4af693b98d78f4a3689ce8cc30.camel@j-davis.com> <16f87504-f174-450e-93cc-2db1074522bb@gmail.com> <96c54fc3dde2ebaccafbd1ffa29b8be1005c8b8c.camel@j-davis.com> <677cde50-6d64-474b-9ba8-bab380a111b3@gmail.com> <599663a8d5948243bd87bf55a4f76bbb4a51a6e8.camel@j-davis.com> <85f2a36f-f70a-4667-be48-49b652457295@gmail.com> <088432f3-a3a9-4c40-8295-6c687c25d651@gmail.com> Content-Language: ru From: Alexander Borisov In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk 09.08.2025 02:17, Jeff Davis пишет: > On Tue, 2025-07-08 at 22:42 +0300, Alexander Borisov wrote: >> Version 3 patches. In version 2 "make -s headerscheck" did not work. > > I ran my own performance tests. What I did was get some test data from > ICU v76.1 by doing: > [..] > Results with perfect hashing (100 iterations): > > Normalization from NFC to NFD with PG: 010.009 > Normalization from NFC to NFD with ICU: 001.580 > Normalization from NFC to NFKD with PG: 009.376 > Normalization from NFC to NFKD with ICU: 000.857 > Normalization from NFD to NFC with PG: 016.026 > Normalization from NFD to NFC with ICU: 001.205 > Normalization from NFD to NFKC with PG: 015.903 > Normalization from NFD to NFKC with ICU: 000.654 > > Results with your code (100 iterations): > > Normalization from NFC to NFD with PG: 004.626 > Normalization from NFC to NFD with ICU: 001.577 > Normalization from NFC to NFKD with PG: 004.024 > Normalization from NFC to NFKD with ICU: 000.861 > Normalization from NFD to NFC with PG: 006.846 > Normalization from NFD to NFC with ICU: 001.209 > Normalization from NFD to NFKC with PG: 006.655 > Normalization from NFD to NFKC with ICU: 000.651 > > Your patches are a major improvement, but I'm trying to figure out why > ICU still wins by so much. Thoughts? I didn't investigate much myself > yet, so it's quite possible there's a bug in my test or something. I had some experimented a bit, and took a look at the ICU code. 1. The performance test is not entirely accurate. The thing is that in ICU (unorm_normalize()), we pass the output buffer and its size. That is, ICU does not calculate how much data we will have at the output; we pass it our buffer. ICU simply checks whether the data fits into the buffer or not. In our case, PG (unicode_normalize()) only accepts the input buffer and first calculates the size of the output buffer. This means we are doing double the work, as we have already gone through the input data at least once too many times. Here, it would be more honest to call the function for calculating the buffer in ICU, and only then call data normalization. 2. In PG, unnecessary table lookups (get_code_entry()) that can clearly be avoided. 3. In PG, the algorithm is not optimized. We could eliminate the decompose_code() function, which is called for each code point. In this function, we can remove recursion and prepare the data in advance. That is, we can perform data expansion in the Perl script. If we do this, we will have code that is in place and without recursion. And then there are all sorts of other minor details. Of course, there are other approaches. I did this comparison (your test, Jeff): 1. Without patch. Normalization from NFC to NFD with PG: 009.121 Normalization from NFC to NFD with ICU: 000.954 Normalization from NFC to NFKD with PG: 009.048 Normalization from NFC to NFKD with ICU: 000.965 Normalization from NFD to NFC with PG: 014.525 Normalization from NFD to NFC with ICU: 000.623 Normalization from NFD to NFKC with PG: 014.380 Normalization from NFD to NFKC with ICU: 000.666 2. With patch. Normalization from NFC to NFD with PG: 005.743 Normalization from NFC to NFD with ICU: 001.005 Normalization from NFC to NFKD with PG: 005.902 Normalization from NFC to NFKD with ICU: 000.963 Normalization from NFD to NFC with PG: 007.837 Normalization from NFD to NFC with ICU: 000.640 Normalization from NFD to NFKC with PG: 008.036 Normalization from NFD to NFKC with ICU: 000.667 3. With a patch, but! With direct access to tables, i.e., I created one large table (index table, unit16_t) where there is no search, direct access to data. Normalization from NFC to NFD with PG: 002.792 Normalization from NFC to NFD with ICU: 000.953 Normalization from NFC to NFKD with PG: 002.865 Normalization from NFC to NFKD with ICU: 000.958 Normalization from NFD to NFC with PG: 004.361 Normalization from NFD to NFC with ICU: 000.651 Normalization from NFD to NFKC with PG: 004.474 Normalization from NFD to NFKC with ICU: 000.668 It is evident that direct access provides x2 from the patch, but adds +1.5MB to the object file size. This is just to check the time difference in access. As a result, I would not look into ICU at the moment, especially since we have a different approach. I am currently working on optimizing unicode_normalize(). I am trying to come up with an improved version of the algorithm in C by the next commitfest (which will be in September). P.S.: In general, I strive to surpass ICU in terms of speed. I think we're making good progress. Let's see what happens. -- Regards, Alexander Borisov