Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pY852-0003Pu-GQ for pgsql-hackers@arkaria.postgresql.org; Fri, 03 Mar 2023 16:16:24 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1pY851-0006ob-0z for pgsql-hackers@arkaria.postgresql.org; Fri, 03 Mar 2023 16:16:23 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pY850-0006oR-LY for pgsql-hackers@lists.postgresql.org; Fri, 03 Mar 2023 16:16:22 +0000 Received: from mail-pg1-x529.google.com ([2607:f8b0:4864:20::529]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1pY84w-00058B-Jn for pgsql-hackers@postgresql.org; Fri, 03 Mar 2023 16:16:21 +0000 Received: by mail-pg1-x529.google.com with SMTP id 16so1780904pge.11 for ; Fri, 03 Mar 2023 08:16:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=/6q3BAd/J2563dReWZEcOawhWxAT/672N05Mx5BacyA=; b=KhEGnTTkNvRVmULcAATMogAYbeTk8XtLVwRz+5FW82/Wyi8t8eBWBlyQ0EWp4fjp3F k8uSMiFPv/jpH8HmLJKmaAoXGy0vBOaTFb/QSQifdugNJtpEhXU1d83gGSh3v1KoCo+2 YzOssyE6vDKeMg3uw1KeDTyUhuhQ11cUBE5yOyBK5AyLnDyhwWlQriLEq/8fE85UI3SH YB5N/i9YW4XXcbf2spm40Yovj/zRK+sLnJIZqCNSHvcAbUqTytj2UereR0j7bJuLrhnq OvsGFkWZmBTJ4nt9b0fkm/Xy9frqgFux0yPyCThgFu2paS8D2PJrhl8N1M6Db2TCmAFF cKWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=/6q3BAd/J2563dReWZEcOawhWxAT/672N05Mx5BacyA=; b=dFV2DI0+MSv/0KzI87bbC2gksJv5Z9kWd5JB3JGqETIQ0V+UCNELW7lCCFBOB51v1m awxNmuYbSn/xUajYuVpHPUg1fxBjS3xXA97iYGFubULH1YvR/LHd4Sg8pUK7NAIccB+W wjYtg0u3Nqvup70sQk9OR+/FOm5ALyagfRnV1qlangzlnpVvI8SKma0plSDZsJif8YOE 7a007CrntFDJm30XS2HES3HlWtB5eYGU5AYGXv2rAseQaVBlk3OFa7tcanuFRC6GUU6t i7M7OcHkscuzu78MGuKISVgpX4bZBrBUiR2H3OGdWV0hSoJosqw5I71m3lPlpCyHsQIp rOwA== X-Gm-Message-State: AO0yUKUoNfPCXtew+rf/3ME1bQeOC8Y5x8A2Mr9ezRkrIHJqm222DZhs +PSEZg89vaWntdNdbnfwSX0aHMEWCQkZiPacicg= X-Google-Smtp-Source: AK7set/WLarInyDMHRNANmKYPzPhWioeabDLydfET7LlXEghvBijgJrL0NlR/RHNWxCNaRmsjklIU9kTHp1svJc9Pm4= X-Received: by 2002:a63:1a1f:0:b0:4f2:8281:8afb with SMTP id a31-20020a631a1f000000b004f282818afbmr665397pga.4.1677860176179; Fri, 03 Mar 2023 08:16:16 -0800 (PST) MIME-Version: 1.0 References: <4FCF6DCF-231C-456A-99D0-8A7FE701AD17@yesql.se> In-Reply-To: From: Jeroen Vermeulen Date: Fri, 3 Mar 2023 17:16:05 +0100 Message-ID: Subject: Re: libpq: PQgetCopyData() and allocation overhead To: Jelte Fennema Cc: daniel@yesql.se, Bharath Rupireddy , PostgreSQL Hackers Content-Type: multipart/alternative; boundary="000000000000c8b50805f60143dd" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000c8b50805f60143dd Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Thank you. I meant to try PQExpBuffer =E2=80=94 as you say, it fits much better with e= xisting libpq style. But then I hit on the callback idea which was even more efficient, by a fair margin. It was also considerably simpler both inside libpq and in the client code, eliminating all sorts of awkward questions about who deallocates the buffer in which situations. So I ditched the "dynamic buffer" concept and went with the callback. One other possible alternative suggests itself: instead of taking a callback and a context pointer, the function could probably just return a struct: status/size, and buffer. Then the caller would have to figure out whether there's a line in the buffer, and if so, process it. It seems like more work for the client code, but it may make the compiler's optimisation work easier. Jeroen On Fri, 3 Mar 2023 at 16:52, Jelte Fennema wrote: > On Thu, 2 Mar 2023 at 20:45, Jeroen Vermeulen wrote: > > I'm attaching a diff now. This is not a patch, it's just a discussion > piece. > > Did you try with PQExpBuffer? I still think that probably fits better > in the API design of libpq. Obviously if it's significantly slower > than the callback approach in this patch then it's worth considering > using the callback approach. Overall it definitely seems reasonable to > me to have an API that doesn't do an allocation per row. > --000000000000c8b50805f60143dd Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Thank you.

I meant to try PQ= ExpBuffer =E2=80=94 as you say, it fits much better with existing libpq sty= le.=C2=A0 But then I hit on the callback idea which was even more efficient= , by a fair margin.=C2=A0 It was also considerably simpler both inside libp= q and in the client code, eliminating all sorts of awkward questions about = who deallocates the buffer in which situations.=C2=A0 So I ditched the &qu= ot;dynamic buffer" concept and went with the callback.
<= br>
One other possible alternative suggests itself: instead of ta= king a callback and a context pointer, the function could probably just ret= urn a struct: status/size, and buffer.=C2=A0 Then the caller would have to = figure out whether there's a line in the buffer, and if so, process it.= =C2=A0 It seems like more work for the client code, but it may make the com= piler's optimisation work easier.


Jeroen

On Fri, 3 Mar 2023 at 16:52, Jelte Fennema <postgres@jeltef.nl> wrote:
On Thu, 2 Mar 2023 at 20= :45, Jeroen Vermeulen <jtvjtv@gmail.com> wrote:
> I'm attaching a diff now.=C2=A0 This is not a patch, it's just= a discussion piece.

Did you try with PQExpBuffer? I still think that probably fits better
in the API design of libpq. Obviously if it's significantly slower
than the callback approach in this patch then it's worth considering using the callback approach. Overall it definitely seems reasonable to
me to have an API that doesn't do an allocation per row.
--000000000000c8b50805f60143dd--