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 1vshl5-00FSEz-0R for pgsql-hackers@arkaria.postgresql.org; Wed, 18 Feb 2026 13:38:27 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vshl2-00G3SQ-2x for pgsql-hackers@arkaria.postgresql.org; Wed, 18 Feb 2026 13:38:25 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vshl2-00G3SI-1v for pgsql-hackers@lists.postgresql.org; Wed, 18 Feb 2026 13:38:24 +0000 Received: from mail-dy1-x132e.google.com ([2607:f8b0:4864:20::132e]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vshkz-00000001Mn0-3RDg for pgsql-hackers@postgresql.org; Wed, 18 Feb 2026 13:38:23 +0000 Received: by mail-dy1-x132e.google.com with SMTP id 5a478bee46e88-2bd3b0bc201so2667628eec.1 for ; Wed, 18 Feb 2026 05:38:21 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1771421900; cv=none; d=google.com; s=arc-20240605; b=Dryr/Zn1+bkW/neKDi/Wq9VRnRthAwofexVv7fdJCd9i6xTyNNkNQb39+22fROwfgH TMglNtnrl51CUWAdq/G4yUoj88UMPpSMJRUrXUud4rKGnFz1LjtG5DOyJqSX64NfizWc EfGEZncmTNxVQXhowjxJoRV2BUXZTxVrWtRm1MBzK7+vPKifTo6z8XaIDKFkyW6a0wsN iTtGOO+pJjdbp2nNL0dOr4PrOvcIohwaGuvgtn4kX9EJ5MzGLHl4iz1ywPpOZfaLHBrl 49hevUTZUuxo+07gELJQ7SoYPpdUzNeL270qccke5Lap45O1DgD6Z8YS6fk3EgSAYSuy Xndg== 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=1F74IGVwlJqCHt4vOFrBq4NqpnBrEkqWgj3z7M22SfI=; fh=6qn8bj5TwIXrBdD+3Zowq472sgBT1cjDS5iaIwy762o=; b=HdMq7nBQzXhJ46h+Q/3GMv/67WwA4tdruccXgFnIUWaKwlwoaTa7uuss1HQb1u6wFp D4cIDyIBFuvcswA6q1NKNitQysNntsLQU8ofiL4JWDLblxYWxt8rVPRz+vdRpQn7GNQR rTu4DyEUSJTYX4HJtXD90T7gghRE+CYNZnH4ulQIT1wmbCHtJL2Y0GQirNnv3wGG7HYH JbWTmMw9jqyQ7NKEMwahvQPoKJdFbwUx9LebjKSL9dIn+HOE1HvPBcKiiwc0alm5+Pt0 meCR5lfhZ1ls1u5v/BSJU0NppQ+v0HbANdJA3rJxT0VdLrlqfBYS02A3Zi8OEUoUs3/e bGxw==; darn=postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1771421900; x=1772026700; darn=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=1F74IGVwlJqCHt4vOFrBq4NqpnBrEkqWgj3z7M22SfI=; b=BuopRUP6C1mrtlqRjlF2s+IgwbpwVmlVkuVfK0LWW4r/76h+gNFwL/mPmfg1EtmH35 v1MnwyDacXbGHBQr0hdi8/MIAXPCJgROsKYScE5I5PYFNKjOxpcDlT/kr53Zb3BnM5WA 3/oRlVVqTSKaJI4kELjiuA/3stVd/bcGBM+kWEMp1BtlOIQDBXSTGGUK+Hkrlt5SxYO/ n8ca0CawGLiKbxzZD8LcZ/kcmYkYulGq1dNwteEht67wMBM87grnlM1qVGE0URHUpwLq BMGuYqxeO6q6r0VgthLKRUpgS3bURS6MUdzxPsnwe1UmJ2gqoh0CSKf+5Yd71pEOpryy FY/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771421900; x=1772026700; 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=1F74IGVwlJqCHt4vOFrBq4NqpnBrEkqWgj3z7M22SfI=; b=IXTL8kWjIToSGEMpH7aCEwvw44ZTydIaprl4SkJ0kZoXLDDALMMyD0xHQNlzgu3hZg poSeVU83nP543eF7jPmaUmygCg1r/Znq6lFP5j7BqbBQgWfzVPod8Ux8QH1if9dyus2C Xp38QrU1yGjQty3GdFuwnIbURURU4eTWKSh+GhBdocnvyR/FlShJsATcxIW8ZgICrX0/ tzL4yticZlQghnnOSERzx2HdnYEAG1ZCMi587atb8g/pxN2Qu2XXUK1vN4YjZx00BFdt FkowisYkjb59stGk6SSDmEZeZKRlZ8eXeIQqdebFxXsM/+71tMFpeiN4wxvqN265G1U5 7OXw== X-Forwarded-Encrypted: i=1; AJvYcCW/LrXp51RvNOTDfi+uIcso2WlJ/Om+1HyjsBMuBI4k5EhoLfSROC2sGBJpmXz+22vKN5oBR3ys6y8+Y+Uo@postgresql.org X-Gm-Message-State: AOJu0YwOAvxEO9iHcGN7cSga1oGVKFkYka1FV0mb34S/1ZmaOvwuzIfq T+xBuxWoVoH/y+rrJUMhF8/U7Pl9YmnLo+K7dJX+jIiiAvdbd7v1YlfjSB4bwlX15Iv/rjDwqz8 cTPHUfxlA4T8E6h89c/4SYdQd/YNIzio= X-Gm-Gg: AZuq6aJIcCbXEn4ZU0JTNeyhCnfs1EKG7CpRWSqq4/NVmbJvmKWCdU4AoC2eJ9SKWjx HyDsCLEetXhpzV10ZQXLzth/8Xcew5oMpqsD5Y1/6GvGdfWuR4TrSU7Jv+XPfZF5MRT+mIxxSxz gVgGkplNESgjCFDEspXgsU22bUbp0Ht9YAFIZL2+DbO7YSq83dMQokphzq1igKVj2mQDYF4cjjH 2j8lzXO9GL0zvXveGBxLIQtg3fQdrgnsOkUoeXLZ6ex0n3DA9QKsmWm8bTpu8CgBQAtL96tSEFb M2GCwwzgzaT9gTo0fg== X-Received: by 2002:a05:7301:38a8:b0:2ba:94c1:6c8c with SMTP id 5a478bee46e88-2bd502bcfb7mr1073258eec.39.1771421899532; Wed, 18 Feb 2026 05:38:19 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Nazir Bilal Yavuz Date: Wed, 18 Feb 2026 16:38:07 +0300 X-Gm-Features: AaiRm52UpoZ67Vq75MXrrKZCkVdS7PfY9V2tuxam81tzYahuZFlBWk23gRfrhdc Message-ID: Subject: Re: Speed up COPY FROM text/CSV parsing using SIMD To: Nathan Bossart Cc: KAZAR Ayoub , Neil Conway , Manni Wood , Andrew Dunstan , Shinya Kato , PostgreSQL-development Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi, On Sat, 14 Feb 2026 at 02:09, Nathan Bossart wrote: > > On Fri, Feb 13, 2026 at 02:45:30PM +0300, Nazir Bilal Yavuz wrote: > > Also, if I change this code to: > > > > if (cstate->simd_enabled) > > { > > if (is_csv) > > result = CopyReadLineText(cstate, true, true); > > else > > result = CopyReadLineText(cstate, false, true); > > } > > else > > { > > if (is_csv) > > result = CopyReadLineText(cstate, true, false); > > else > > result = CopyReadLineText(cstate, false, false); > > } > > > > then I see ~%5 performance improvement in scalar path compared to master. > > Hm. What difference do you see if you just do > > if (is_csv) > result = CopyReadLineText(cstate, true); > else > result = CopyReadLineText(cstate, false); > > both with and without the SIMD stuff? IIUC this is allowing the compiler > to remove several branches in CopyReadLineText(), which might be a nice > improvement on its own. That being said, I'm less convinced that adding a > simd_enabled parameter to CopyReadLineText() helps, because 1) it's > involved in fewer branches and 2) we change it within the function, so the > compiler can't remove the branches, anyway. But perhaps I'm missing > something. I did couple of benchmarks, some info about them: - Benchmarks show percentage comparisons of timings against the master branch. Positive values mean a regression, while negative values mean an improvement. - There are a total 200000 lines in each input and each line is 8192 bytes. - For the columns, none means there is no special character. The other numbers represent the ratio of normal characters to special characters. For example, 0 means all the data is special characters, 4 means %25 of the data is special characters, 16 means 1/16 of the data is special characters and such. -------------------- This is the benchmark without the SIMD stuff: - only_inline: Only change is CopyReadLineText() being inlined. - is_csv_verbose-wo-inline: is_csv is sent as a constant boolean like you suggested but CopyReadLineText() isn't inlined. - is_csv_verbose-w-inline: is_csv is sent as a constant boolean and CopyReadLineText() is inlined. +-------------------------------+-------+------+------+-------+-------+------+ | TEXT | none | 0 | 4 | 8 | 16 | 32 | +-------------------------------+-------+------+------+-------+-------+------+ | only_inline | 0 | +1.6 | 0 | 0 | -1 | 0 | +-------------------------------+-------+------+------+-------+-------+------+ | is_csv_verbose-wo-inline | 0 | 0 | 0 | 0 | 0 | 0 | +-------------------------------+-------+------+------+-------+-------+------+ | is_csv_verbose-w-inline | -3.5 | 0 | -7.7 | -2.3 | -4.1 | -3.4 | +-------------------------------+-------+------+------+-------+-------+------+ | | | | | | | | +-------------------------------+-------+------+------+-------+-------+------+ | | | | | | | | +-------------------------------+-------+------+------+-------+-------+------+ | CSV | none | 0 | 4 | 8 | 16 | 32 | +-------------------------------+-------+------+------+-------+-------+------+ | only_inline | -1.1 | 0 | 0 | 0 | 0 | -1 | +-------------------------------+-------+------+------+-------+-------+------+ | is_csv_verbose-wo-inline | 0 | 0 | 0 | 0 | -0.3 | 0 | +-------------------------------+-------+------+------+-------+-------+------+ | is_csv_verbose-w-inline | -4 | -2.3 | -1.2 | -1.8 | -2.8 | -2.7 | +-------------------------------+-------+------+------+-------+-------+------+ By looking the benchmark results, if (is_csv) result = CopyReadLineText(cstate, true); else result = CopyReadLineText(cstate, false); with inline CopyReadLineText() function helps the performance even without SIMD. ---------------------------------------- This is the same benchmark with SIMD stuff: only_inline: Only change is CopyReadLineText() being inlined, there is no simd_enabled argument in the CopyReadLineText(). is_csv_verbose-w-inline: is_csv is sent as a constant boolean and CopyReadLineText() is inlined. There is no simd_enabled argument in the CopyReadLineText(). simd_enabled_verbose-w-inline: simd_enabled is sent as a constant boolean and CopyReadLineText() is inlined. both_verbose_w_inline: both is_csv and simd_enabled are sent as a constant boolean and CopyReadLineText() is inlined. +-------------------------------+-------+------+------+-------+-------+------+ | TEXT | none | 0 | 4 | 8 | 16 | 32 | +-------------------------------+-------+------+------+-------+-------+------+ | only_inline | -11 | +9.7 | +9.1 | +11.4 | +14.8 | +8 | +-------------------------------+-------+------+------+-------+-------+------+ | is_csv_verbose-wo-inline | -11.9 | +4.5 | +2.4 | +3.5 | +2.2 | +1.8 | +-------------------------------+-------+------+------+-------+-------+------+ | is_csv_verbose-w-inline | -12.6 | 0 | -2.4 | +2.8 | +1.6 | 0 | +-------------------------------+-------+------+------+-------+-------+------+ | both_verbose_w_inline | -12.1 | 0 | -5 | 0 | +2.5 | -1.8 | +-------------------------------+-------+------+------+-------+-------+------+ | | | | | | | | +-------------------------------+-------+------+------+-------+-------+------+ | CSV | none | 0 | 4 | 8 | 16 | 32 | +-------------------------------+-------+------+------+-------+-------+------+ | only_inline | -22.6 | +4.2 | +2.1 | +2.6 | 0 | +2.2 | +-------------------------------+-------+------+------+-------+-------+------+ | is_csv_verbose-w-inline | -22.5 | -2.1 | -3.4 | -3.9 | -6.4 | -3.4 | +-------------------------------+-------+------+------+-------+-------+------+ | simd_enabled_verbose-w-inline | -23 | 0 | -1.9 | -2.2 | -4.8 | -1.6 | +-------------------------------+-------+------+------+-------+-------+------+ | both_verbose_w_inline | -23.3 | -2.9 | -5 | -4.5 | -7.1 | -4.3 | +-------------------------------+-------+------+------+-------+-------+------+ By looking at these results having both is_csv and simd_enabled as an argument and sending them as constant boolean arguments help most. > > Some other random thoughts: I am sending the benchmark results for now. I haven't tested other suggestions yet. I will follow up with another email once I have tested them. -- Regards, Nazir Bilal Yavuz Microsoft