You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@trafficserver.apache.org by Alan Carroll <am...@network-geographics.com> on 2023/12/07 01:00:28 UTC
[TSAPI] TSTxnAlloc
Proposed Transaction based memory allocation API
TSTxnAlloc
**********
Traffic Server Transaction based memory allocation.
Synopsis
========
.. code-block:: cpp
#include <ts/ts.h>
.. function:: swoc::MemSpan<void> TSTxnAlloc(TSHttpTxn txn, size_t bytes)
.. function:: swoc::MemSpan<void> TSTxnAllocAligned(TSHttpTxn txn, size_t bytes, size_t align)
.. function:: template < typename T > T * TSTxnAllocInstance();
.. function:: template < typename T > swoc::MemSpan<T> TSTxnAllocArray(size_t count);
.. function:: swoc::TextView TSTxnLocalizeString(TSHttpTxn txn, swoc::TextView s)
.. function:: swoc::TextView TSTxnLocalizeCString(TSHttpTxn txn, char const * s)
.. function:: template < typename F > void TSTxnFinalize(TSHttpTxn txn, F && f)
Description
===========
These functions are used to allocate memory that has the same lifetime as a transaction. This has two differences from
normal allocation which are frequently advantageous for plugins.
* Allocation is much faster than :code:`malloc` or equivalent.
* The memory is released at the end of the transaction automatically.
The only function in this group that does not allocate is :func:`TSTxnFinalize`. Instead this provides a functor
which is invoked just before the transaction local memory is released.
:func:`TSTxnAlloc` allocates a block of memory of size :arg:`bytes`.
:func:`TSTxnAllocAligned` allocates a block of memory of size :arg:`bytes` that is aligned at a multiple of :arg:`align`,
which must be a power of 2.
:func:`TSTxnAllocInstance` allocates an instance of a type :code:`T` with the required alignment for :arg:`T`,
calls the default constructor for :code:`T`, and the returns the pointer.
:func:`TSTxnAllocArray` allocates a block of memory of size and alignment to hold :arg:`count` instances of :code:`T`. These
are not initialized / constructed.
:func:`TSTxnLocalizeString` copies the string :arg:`s` to transaction local memory and returns a view of the copied string.
:func:`TSTxnLocalizeCString` copies a C string (nul character terminated) :arg:`s` to transaction local memory and returns a view of the copied string.
:func:`TSTxnFinalize` creates a finalizer for the transaction which are described in :ref:`finalizers`.
Notes
=====
In general this memory should avoid referencing memory outside of transaction local memory. Strings are the archetype
as a string is complete in itself and requires no cleanup beyond deallocation. For variable sized structures it is
possible to use :code:`swoc::IntrusiveDList` to create lists which reside entirely in transaction local memory and
therefore require no addtional cleanup.
.. _finalizers::
Finalizers
----------
If cleanup is unavoidable then a :em:`finalizer` can be used. This is a functor that is invoked just before cleaning
up transaction local memory which is intended to perform addtional cleanup. This imposes several restrictions
* The finalizer itself must not require any cleanup beyond deallocation. One aspect is the functor instance must
not contain any non-transaction local allocated memory.
* The finalizer must only do allocation related cleanup. It must not call any TS plugion API calls. The transaction
object is likely to be in an unusable state when the finalizer is invoked.
For an example finalizer, suppose the allocation is used to hold a :code:`std::vector<size_t>`. Simply releasing the
memory will leak the vector elements, so the vector must be destructed. This can be handled by a finalizer that looks
like
.. code-block:: cpp
auto * vecp = TSTxnAllocInstance<std::vector<size_t>>(txn);
TSTxnFinalizer(txn, [=]() -> void { delete vecp; });
The pointer to the allocated vector is captured by the lambda and when the transaction local memory is released the
vector contents are also released. Be very very careful or (better) avoid entirely capture by reference, as the target of the
reference is likely to be long out of scope when the finalizer is invoked.
See also
========
:manpage:`TSAPI(3ts)`
+
RE: [TSAPI] TSTxnAlloc
Posted by Alan Carroll <am...@network-geographics.com>.
See my previous email - we could say it must be a POD for TxnAlloc and if it's not, use Cleanup.
-----Original Message-----
From: Chris McFarlen <ch...@mcfarlen.us>
Sent: Friday, December 8, 2023 12:03 PM
To: dev@trafficserver.apache.org
Subject: Re: [TSAPI] TSTxnAlloc
Should the template function versions ensure is_trivially_destructible<T>? This should reject non POD allocations.
Re: [TSAPI] TSTxnAlloc
Posted by Chris McFarlen <ch...@mcfarlen.us>.
Should the template function versions ensure is_trivially_destructible<T>? This should reject non POD allocations.
Sent with Proton Mail secure email.
On Wednesday, December 6th, 2023 at 7:00 PM, Alan Carroll <am...@network-geographics.com> wrote:
> Proposed Transaction based memory allocation API
>
> TSTxnAlloc
> **********
>
> Traffic Server Transaction based memory allocation.
>
> Synopsis
> ========
>
> .. code-block:: cpp
>
> #include <ts/ts.h>
>
>
> .. function:: swoc::MemSpan<void> TSTxnAlloc(TSHttpTxn txn, size_t bytes)
>
> .. function:: swoc::MemSpan<void> TSTxnAllocAligned(TSHttpTxn txn, size_t bytes, size_t align)
>
> .. function:: template < typename T > T * TSTxnAllocInstance();
>
> .. function:: template < typename T > swoc::MemSpan<T> TSTxnAllocArray(size_t count);
>
> .. function:: swoc::TextView TSTxnLocalizeString(TSHttpTxn txn, swoc::TextView s)
> .. function:: swoc::TextView TSTxnLocalizeCString(TSHttpTxn txn, char const * s)
> .. function:: template < typename F > void TSTxnFinalize(TSHttpTxn txn, F && f)
>
>
> Description
> ===========
>
> These functions are used to allocate memory that has the same lifetime as a transaction. This has two differences from
> normal allocation which are frequently advantageous for plugins.
>
> * Allocation is much faster than :code:`malloc` or equivalent.
> * The memory is released at the end of the transaction automatically.
>
> The only function in this group that does not allocate is :func:`TSTxnFinalize`. Instead this provides a functor
> which is invoked just before the transaction local memory is released.
>
> :func:`TSTxnAlloc` allocates a block of memory of size :arg:`bytes`.
>
> :func:`TSTxnAllocAligned` allocates a block of memory of size :arg:`bytes` that is aligned at a multiple of :arg:`align`,
> which must be a power of 2.
>
> :func:`TSTxnAllocInstance` allocates an instance of a type :code:`T` with the required alignment for :arg:`T`,
> calls the default constructor for :code:`T`, and the returns the pointer.
>
> :func:`TSTxnAllocArray` allocates a block of memory of size and alignment to hold :arg:`count` instances of :code:`T`. These
> are not initialized / constructed.
>
> :func:`TSTxnLocalizeString` copies the string :arg:`s` to transaction local memory and returns a view of the copied string.
>
> :func:`TSTxnLocalizeCString` copies a C string (nul character terminated) :arg:`s` to transaction local memory and returns a view of the copied string.
>
> :func:`TSTxnFinalize` creates a finalizer for the transaction which are described in :ref:`finalizers`.
>
> Notes
> =====
>
> In general this memory should avoid referencing memory outside of transaction local memory. Strings are the archetype
> as a string is complete in itself and requires no cleanup beyond deallocation. For variable sized structures it is
> possible to use :code:`swoc::IntrusiveDList` to create lists which reside entirely in transaction local memory and
> therefore require no addtional cleanup.
>
> .. _finalizers::
>
> Finalizers
> ----------
>
> If cleanup is unavoidable then a :em:`finalizer` can be used. This is a functor that is invoked just before cleaning
> up transaction local memory which is intended to perform addtional cleanup. This imposes several restrictions
>
> * The finalizer itself must not require any cleanup beyond deallocation. One aspect is the functor instance must
> not contain any non-transaction local allocated memory.
> * The finalizer must only do allocation related cleanup. It must not call any TS plugion API calls. The transaction
> object is likely to be in an unusable state when the finalizer is invoked.
>
> For an example finalizer, suppose the allocation is used to hold a :code:`std::vector<size_t>`. Simply releasing the
>
> memory will leak the vector elements, so the vector must be destructed. This can be handled by a finalizer that looks
> like
>
> .. code-block:: cpp
>
> auto * vecp = TSTxnAllocInstance<std::vector<size_t>>(txn);
>
> TSTxnFinalizer(txn, = -> void { delete vecp; });
>
>
> The pointer to the allocated vector is captured by the lambda and when the transaction local memory is released the
> vector contents are also released. Be very very careful or (better) avoid entirely capture by reference, as the target of the
> reference is likely to be long out of scope when the finalizer is invoked.
>
> See also
> ========
>
> :manpage:`TSAPI(3ts)`
> +
Re: [E] [TSAPI] TSTxnAlloc
Posted by Walt Karas <wk...@yahooinc.com.INVALID>.
On Tue, Dec 12, 2023 at 1:03 PM Alan Carroll <am...@network-geographics.com>
wrote:
> >> If the memory returned by these new functions are not in the Txn arena,
> where are they stored?
>
> In a swoc::MemArena which will replace the Arena in the HTTP state machine.
>
> >> I guess my comments for the TxnAuxDataMgr class template are too sparse:
> >>
> https://urldefense.com/v3/__https://github.com/apache/trafficserver/blob/d13e3a7c3c799c9493670fd791edf53963e00bd8/include/tscpp/api/Cleanup.h*L127__;Iw!!Op6eflyXZCqGR5I!EcptkopTLq_jA58Pq4lCnio8yangZqNiz9gVZy7QoUIVxKwqQYR_V_8VoJQXgJM9Abf3VOjT1XdGJMfg0P_E$
>
> >> It only involves creating a single TSCont instance per plugin at
> startup (in the plugin init function). Is a single TSCont per plugin too
> much?
>
> Arena based memory is also much faster to allocate and de-allocate. This
> is particularly true for strings, contrasting arena memory vs.
> Std::string. I also consider this effectively zero over head because the
> HttpSM needs an arena for its own purposes. With the better API provided
> by swoc::MemArena it becomes useful to also expose it to plugins. Also, in
> addition to the TSCont, that consumes a more precious resource,
> a user transaction argument.
>
> This work is intended for data that does not require cleanup, strings and
> PODs. It might be reasonable to unify these be replacing / implementing
> Finalizers using the aux data manager. From my point of view, finalizers
> are exceptional and rarely used. I would expect most plugins to not use
> them.
> What could be done is rather than having a class for such management,
> provide a utility function that allocates and constructs a type T and also
> arranges (using this mechanism) to do the cleanup on TXN_CLOSE.\
>
I don't see how your answers are related to my questions so I'll let others
consider this.
> -----Original Message-----
> From: Walt Karas <wk...@yahooinc.com.INVALID>
> Sent: Thursday, December 7, 2023 9:27 AM
> To: dev@trafficserver.apache.org
> Subject: Re: [E] [TSAPI] TSTxnAlloc
>
>
>
RE: [E] [TSAPI] TSTxnAlloc
Posted by Alan Carroll <am...@network-geographics.com>.
>> If the memory returned by these new functions are not in the Txn arena, where are they stored?
In a swoc::MemArena which will replace the Arena in the HTTP state machine.
>> I guess my comments for the TxnAuxDataMgr class template are too sparse:
>> https://github.com/apache/trafficserver/blob/d13e3a7c3c799c9493670fd791edf53963e00bd8/include/tscpp/api/Cleanup.h#L127
>> It only involves creating a single TSCont instance per plugin at startup (in the plugin init function). Is a single TSCont per plugin too much?
Arena based memory is also much faster to allocate and de-allocate. This is particularly true for strings, contrasting arena memory vs.
Std::string. I also consider this effectively zero over head because the HttpSM needs an arena for its own purposes. With the better API provided
by swoc::MemArena it becomes useful to also expose it to plugins. Also, in addition to the TSCont, that consumes a more precious resource,
a user transaction argument.
This work is intended for data that does not require cleanup, strings and PODs. It might be reasonable to unify these be replacing / implementing
Finalizers using the aux data manager. From my point of view, finalizers are exceptional and rarely used. I would expect most plugins to not use them.
What could be done is rather than having a class for such management, provide a utility function that allocates and constructs a type T and also
arranges (using this mechanism) to do the cleanup on TXN_CLOSE.
-----Original Message-----
From: Walt Karas <wk...@yahooinc.com.INVALID>
Sent: Thursday, December 7, 2023 9:27 AM
To: dev@trafficserver.apache.org
Subject: Re: [E] [TSAPI] TSTxnAlloc
Re: [E] [TSAPI] TSTxnAlloc
Posted by Walt Karas <wk...@yahooinc.com.INVALID>.
I guess my comments for the TxnAuxDataMgr class template are too sparse:
https://github.com/apache/trafficserver/blob/d13e3a7c3c799c9493670fd791edf53963e00bd8/include/tscpp/api/Cleanup.h#L127
It only involves creating a single TSCont instance per plugin at startup
(in the plugin init function). Is a single TSCont per plugin too much?
If the memory returned by these new functions are not in the Txn arena,
where are they stored?
On Thu, Dec 7, 2023 at 9:56 AM Alan Carroll <am...@network-geographics.com>
wrote:
> "Arena.h" is scheduled for KIWF. This would be implemented using
> swoc::MemArena, which is already available to plugins. I am concerned about
> giving plugins direct access to the MemArena because I planned to use it
> internally in the HttpSM as well. I would be interested to
> hear what others thinks about exposing the MemArena.
>
> Internally the finalizers are implemented as an IntrusiveDList in the
> MemArena, which avoids having to create and cleanup TSInkCont instances.
> Also I want to avoid calling any plugin API (such as TSXXXDestroy) to avoid
> reliance on the HttpSM being in a usable state. And the finalizers are
> about cleaning up UDTs, not ATS resources.
>
> -----Original Message-----
> From: Walt Karas <wk...@yahooinc.com.INVALID>
> Sent: Wednesday, December 6, 2023 9:25 PM
> To: dev@trafficserver.apache.org
> Subject: Re: [E] [TSAPI] TSTxnAlloc
>
> Could we move Arena.h to tscpp/util, and just add:
>
> Arena & tsapi::txnArena(TSHttpTxn txn);
>
> For your finalizer example, when would that be better than using
> Cleanup.h? That is, when would it be better than having the vector be a
> data member of the TxnAuxData class you provide as a parameter to the
> TxnAuxDataMgr template?
>
RE: [E] [TSAPI] TSTxnAlloc
Posted by Alan Carroll <am...@network-geographics.com>.
"Arena.h" is scheduled for KIWF. This would be implemented using swoc::MemArena, which is already available to plugins. I am concerned about giving plugins direct access to the MemArena because I planned to use it internally in the HttpSM as well. I would be interested to
hear what others thinks about exposing the MemArena.
Internally the finalizers are implemented as an IntrusiveDList in the MemArena, which avoids having to create and cleanup TSInkCont instances. Also I want to avoid calling any plugin API (such as TSXXXDestroy) to avoid reliance on the HttpSM being in a usable state. And the finalizers are about cleaning up UDTs, not ATS resources.
-----Original Message-----
From: Walt Karas <wk...@yahooinc.com.INVALID>
Sent: Wednesday, December 6, 2023 9:25 PM
To: dev@trafficserver.apache.org
Subject: Re: [E] [TSAPI] TSTxnAlloc
Could we move Arena.h to tscpp/util, and just add:
Arena & tsapi::txnArena(TSHttpTxn txn);
For your finalizer example, when would that be better than using Cleanup.h? That is, when would it be better than having the vector be a data member of the TxnAuxData class you provide as a parameter to the TxnAuxDataMgr template?
Re: [E] [TSAPI] TSTxnAlloc
Posted by Walt Karas <wk...@yahooinc.com.INVALID>.
Could we move Arena.h to tscpp/util, and just add:
Arena & tsapi::txnArena(TSHttpTxn txn);
For your finalizer example, when would that be better than using
Cleanup.h? That is, when would it be better than having the vector be a
data member of the TxnAuxData class you provide as a parameter to the
TxnAuxDataMgr template?
On Wed, Dec 6, 2023 at 8:00 PM Alan Carroll <am...@network-geographics.com>
wrote:
> Proposed Transaction based memory allocation API
>
> TSTxnAlloc
> **********
>
> Traffic Server Transaction based memory allocation.
>
> Synopsis
> ========
>
> .. code-block:: cpp
>
> #include <ts/ts.h>
>
> .. function:: swoc::MemSpan<void> TSTxnAlloc(TSHttpTxn txn, size_t bytes)
> .. function:: swoc::MemSpan<void> TSTxnAllocAligned(TSHttpTxn txn, size_t
> bytes, size_t align)
> .. function:: template < typename T > T * TSTxnAllocInstance();
> .. function:: template < typename T > swoc::MemSpan<T>
> TSTxnAllocArray(size_t count);
> .. function:: swoc::TextView TSTxnLocalizeString(TSHttpTxn txn,
> swoc::TextView s)
> .. function:: swoc::TextView TSTxnLocalizeCString(TSHttpTxn txn, char
> const * s)
> .. function:: template < typename F > void TSTxnFinalize(TSHttpTxn txn, F
> && f)
>
> Description
> ===========
>
> These functions are used to allocate memory that has the same lifetime as
> a transaction. This has two differences from
> normal allocation which are frequently advantageous for plugins.
>
> * Allocation is much faster than :code:`malloc` or equivalent.
> * The memory is released at the end of the transaction automatically.
>
> The only function in this group that does not allocate is
> :func:`TSTxnFinalize`. Instead this provides a functor
> which is invoked just before the transaction local memory is released.
>
> :func:`TSTxnAlloc` allocates a block of memory of size :arg:`bytes`.
>
> :func:`TSTxnAllocAligned` allocates a block of memory of size :arg:`bytes`
> that is aligned at a multiple of :arg:`align`,
> which must be a power of 2.
>
> :func:`TSTxnAllocInstance` allocates an instance of a type :code:`T` with
> the required alignment for :arg:`T`,
> calls the default constructor for :code:`T`, and the returns the pointer.
>
> :func:`TSTxnAllocArray` allocates a block of memory of size and alignment
> to hold :arg:`count` instances of :code:`T`. These
> are not initialized / constructed.
>
> :func:`TSTxnLocalizeString` copies the string :arg:`s` to transaction
> local memory and returns a view of the copied string.
>
> :func:`TSTxnLocalizeCString` copies a C string (nul character terminated)
> :arg:`s` to transaction local memory and returns a view of the copied
> string.
>
> :func:`TSTxnFinalize` creates a finalizer for the transaction which are
> described in :ref:`finalizers`.
>
> Notes
> =====
>
> In general this memory should avoid referencing memory outside of
> transaction local memory. Strings are the archetype
> as a string is complete in itself and requires no cleanup beyond
> deallocation. For variable sized structures it is
> possible to use :code:`swoc::IntrusiveDList` to create lists which reside
> entirely in transaction local memory and
> therefore require no addtional cleanup.
>
> .. _finalizers::
>
> Finalizers
> ----------
>
> If cleanup is unavoidable then a :em:`finalizer` can be used. This is a
> functor that is invoked just before cleaning
> up transaction local memory which is intended to perform addtional
> cleanup. This imposes several restrictions
>
> * The finalizer itself must not require any cleanup beyond deallocation.
> One aspect is the functor instance must
> not contain any non-transaction local allocated memory.
> * The finalizer must only do allocation related cleanup. It must not call
> any TS plugion API calls. The transaction
> object is likely to be in an unusable state when the finalizer is
> invoked.
>
> For an example finalizer, suppose the allocation is used to hold a
> :code:`std::vector<size_t>`. Simply releasing the
> memory will leak the vector elements, so the vector must be destructed.
> This can be handled by a finalizer that looks
> like
>
> .. code-block:: cpp
>
> auto * vecp = TSTxnAllocInstance<std::vector<size_t>>(txn);
> TSTxnFinalizer(txn, [=]() -> void { delete vecp; });
>
> The pointer to the allocated vector is captured by the lambda and when the
> transaction local memory is released the
> vector contents are also released. Be very very careful or (better) avoid
> entirely capture by reference, as the target of the
> reference is likely to be long out of scope when the finalizer is invoked.
>
> See also
> ========
>
> :manpage:`TSAPI(3ts)`
> +
>